From 9257a01fd6a8d548828e5bd009a05dbe9fce9f41 Mon Sep 17 00:00:00 2001 From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org> Date: Mon, 27 Oct 1997 03:59:44 +0100 Subject: [PATCH] encodings/ directory added work on Image.GIF begun Rev: src/modules/Image/Makefile.in:1.6 Rev: src/modules/Image/colortable.c:1.9 Rev: src/modules/Image/colortable.h:1.1 Rev: src/modules/Image/configure.in:1.3 Rev: src/modules/Image/doc/Image.colortable.html:1.3 Rev: src/modules/Image/doc/Image.html:1.9 Rev: src/modules/Image/doc/Image.image.html:1.12 Rev: src/modules/Image/encodings/Makefile.in:1.1 Rev: src/modules/Image/encodings/configure.in:1.1 Rev: src/modules/Image/encodings/gif.c:1.1 Rev: src/modules/Image/encodings/gif_lzw.c:1.1 Rev: src/modules/Image/encodings/gif_lzw.h:1.1 Rev: src/modules/Image/image.c:1.48 --- .gitattributes | 2 + src/modules/Image/Makefile.in | 4 +- src/modules/Image/colortable.c | 149 +++--- src/modules/Image/colortable.h | 101 ++++ src/modules/Image/configure.in | 2 + src/modules/Image/doc/Image.colortable.html | 138 +++-- src/modules/Image/doc/Image.html | 34 +- src/modules/Image/doc/Image.image.html | 36 ++ src/modules/Image/encodings/Makefile.in | 33 ++ src/modules/Image/encodings/configure.in | 11 + src/modules/Image/encodings/gif.c | 535 ++++++++++++++++++++ src/modules/Image/encodings/gif_lzw.c | 18 + src/modules/Image/encodings/gif_lzw.h | 10 + src/modules/Image/image.c | 14 +- 14 files changed, 931 insertions(+), 156 deletions(-) create mode 100644 src/modules/Image/colortable.h create mode 100644 src/modules/Image/encodings/Makefile.in create mode 100644 src/modules/Image/encodings/configure.in create mode 100644 src/modules/Image/encodings/gif.c create mode 100644 src/modules/Image/encodings/gif_lzw.c create mode 100644 src/modules/Image/encodings/gif_lzw.h diff --git a/.gitattributes b/.gitattributes index 3040264f19..4ec7992e55 100644 --- a/.gitattributes +++ b/.gitattributes @@ -75,6 +75,8 @@ testfont binary /src/modules/Image/colortable.c foreign_ident /src/modules/Image/dct.c foreign_ident /src/modules/Image/doc/Image.html foreign_ident +/src/modules/Image/encodings/gif.c foreign_ident +/src/modules/Image/encodings/gif_lzw.c foreign_ident /src/modules/Image/font.c foreign_ident /src/modules/Image/illustration.pike foreign_ident /src/modules/Image/image.c foreign_ident diff --git a/src/modules/Image/Makefile.in b/src/modules/Image/Makefile.in index 6fd00a3b0b..948d8599b1 100644 --- a/src/modules/Image/Makefile.in +++ b/src/modules/Image/Makefile.in @@ -1,8 +1,10 @@ SRCDIR=@srcdir@ VPATH=@srcdir@:@srcdir@/../..:../.. OBJS = image.o font.o quant.o lzw.o togif.o matrix.o pnm.o blit.o \ - pattern.o dct.o operator.o x.o colortable.o polyfill.o + pattern.o dct.o operator.o x.o colortable.o polyfill.o MODNAME=image +MODULE_SUBDIRS=encodings +MODULE_ARCHIVES=encodings/gif.a MODULE_LDFLAGS=@LDFLAGS@ @SET_MAKE@ diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c index f94c54ebc6..153f718e09 100644 --- a/src/modules/Image/colortable.c +++ b/src/modules/Image/colortable.c @@ -1,11 +1,11 @@ #include <config.h> -/* $Id: colortable.c,v 1.8 1997/10/21 18:37:01 mirar Exp $ */ +/* $Id: colortable.c,v 1.9 1997/10/27 02:50:45 mirar Exp $ */ /* **! module Image **! note -**! $Id: colortable.c,v 1.8 1997/10/21 18:37:01 mirar Exp $<br> +**! $Id: colortable.c,v 1.9 1997/10/27 02:50:45 mirar Exp $<br> **! class colortable **! **! This object keeps colortable information, @@ -18,7 +18,7 @@ #undef COLORTABLE_REDUCE_DEBUG #include "global.h" -RCSID("$Id: colortable.c,v 1.8 1997/10/21 18:37:01 mirar Exp $"); +RCSID("$Id: colortable.c,v 1.9 1997/10/27 02:50:45 mirar Exp $"); #include <sys/types.h> #include <sys/stat.h> @@ -39,15 +39,14 @@ RCSID("$Id: colortable.c,v 1.8 1997/10/21 18:37:01 mirar Exp $"); #include "builtin_functions.h" #include "image.h" +#include "colortable.h" struct program *image_colortable_program; extern struct program *image_program; -typedef unsigned long nct_weight_t; #define WEIGHT_NEEDED (nct_weight_t)(0x10000000) #define WEIGHT_REMOVE (nct_weight_t)(0x10000001) -#define COLORLOOKUPCACHEHASHSIZE 207 #define COLORLOOKUPCACHEHASHR 7 #define COLORLOOKUPCACHEHASHG 17 #define COLORLOOKUPCACHEHASHB 1 @@ -73,91 +72,6 @@ typedef unsigned long nct_weight_t; #define SQ(x) ((x)*(x)) static INLINE int sq(int x) { return x*x; } -struct nct_flat_entry /* flat colorentry */ -{ - rgb_group color; - nct_weight_t weight; - signed long no; -}; - -struct nct_scale -{ - struct nct_scale *next; - rgb_group low,high; - rgbl_group vector; /* high-low */ - float invsqvector; /* |vector|² */ - INT32 realsteps; - int steps; - float mqsteps; /* 1.0/(steps-1) */ - int no[1]; /* actually no[steps] */ -}; - -struct neo_colortable -{ - enum nct_type - { - NCT_NONE, /* no colors */ - NCT_FLAT, /* flat with weight */ - NCT_CUBE /* cube with additions */ - } type; - enum nct_lookup_mode /* see union "lu" below */ - { - NCT_TREE, /* tree lookup */ - NCT_CUBICLES, /* cubicle lookup */ - NCT_FULL /* scan all values */ - } lookup_mode; - - union - { - struct nct_flat - { - int numentries; - struct nct_flat_entry *entries; - } flat; - struct nct_cube - { - nct_weight_t weight; - int r,g,b; /* steps of sides */ - struct nct_scale *firstscale; - INT32 disttrig; /* (sq) distance trigger */ - int numentries; - } cube; - } u; - - rgbl_group spacefactor; - /* rgb space factors, normally 2,3,1 */ - - struct lookupcache - { - rgb_group src; - rgb_group dest; - int index; - } lookupcachehash[COLORLOOKUPCACHEHASHSIZE]; - - union /* of pointers!! */ - { - struct nctlu_cubicles - { - int r,g,b; /* size */ - int accur; /* accuracy, default 2 */ - struct nctlu_cubicle - { - int n; - int *index; /* NULL if not initiated */ - } *cubicles; /* [r*g*b], index as [ri+(gi+bi*g)*r] */ - } cubicles; - struct nctlu_tree - { - struct nctlu_treenode - { - int splitvalue; - enum { SPLIT_R,SPLIT_G,SPLIT_B,SPLIT_DONE } split_direction; - int less,more; - } *nodes; /* shoule be colors×2 */ - } tree; - } lu; -}; - #define THIS ((struct neo_colortable *)(fp->current_storage)) #define THISOBJ (fp->current_object) @@ -1889,6 +1803,48 @@ void image_colortable_cast_to_array(INT32 args) free(flat.entries); } +int image_colortable_size(struct neo_colortable *nct) +{ + if (nct->type==NCT_FLAT) + return nct->u.flat.numentries; + else if (nct->type==NCT_CUBE) + return nct->u.cube.numentries; + else return 0; +} + +void image_colortable__sizeof(INT32 args) +{ + pop_n_elems(args); + push_int(image_colortable_size(THIS)); +} + +void image_colortable_write_rgb(struct neo_colortable *nct, + unsigned char *dest) +{ + struct nct_flat flat; + int i; + + if (nct->type==NCT_NONE) + return; + + if (nct->type==NCT_CUBE) + flat=_img_nct_cube_to_flat(nct->u.cube); + else + flat=nct->u.flat; + + /* sort in number order? */ + + for (i=0; i<flat.numentries; i++) + { + *(dest++)=flat.entries[i].color.r; + *(dest++)=flat.entries[i].color.g; + *(dest++)=flat.entries[i].color.b; + } + + if (nct->type==NCT_CUBE) + free(flat.entries); +} + /* **! method object cast(string to) **! cast the colortable to an array @@ -2078,7 +2034,7 @@ void image_colortable_cubicles(INT32 args) **! the lookup method, which may take time the first **! use of the colortable - the second use is quicker. **! -**! see also +**! see also: **! cubicle, tree, full **/ @@ -2718,6 +2674,13 @@ static void _img_nct_map_to_flat_tree(rgb_group *s, error("colortable->map(): map to flat/tree not implemented\n"); } +void image_colortable_get_index_line(struct neo_colortable *nct, + rgb_group *s, + unsigned char *buf, + int len) +{ +} + void image_colortable_map(INT32 args) { struct image *src; @@ -2851,6 +2814,10 @@ void init_colortable_programs(void) add_function("cast",image_colortable_cast, "function(string:array)",0); + /* info */ + add_function("_sizeof",image_colortable__sizeof, + "function(:int)",0); + /* modes */ add_function("tree",image_colortable_tree, "function(:object)",0); diff --git a/src/modules/Image/colortable.h b/src/modules/Image/colortable.h new file mode 100644 index 0000000000..9e72450d3f --- /dev/null +++ b/src/modules/Image/colortable.h @@ -0,0 +1,101 @@ +#define COLORLOOKUPCACHEHASHSIZE 207 + +typedef unsigned long nct_weight_t; + +struct nct_flat_entry /* flat colorentry */ +{ + rgb_group color; + nct_weight_t weight; + signed long no; +}; + +struct nct_scale +{ + struct nct_scale *next; + rgb_group low,high; + rgbl_group vector; /* high-low */ + float invsqvector; /* |vector|² */ + INT32 realsteps; + int steps; + float mqsteps; /* 1.0/(steps-1) */ + int no[1]; /* actually no[steps] */ +}; + +struct neo_colortable +{ + enum nct_type + { + NCT_NONE, /* no colors */ + NCT_FLAT, /* flat with weight */ + NCT_CUBE /* cube with additions */ + } type; + enum nct_lookup_mode /* see union "lu" below */ + { + NCT_TREE, /* tree lookup */ + NCT_CUBICLES, /* cubicle lookup */ + NCT_FULL /* scan all values */ + } lookup_mode; + + union + { + struct nct_flat + { + int numentries; + struct nct_flat_entry *entries; + } flat; + struct nct_cube + { + nct_weight_t weight; + int r,g,b; /* steps of sides */ + struct nct_scale *firstscale; + INT32 disttrig; /* (sq) distance trigger */ + int numentries; + } cube; + } u; + + rgbl_group spacefactor; + /* rgb space factors, normally 2,3,1 */ + + struct lookupcache + { + rgb_group src; + rgb_group dest; + int index; + } lookupcachehash[COLORLOOKUPCACHEHASHSIZE]; + + union /* of pointers!! */ + { + struct nctlu_cubicles + { + int r,g,b; /* size */ + int accur; /* accuracy, default 2 */ + struct nctlu_cubicle + { + int n; + int *index; /* NULL if not initiated */ + } *cubicles; /* [r*g*b], index as [ri+(gi+bi*g)*r] */ + } cubicles; + struct nctlu_tree + { + struct nctlu_treenode + { + int splitvalue; + enum { SPLIT_R,SPLIT_G,SPLIT_B,SPLIT_DONE } split_direction; + int less,more; + } *nodes; /* shoule be colors×2 */ + } tree; + } lu; +}; + + +/* exported methods */ + +void image_colortable_get_index_line(struct neo_colortable *nct, + rgb_group *s, + unsigned char *buf, + int len); + +int image_colortable_size(struct neo_colortable *nct); + +void image_colortable_write_rgb(struct neo_colortable *nct, + unsigned char *dest); diff --git a/src/modules/Image/configure.in b/src/modules/Image/configure.in index c45706f102..7184a2532a 100644 --- a/src/modules/Image/configure.in +++ b/src/modules/Image/configure.in @@ -11,6 +11,8 @@ AC_CHECK_HEADERS(sys/fcntl.h fcntl.h stdlib.h) AC_SUBST(RANLIB) +AC_CONFIG_SUBDIRS(encodings) + AC_OUTPUT(Makefile,echo FOO >stamp-h ) diff --git a/src/modules/Image/doc/Image.colortable.html b/src/modules/Image/doc/Image.colortable.html index 0bffac3c19..98be7b7ace 100644 --- a/src/modules/Image/doc/Image.colortable.html +++ b/src/modules/Image/doc/Image.colortable.html @@ -14,6 +14,48 @@ This object keeps colortable information, <tt><a href=Image.font.html>Image.font</a></tt> </blockquote> +<hr> +<a name=%60*> </a> +<a name=%60%60*> </a> +<a name=map> </a> +<h4>SYNOPSIS</h4> +<blockquote> +<tt>object <b>map</b>(object image)<br> +object <b>`*</b>(object image)<br> +object <b>``*</b>(object image)</tt> +</blockquote> + +<h4>DESCRIPTION</h4> + + +<blockquote> +Map colors in an image object to the colors in + the colortable, and creates a new image with the + closest colors. +</blockquote> +<h4>RETURNS</h4> + + +<blockquote> +a new image object +</blockquote> + + +<h4>NOTE</h4> +<blockquote> +Flat (not cube) colortable and not '<tt><a href=Image.colortable.html#full>full</a></tt>' method: + this method does figure out the data needed for + the lookup method, which may take time the first + use of the colortable - the second use is quicker. + +<p> cubicle, tree, full +</blockquote> + + +<h4>SEE ALSO</h4> +<blockquote> <tt><a href=Image.colortable.html#></a></tt> +</blockquote> + <hr> <a name=%60+> </a> <h4>SYNOPSIS</h4> @@ -75,11 +117,11 @@ void <b>create</b>(object(Image.image) image, int number)<br> void <b>create</b>(object(Image.image) image, int number, array(array(int)) needed)<br> void <b>create</b>(int r, int g, int b)<br> void <b>create</b>(int r, int g, int b, array(int) from1, array(int) to1, int steps1, ..., array(int) fromn, array(int) ton, int stepsn)<br> -void <b>add</b>(array(array(int)) colors)<br> -void <b>add</b>(object(Image.image) image, int number)<br> -void <b>add</b>(object(Image.image) image, int number, array(array(int)) needed)<br> -void <b>add</b>(int r, int g, int b)<br> -void <b>add</b>(int r, int g, int b, array(int) from1, array(int) to1, int steps1, ..., array(int) fromn, array(int) ton, int stepsn)</tt> +object <b>add</b>(array(array(int)) colors)<br> +object <b>add</b>(object(Image.image) image, int number)<br> +object <b>add</b>(object(Image.image) image, int number, array(array(int)) needed)<br> +object <b>add</b>(int r, int g, int b)<br> +object <b>add</b>(int r, int g, int b, array(int) from1, array(int) to1, int steps1, ..., array(int) fromn, array(int) ton, int stepsn)</tt> </blockquote> <h4>DESCRIPTION</h4> @@ -192,7 +234,8 @@ ignores argument (ie <tt>(string)colortable</tt> gives an array) <h4>SYNOPSIS</h4> <blockquote> <tt>object <b>cubicles</b>()<br> -object <b>cubicles</b>(int r, int g, int b)</tt> +object <b>cubicles</b>(int r, int g, int b)<br> +object <b>cubicles</b>(int r, int g, int b, int accuracy)</tt> </blockquote> <h4>DESCRIPTION</h4> @@ -216,7 +259,16 @@ Set the colortable to use the cubicles algorithm to lookup <p> example: <tt>colors=Image.colortable(img)->cubicles();</tt> -<p> algorithm time: between O[ln n] and O[n] +<p> algorithm time: between O[m] and O[m * n], + where n is numbers of colors and m is number of pixels + +<p> The arguments can be heavy trimmed for the usage + of your colortable; a large number (10×10×10 or bigger) + of cubicles is recommended when you use the colortable + repeatedly, since the calculation takes much + more time then usage. + +<p> In some cases, the <tt><a href=Image.colortable.html#full>full</a></tt> method is faster. </blockquote> <h4>ARGUMENTS</h4> <blockquote><dl> @@ -226,8 +278,14 @@ Set the colortable to use the cubicles algorithm to lookup <dd>Size, ie how much the colorspace is divided. Note that the size of each cubicle is at least about 8b, and that it takes time to calculate them. The number of - cubicles are <tt>r*g*b</tt>, and default is r=18, g=20, b=12, - ie 4320 cubicles. + cubicles are <tt>r*g*b</tt>, and default is 4,5,4, + ie 80 cubicles. This works good for 200±100 colors. +<dt><tt>int accuracy</tt> + <dd>Accuracy when checking sides of cubicles. + Default is 16. A value of 1 gives complete accuracy, + ie cubicle() method gives exactly the same result + as full(), but takes (in worst case) 16× the time + to calculate. </dl></blockquote> <h4>RETURNS</h4> @@ -260,7 +318,8 @@ Set the colortable to use full scan to lookup the closest color. <p> example: <tt>colors=Image.colortable(img)->full();</tt> -<p> algorithm time: O[n], where n is numbers of colors +<p> algorithm time: O[n*m], where n is numbers of colors + and m is number of pixels </blockquote> <h4>RETURNS</h4> @@ -276,72 +335,65 @@ Not applicable to colorcube types of colortable. </blockquote> <hr> -<a name=map> </a> +<a name=reduce> </a> <h4>SYNOPSIS</h4> <blockquote> -<tt>object <b>map</b>(object image)</tt> +<tt>object <b>reduce</b>(int colors)</tt> </blockquote> <h4>DESCRIPTION</h4> <blockquote> -Map colors in an image object to the colors in - the colortable, and creates a new image with the - closest colors. +reduces the number of colors + +<p> All needed (see <tt><a href=Image.colortable.html#create>create</a></tt>) colors are kept. </blockquote> <h4>ARGUMENTS</h4> <blockquote><dl> -<dt><tt>int r</tt> -<dt><tt>int g</tt> -<dt><tt>int b</tt> - <dd>Size, ie how much the colorspace is divided. - Note that the size of each cubicle is at least about 8b, - and that it takes time to calculate them. The number of - cubicles are <tt>r*g*b</tt>, and default is r=18, g=20, b=12, - ie 4320 cubicles. +<dt><tt>int colors</tt> + <dd>target number of colors </dl></blockquote> <h4>RETURNS</h4> <blockquote> -a new image object -</blockquote> - - -<h4>NOTE</h4> -<blockquote> -this method doesn't figure out the cubicles, this is - done on the first use of the colortable - -<p> Not applicable to colorcube types of colortable. +the new <ref>colortable</ref> object </blockquote> <hr> -<a name=reduce> </a> +<a name=spacefactors> </a> <h4>SYNOPSIS</h4> <blockquote> -<tt>object <b>reduce</b>(int colors)</tt> +<tt>object <b>spacefactors</b>(int r, int g, int b)</tt> </blockquote> <h4>DESCRIPTION</h4> <blockquote> -reduces the number of colors +Colortable tuning option, this sets the color space + distance factors. This is used when comparing distances + in the colorspace and comparing grey levels. -<p> All needed (see <tt><a href=Image.colortable.html#create>create</a></tt>) colors are kept. +<p> Default factors are 2, 3 and 1; blue is much + darker than green. Compare with <tt><a href=Image.image.html#grey>Image.image::grey</a></tt>(). </blockquote> -<h4>ARGUMENTS</h4> -<blockquote><dl> -<dt><tt>int colors</tt> - <dd>target number of colors -</dl></blockquote> <h4>RETURNS</h4> <blockquote> -the new <ref>colortable</ref> object +the called object +</blockquote> + + +<h4>NOTE</h4> +<blockquote> +This has no sanity check. Some functions may bug + if the factors are to high - color reduction functions + sums grey levels in the image, this could exceed maxint + in the case of high factors. Negative values may + also cause strange effects. *grin* </blockquote> <hr> diff --git a/src/modules/Image/doc/Image.html b/src/modules/Image/doc/Image.html index 389d650363..2907bac2d8 100644 --- a/src/modules/Image/doc/Image.html +++ b/src/modules/Image/doc/Image.html @@ -10,23 +10,23 @@ This module adds image-drawing and -manipulating <h4>NOTE</h4> <blockquote> -$Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - -<p> $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> - $Id: Image.html,v 1.8 1997/10/12 21:07:28 mirar Exp $<br> +$Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + +<p> $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> + $Id: Image.html,v 1.9 1997/10/27 02:50:50 mirar Exp $<br> </blockquote> diff --git a/src/modules/Image/doc/Image.image.html b/src/modules/Image/doc/Image.image.html index 35ff02610e..e24692d206 100644 --- a/src/modules/Image/doc/Image.image.html +++ b/src/modules/Image/doc/Image.image.html @@ -2023,6 +2023,42 @@ This function is new (april-97) and rather untested. <tt><a href=Image.image.html#setcolor>setcolor</a></tt> </blockquote> +<hr> +<a name=read_lsb_grey> </a> +<a name=read_lsb_rgb> </a> +<a name=write_lsb_grey> </a> +<a name=write_lsb_rgb> </a> +<h4>SYNOPSIS</h4> +<blockquote> +<tt>object <b>write_lsb_rgb</b>(string what)<br> +object <b>write_lsb_grey</b>(string what)<br> +string <b>read_lsb_rgb</b>()<br> +string <b>read_lsb_grey</b>()</tt> +</blockquote> + +<h4>DESCRIPTION</h4> + + +<blockquote> +These functions read/write in the least significant bit + of the image pixel values. The _rgb() functions + read/write on each of the red, green and blue values, + and the grey keeps the same lsb on all three. + +<p> The string is nullpadded or cut to fit. +</blockquote> +<h4>ARGUMENTS</h4> +<blockquote><dl> +<dt><tt>string what</tt> + <dd>the hidden message +</dl></blockquote> +<h4>RETURNS</h4> + + +<blockquote> +the current object or the read string +</blockquote> + <hr> <a name=rotate> </a> <a name=rotate_expand> </a> diff --git a/src/modules/Image/encodings/Makefile.in b/src/modules/Image/encodings/Makefile.in new file mode 100644 index 0000000000..9813a22d67 --- /dev/null +++ b/src/modules/Image/encodings/Makefile.in @@ -0,0 +1,33 @@ +SRCDIR=@srcdir@ +VPATH=@srcdir@:@srcdir@/../../..:../../.. +GIF_OBJS = gif.o gif_lzw.o +OBJS=gif.a + +@SET_MAKE@ + +CC=@CC@ +CPP=@CPP@ + +PREFLAGS=-I. -I$(SRCDIR) -I$(SRCDIR)/../../.. -I$(SRCDIR)/.. -I../../.. -I.. -I. $(MODULE_CPPFLAGS) $(DEFINES) +CFLAGS=$(PREFLAGS) $(OTHERFLAGS) $(MODULE_CFLAGS) #@CCSHARED@ + +all: $(OBJS) + +gif.a : $(GIF_OBJS) + rm -f gif.a + ar cq gif.a $(GIF_OBJS) + $(RANLIB) gif.a + +depend: + gcc -MM $(PREFLAGS) $(SRCDIR)/*.c | $(TMP_BINDIR)/fixdepends.sh $(SRCDIR) + +clean: + -rm -f *.o *.a *.so module.so + +pike: all + cd ../../..; $(MAKE) + +pure: all + cd ../../..; $(MAKE) pure + +@dependencies@ diff --git a/src/modules/Image/encodings/configure.in b/src/modules/Image/encodings/configure.in new file mode 100644 index 0000000000..8bd063f6c1 --- /dev/null +++ b/src/modules/Image/encodings/configure.in @@ -0,0 +1,11 @@ +AC_INIT(gif.c) + +AC_SET_MAKE + +sinclude(../../module_configure.in) + +AC_SUBST(RANLIB) + +AC_OUTPUT(Makefile,echo FOO >stamp-h ) + + diff --git a/src/modules/Image/encodings/gif.c b/src/modules/Image/encodings/gif.c new file mode 100644 index 0000000000..8e3618fbe6 --- /dev/null +++ b/src/modules/Image/encodings/gif.c @@ -0,0 +1,535 @@ +/* $Id: gif.c,v 1.1 1997/10/27 02:50:54 mirar Exp $ */ + +/* +**! module Image +**! note +**! $Id: gif.c,v 1.1 1997/10/27 02:50:54 mirar Exp $ +**! +**! submodule GIF +**! +**! This submodule keep the GIF encode/decode capabilities +**! of the <ref>Image</ref> module. +**! +**! GIF is a common image storage format, +**! usable for a limited color palette - a GIF image can +**! only contain as most 256 colors - and animations. +**! +**! see also: Image, Image.image, Image.colortable +*/ + +#include <math.h> +#include <ctype.h> + +#include "stralloc.h" +#include "global.h" +RCSID("$Id: gif.c,v 1.1 1997/10/27 02:50:54 mirar Exp $"); +#include "pike_macros.h" +#include "object.h" +#include "constants.h" +#include "interpret.h" +#include "svalue.h" +#include "threads.h" +#include "array.h" +#include "error.h" + + +#include "image.h" +#include "colortable.h" +#include "builtin_functions.h" + +#include "gif_lzw.h" + +extern struct program *image_colortable_program; +extern struct program *image_program; + +extern void f_add(INT32 args); + +/* + +goal: + +string encode(object img); +string encode(object img,int colors); +string encode(object img,object colortable); + Simply make a complete GIF file. + +string encode_transparent(object img,object alpha); +string encode_transparent(object img,object alpha,int r,int g,int b); +string encode_transparent(object img,int colors,int r,int g,int b); +string encode_transparent(object img,int colors,object alpha,int r,int g,int b); +string encode_transparent(object img,object colortable,object alpha); +string encode_transparent(object img,object colortable,object alpha,int r,int g,int b); +string encode_transparent(object img,object colortable,int transp_index); + Simply make a complete GIF file with transparency; + Transparency is taken from the given alpha mask + (black=transparent), the color closest(!) to the given, or + by the given index in the colortable. The following r,g,b + values gives the possibility of setting the transparent color + (some decoders ignore the transparency). + +object decode(string data); + Decode GIF data to one (!) image object. + +object decode_alpha(string data); + Decode GIF alpha channel to an image object. + black marks transparent, white marks full opaque. + +advanced: + +string header_block(object img,object colortable,int noglobalpalette); +string header_block(object img,int numcol,int noglobalpalette); +string end_block(); +string transparency_block(int no); +string delay_block(int centiseconds); +string netscape_loop_block(void|int number_of_loops); + +string image_block(int x,int y,object img,object colortable,int nolocalpalette,int transp_index); +string image_block(int x,int y,object img,object colortable,object|int alpha,int nolocalpalette); +string image_block(int x,int y,object img,object colortable,object|int alpha,int nolocalpalette,int r,int g,int b); + +string _function_block(int function,string data); + +array _decode(string data); +: int xsize, int ysize, int numcol, 0|object colortable, +: (not in absolut order:) +: ({ int x, int y, object image, 0|object alpha, object colortable, +: int transparency, int transparency_index, +: int user_input, int disposal, int delay, +: string data}), +: ({ int major, int minor, string data }), + +string _encode(array data); + + */ + +/* +**! method string _gce_block(int transparency,int transparency_index,int delay,int user_input,int disposal); +**! +**! This function gives back a Graphic Control Extension block, +**! normally placed before an render block. +**! +**! arg int transparency +**! arg int transparency_index +**! The following image has transparency, marked with this index. +**! arg int delay +**! View the following rendering for this many centiseconds (0..65535). +**! arg int user_input +**! Wait the delay or until user input. If delay is zero, +**! wait indefinitely for user input. May sound the bell +**! upon decoding. +**! arg int disposal +**! Disposal method number; +**! <dl compact> +**! <dt>0<dd>No disposal specified. The decoder is +**! not required to take any action. +**! <dt>1<dd>Do not dispose. The graphic is to be left +**! in place. +**! <dt>2<dd>Restore to background color. The area used by the +**! graphic must be restored to the background color. +**! <dt>3<dd>Restore to previous. The decoder is required to +**! restore the area overwritten by the graphic with +**! what was there prior to rendering the graphic. +**! <dt compact>4-7<dd>To be defined. +**! </dl> +**! +**! note +**! This is in the very advanced sector of the GIF support; +**! please read about how GIFs file works. +**! +**! Most decoders just ignore some or all of these parameters. +*/ + +void image_gif__gce_block(INT32 args) +{ + char buf[20]; + if (args<5) + error("Image.GIF._gce_block(): too few arguments\n"); + if (sp[-args].type!=T_INT || + sp[1-args].type!=T_INT || + sp[2-args].type!=T_INT || + sp[3-args].type!=T_INT || + sp[4-args].type!=T_INT) + error("Image.GIF._gce_block(): Illegal argument(s)\n"); + sprintf(buf,"%c%c%c%c%c%c%c%c", + 0x21, /* extension intruder */ + 0xf9, /* gce extension */ + 4, /* block size */ + (((sp[4-args].u.integer & 7)<<2) /* disposal */ + | ((!!sp[3-args].u.integer)<<1) /* user input */ + | (!!sp[-args].u.integer)), /* transparency */ + sp[2-args].u.integer & 255, /* delay, ls8 */ + (sp[2-args].u.integer>>8) & 255, /* delay, ms8 */ + sp[1-args].u.integer & 255, /* transparency index */ + 0 /* end block */ + ); + + pop_n_elems(args); + push_string(make_shared_binary_string(buf,8)); +} +/* +**! method string render_block(object img,object colortable,int x,int y,int localpalette); +**! method string render_block(object img,object colortable,int x,int y,int localpalette,int transp_index); +**! method string render_block(object img,object colortable,int x,int y,int localpalette,object alpha); +**! method string render_block(object img,object colortable,int x,int y,int localpalette,object alpha,int r,int g,int b); +**! method string render_block(object img,object colortable,int x,int y,int localpalette,int transp_index,int interlace,int delay,int user_input,int disposal); +**! method string render_block(object img,object colortable,int x,int y,int localpalette,object alpha,int r,int g,int b,int interlace,int delay,int user_input,int disposal); +**! +**! This function gives a image block for placement in a GIF file, +**! with or without transparency. +**! The some options actually gives two blocks, +**! the first with graphic control extensions for such things +**! as delay or transparency. +**! +**! object img +**! The image. +**! object colortable +**! Colortable with colors to use and to write as palette. +**! arg int x +**! arg int y +**! Position of this image. +**! int localpalette +**! If set, writes a local palette. +**! int transp_index +**! Index of the transparent color in the colortable. +**! <tt>-1</tt> indicates no transparency. +**! object alpha +**! Alpha channel image; black is transparent. +**! int r +**! int g +**! int b +**! Color of transparent pixels. Not all decoders understands +**! transparency. +**! arg int delay +**! View this image for this many centiseconds. Default is zero. +**! arg int user_input +**! If set: wait the delay or until user input. If delay is zero, +**! wait indefinitely for user input. May sound the bell +**! upon decoding. Default is non-set. +**! arg int disposal +**! Disposal method number; +**! <dl compact> +**! <dt>0<dd>No disposal specified. The decoder is +**! not required to take any action. (default) +**! <dt>1<dd>Do not dispose. The graphic is to be left +**! in place. +**! <dt>2<dd>Restore to background color. The area used by the +**! graphic must be restored to the background color. +**! <dt>3<dd>Restore to previous. The decoder is required to +**! restore the area overwritten by the graphic with +**! what was there prior to rendering the graphic. +**! <dt compact>4-7<dd>To be defined. +**! </dl> +**! +**! see also: +**! encode, _encode, header_block, end_block +**! +**! note +**! This is in the advanced sector of the GIF support; +**! please read some about how GIFs are packed. +**! +**! The user_input and disposal method are unsupported +**! in most decoders. +*/ + +int image_gif_add_line(struct neo_colortable *nct, + struct gif_lzw *lzw, + rgb_group *s, + rgb_group *m, + int len, + int alphaidx) +{ + unsigned char *buf=alloca(len); + int n; + unsigned char *bd; + + image_colortable_get_index_line(nct,s,buf,len); + + if (m) + { + n=len; + bd=buf; + while (n--) + { + if (!(m->r||m->g||m->b)) *bd=alphaidx; + m++; + bd++; + } + } + + return image_gif_lzw_add(lzw,buf,len); +} + +void image_gif_render_block(INT32 args) +{ + struct image *img,*alpha=NULL; + struct neo_colortable *nct; + int numcolors; + int localpalette,xpos,ypos; + int alphaidx=-1; + rgb_group alphacolor; + int alphaentry=0; + int transparency; + int n; + int delay=0; + int user_input=0; + int disposal=0; + int numstrings=0; + int interlace=0; + int bpp; + struct pike_string *ps; + + unsigned char *indexbuf; + unsigned char buf[20]; + + int y,xs,ys; + rgb_group *img_s,*alpha_s=NULL; + struct gif_lzw lzw; + + if (args<2) + error("Image.GIF.render_block(): Too few arguments\n"); + if (sp[-args].type!=T_OBJECT || + !(img=(struct image*)get_storage(sp[-args].u.object,image_program))) + error("Image.GIF.render_block(): Illegal argument 1 (expected image object)\n"); + else if (!img->img) + error("Image.GIF.render_block(): given image has no image\n"); + if (sp[1-args].type!=T_OBJECT || + !(nct=(struct neo_colortable*) + get_storage(sp[1-args].u.object,image_colortable_program))) + error("Image.GIF.render_block(): Illegal argument 2 (expected colortable object)\n"); + + if (args>=4) + { + if (sp[2-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument 3 (expected int)\n"); + if (sp[3-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument 4 (expected int)\n"); + xpos=sp[2-args].u.integer; + ypos=sp[3-args].u.integer; + } + else xpos=ypos=0; + + numcolors=image_colortable_size(nct); + if (numcolors==0) + error("Image.GIF.render_block(): no colors in colortable\n"); + else if (numcolors>256) + error("Image.GIF.render_block(): too many colors in colortable (256 is max)\n"); + + if (args>=5) + { + if (sp[4-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument 5 (expected int)\n"); + localpalette=sp[3-args].u.integer; + } + else localpalette=0; + if (args>=6) + { + if (sp[5-args].type==T_INT) + { + alphaidx=sp[5-args].u.integer; + alpha=0; + alphaentry=0; + if (alphaidx!=-1 && numcolors<=alphaidx) + error("Image.GIF.render_block(): illegal index to transparent color\n"); + n=6; + } + else if (sp[5-args].type==T_OBJECT && + (alpha=(struct image*)get_storage(sp[-args].u.object,image_program))) + { + if (!alpha->img) + error("Image.GIF.render_block(): given alpha channel has no image\n"); + else if (alpha->xsize != img->xsize || + alpha->ysize != img->ysize) + error("Image.GIF.render_block(): given alpha channel differ in size from given image\n"); + alphaidx=numcolors; + alphaentry=1; + if (numcolors>255) + error("Image.GIF.render_block(): too many colors in colortable (255 is max, need one for transparency)\n"); + n=9; + + alphacolor.r=alphacolor.g=alphacolor.b=0; + if (args>=9) + { + if (sp[6-args].type!=T_INT || + sp[7-args].type!=T_INT || + sp[8-args].type!=T_INT) + error("Image.GIF.render_block(): illegal argument 7..9 (expected int)\n"); + alphacolor.r=(unsigned char)(sp[6-args].u.integer); + alphacolor.g=(unsigned char)(sp[7-args].u.integer); + alphacolor.b=(unsigned char)(sp[8-args].u.integer); + } + } + else + error("Image:GIF.render_block(): Illegal argument 6 (expected int or image object)\n"); + if (alphaidx!=-1) transparency=1; else transparency=0; + + if (args>n) /* interlace and gce arguments */ + { + if (args>n) + if (sp[n-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument %d (expected int)\n",n+1); + else + interlace=!!sp[n-args].u.integer; + n++; + if (args>n) + if (sp[n-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument %d (expected int)\n",n+1); + else + delay=sp[n-args].u.integer; + n++; + if (args>n) + if (sp[n-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument %d (expected int)\n",n+1); + else + user_input=!!sp[n-args].u.integer; + n++; + if (args>n) + if (sp[n-args].type!=T_INT) + error("Image:GIF.render_block(): Illegal argument %d (expected int)\n",n+1); + else + disposal=sp[n-args].u.integer&7; + } + } + else + transparency=0; + + bpp=1; + while ((1<<bpp)<numcolors+alphaentry) bpp++; + if (alphaentry) alphaidx=(1<<bpp)-1; + +/*** write GCE if needed */ + + if (transparency || delay || user_input || disposal) + /* write gce control block */ + { + push_int(transparency); + push_int(alphaidx); + push_int(delay); + push_int(user_input); + push_int(disposal); + image_gif__gce_block(5); + numstrings++; + } + +/*** write image rendering header */ + + sprintf(buf,"%c%c%c%c%c%c%c%c%c%c", + 0x2c, /* render block initiator */ + xpos&255, (xpos>>8)&255, /* left position */ + ypos&255, (ypos>>8)&255, /* top position */ + img->xsize&255, (img->xsize>>8)&255, /* width */ + img->ysize&255, (img->ysize>>8)&255, /* height */ + /* packed field */ + ((localpalette<<7) + | (interlace<<6) + | (0 <<5) /* palette is sorted, most used first */ + | ((bpp)-1)) /* palette size = 2^bpp */ + ); + push_string(make_shared_binary_string(buf,10)); + numstrings++; + +/*** write local palette if needed */ + + if (localpalette) + { + ps=begin_shared_string((1<<bpp)*3); + image_colortable_write_rgb(nct,ps->str); + MEMSET(ps->str+numcolors*3,0,((1<<bpp)-numcolors)*3); + if (alphaentry) + { + ps->str[3*alphaentry+0]=alphacolor.r; + ps->str[3*alphaentry+1]=alphacolor.g; + ps->str[3*alphaentry+2]=alphacolor.b; + } + push_string(end_shared_string(ps)); + numstrings++; + } + +/*** write the image */ + + /* write lzw minimum code size */ + if (bpp<2) + sprintf(buf,"%c",2); + else + sprintf(buf,"%c",bpp); + + push_string(make_shared_binary_string(buf,1)); + numstrings++; + + numstrings+=image_gif_lzw_init(&lzw,bpp<2?2:bpp); + + xs=img->xsize; + ys=img->ysize; + img_s=img->img; + if (alpha) alpha_s=alpha->img; + + if (interlace) + { + /* interlace: + row 0, 8, 16, ... + row 4, 12, 20, ... + row 2, 6, 10, ... + row 1, 3, 5, 7, ... */ + + for (y=0; y<ys; y+=8) + numstrings+=image_gif_add_line(nct,&lzw,img_s+xs*y, + alpha?alpha_s+xs*y:NULL,xs,alphaidx); + for (y=4; y<ys; y+=8) + numstrings+=image_gif_add_line(nct,&lzw,img_s+xs*y, + alpha?alpha_s+xs*y:NULL,xs,alphaidx); + for (y=2; y<ys; y+=4) + numstrings+=image_gif_add_line(nct,&lzw,img_s+xs*y, + alpha?alpha_s+xs*y:NULL,xs,alphaidx); + for (y=1; y<ys; y+=2) + numstrings+=image_gif_add_line(nct,&lzw,img_s+xs*y, + alpha?alpha_s+xs*y:NULL,xs,alphaidx); + } + else + { + y=ys; + if (!alpha) alpha_s=NULL; + while (y--) + { + numstrings+=image_gif_add_line(nct,&lzw,img_s,alpha_s,xs,alphaidx); + if (alpha) alpha_s+=xs; + img_s+=xs; + } + } + + numstrings+=image_gif_lzw_finish(&lzw); + +/*** done */ + + f_add(numstrings); + + (ps=sp[-1].u.string)->refs++; + + pop_n_elems(args+1); + push_string(ps); +} + +struct program *image_gif_module_program=NULL; + +void init_image_gif() +{ + start_new_program(); + + add_function("render_block",image_gif_render_block, + "function(object,object,void|int,void|int,void|int,void|object,void|int,void|int,void|int,void|int,void|int,void|int,void|int:string)" + "|function(object,object,void|int,void|int,void|int,void|int,void|int,void|int,void|int,void|int:string)",0); + add_function("_gce_block",image_gif__gce_block, + "function(int,int,int,int,int:string)",0); + + image_gif_module_program=end_program(); + push_object(clone_object(image_gif_module_program,0)); + add_constant(make_shared_string("GIF"),sp-1,0); + pop_stack(); +} + +void exit_image_gif() +{ + if(image_gif_module_program) + { + free_program(image_gif_module_program); + image_gif_module_program=0; + } +} diff --git a/src/modules/Image/encodings/gif_lzw.c b/src/modules/Image/encodings/gif_lzw.c new file mode 100644 index 0000000000..6b60e41f19 --- /dev/null +++ b/src/modules/Image/encodings/gif_lzw.c @@ -0,0 +1,18 @@ +/* $Id: gif_lzw.c,v 1.1 1997/10/27 02:50:55 mirar Exp $ */ + +#include "gif_lzw.h" + +int image_gif_lzw_init(struct gif_lzw *lzw,int bpp) +{ + return 0; +} + +int image_gif_lzw_add(struct gif_lzw *lzw,unsigned char *data,int len) +{ + return 0; +} + +int image_gif_lzw_finish(struct gif_lzw *lzw) +{ + return 0; +} diff --git a/src/modules/Image/encodings/gif_lzw.h b/src/modules/Image/encodings/gif_lzw.h new file mode 100644 index 0000000000..8cd60f0f35 --- /dev/null +++ b/src/modules/Image/encodings/gif_lzw.h @@ -0,0 +1,10 @@ + +struct gif_lzw +{ +}; + +/* returns number of strings written on stack */ + +int image_gif_lzw_init(struct gif_lzw *lzw,int bits); +int image_gif_lzw_add(struct gif_lzw *lzw,unsigned char *data,int len); +int image_gif_lzw_finish(struct gif_lzw *lzw); diff --git a/src/modules/Image/image.c b/src/modules/Image/image.c index 6e780eda99..2c1ba7ea14 100644 --- a/src/modules/Image/image.c +++ b/src/modules/Image/image.c @@ -1,4 +1,4 @@ -/* $Id: image.c,v 1.47 1997/10/25 17:47:52 grubba Exp $ */ +/* $Id: image.c,v 1.48 1997/10/27 02:50:48 mirar Exp $ */ /* **! module Image @@ -6,7 +6,7 @@ **! This module adds image-drawing and -manipulating **! capabilities to pike. **! note -**! $Id: image.c,v 1.47 1997/10/25 17:47:52 grubba Exp $<br> +**! $Id: image.c,v 1.48 1997/10/27 02:50:48 mirar Exp $<br> **! see also: Image.font, Image.image **! **! class image @@ -107,7 +107,7 @@ #include "stralloc.h" #include "global.h" -RCSID("$Id: image.c,v 1.47 1997/10/25 17:47:52 grubba Exp $"); +RCSID("$Id: image.c,v 1.48 1997/10/27 02:50:48 mirar Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -2865,9 +2865,11 @@ void image_read_lsb_grey(INT32 args) #define RGB_TYPE "int|void,int|void,int|void,int|void" void init_font_programs(void); -void init_colortable_programs(void); void exit_font(void); +void init_colortable_programs(void); void exit_colortable(void); +void init_image_gif(void); +void exit_image_gif(void); void pike_module_init(void) { @@ -3073,6 +3075,8 @@ void pike_module_init(void) init_font_programs(); init_colortable_programs(); + + init_image_gif(); } void pike_module_exit(void) @@ -3084,6 +3088,8 @@ void pike_module_exit(void) } exit_font(); exit_colortable(); + + exit_image_gif(); } -- GitLab