7 image.c - implements most of the basic functions of Imager and much of the rest
13 c = i_color_new(red, green, blue, alpha);
21 image.c implements the basic functions to create and destroy image and
22 color objects for Imager.
24 =head1 FUNCTION REFERENCE
26 Some of these functions are internal.
37 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) )
39 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
40 static void fake(void) { ceil(1); }
42 static int i_ppix_d(i_img *im, int x, int y, const i_color *val);
43 static int i_gpix_d(i_img *im, int x, int y, i_color *val);
44 static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
45 static int i_plin_d(i_img *im, int l, int r, int y, const i_color *vals);
46 static int i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val);
47 static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
48 static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
49 static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals);
50 static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
51 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
52 /*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
53 static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
56 =item ICL_new_internal(r, g, b, a)
58 Return a new color object with values passed to it.
60 r - red component (range: 0 - 255)
61 g - green component (range: 0 - 255)
62 b - blue component (range: 0 - 255)
63 a - alpha component (range: 0 - 255)
69 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
72 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
74 if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
79 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
85 =item ICL_set_internal(cl, r, g, b, a)
87 Overwrite a color with new values.
89 cl - pointer to color object
90 r - red component (range: 0 - 255)
91 g - green component (range: 0 - 255)
92 b - blue component (range: 0 - 255)
93 a - alpha component (range: 0 - 255)
99 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
100 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
102 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
103 i_fatal(2,"malloc() error\n");
108 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
114 =item ICL_add(dst, src, ch)
116 Add src to dst inplace - dst is modified.
118 dst - pointer to destination color object
119 src - pointer to color object that is added
120 ch - number of channels
126 ICL_add(i_color *dst,i_color *src,int ch) {
129 tmp=dst->channel[i]+src->channel[i];
130 dst->channel[i]= tmp>255 ? 255:tmp;
137 Dump color information to log - strictly for debugging.
139 cl - pointer to color object
145 ICL_info(i_color const *cl) {
146 mm_log((1,"i_color_info(cl* %p)\n",cl));
147 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
153 Destroy ancillary data for Color object.
155 cl - pointer to color object
161 ICL_DESTROY(i_color *cl) {
162 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
167 =item i_fcolor_new(double r, double g, double b, double a)
171 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
174 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
176 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
181 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
187 =item i_fcolor_destroy(i_fcolor *cl)
191 void i_fcolor_destroy(i_fcolor *cl) {
196 =item IIM_base_8bit_direct (static)
198 A static i_img object used to initialize direct 8-bit per sample images.
202 static i_img IIM_base_8bit_direct =
204 0, /* channels set */
205 0, 0, 0, /* xsize, ysize, bytes */
208 i_direct_type, /* type */
211 { 0, 0, NULL }, /* tags */
214 i_ppix_d, /* i_f_ppix */
215 i_ppixf_d, /* i_f_ppixf */
216 i_plin_d, /* i_f_plin */
217 i_plinf_d, /* i_f_plinf */
218 i_gpix_d, /* i_f_gpix */
219 i_gpixf_d, /* i_f_gpixf */
220 i_glin_d, /* i_f_glin */
221 i_glinf_d, /* i_f_glinf */
222 i_gsamp_d, /* i_f_gsamp */
223 i_gsampf_d, /* i_f_gsampf */
227 NULL, /* i_f_addcolors */
228 NULL, /* i_f_getcolors */
229 NULL, /* i_f_colorcount */
230 NULL, /* i_f_maxcolors */
231 NULL, /* i_f_findcolor */
232 NULL, /* i_f_setcolors */
234 NULL, /* i_f_destroy */
237 /*static void set_8bit_direct(i_img *im) {
238 im->i_f_ppix = i_ppix_d;
239 im->i_f_ppixf = i_ppixf_d;
240 im->i_f_plin = i_plin_d;
241 im->i_f_plinf = i_plinf_d;
242 im->i_f_gpix = i_gpix_d;
243 im->i_f_gpixf = i_gpixf_d;
244 im->i_f_glin = i_glin_d;
245 im->i_f_glinf = i_glinf_d;
248 im->i_f_addcolor = NULL;
249 im->i_f_getcolor = NULL;
250 im->i_f_colorcount = NULL;
251 im->i_f_findcolor = NULL;
255 =item IIM_new(x, y, ch)
257 =item i_img_8_new(x, y, ch)
259 =category Image creation/destruction
261 =synopsis i_img *img = i_img_8_new(width, height, channels);
263 Creates a new image object I<x> pixels wide, and I<y> pixels high with
271 IIM_new(int x,int y,int ch) {
273 mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
275 im=i_img_empty_ch(NULL,x,y,ch);
277 mm_log((1,"(%p) <- IIM_new\n",im));
283 IIM_DESTROY(i_img *im) {
284 mm_log((1,"IIM_DESTROY(im* %p)\n",im));
292 Create new image reference - notice that this isn't an object yet and
293 this should be fixed asap.
303 mm_log((1,"i_img_struct()\n"));
304 if ( (im=mymalloc(sizeof(i_img))) == NULL)
305 i_fatal(2,"malloc() error\n");
307 *im = IIM_base_8bit_direct;
315 mm_log((1,"(%p) <- i_img_struct\n",im));
320 =item i_img_empty(im, x, y)
322 Re-new image reference (assumes 3 channels)
325 x - xsize of destination image
326 y - ysize of destination image
328 **FIXME** what happens if a live image is passed in here?
330 Should this just call i_img_empty_ch()?
336 i_img_empty(i_img *im,int x,int y) {
337 mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
338 return i_img_empty_ch(im, x, y, 3);
342 =item i_img_empty_ch(im, x, y, ch)
344 Re-new image reference
347 x - xsize of destination image
348 y - ysize of destination image
349 ch - number of channels
355 i_img_empty_ch(i_img *im,int x,int y,int ch) {
358 mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
360 if (x < 1 || y < 1) {
361 i_push_error(0, "Image sizes must be positive");
364 if (ch < 1 || ch > MAXCHANNELS) {
365 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
368 /* check this multiplication doesn't overflow */
370 if (bytes / y / ch != x) {
371 i_push_errorf(0, "integer overflow calculating image allocation");
376 if ( (im=mymalloc(sizeof(i_img))) == NULL)
377 i_fatal(2,"malloc() error\n");
379 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
380 i_tags_new(&im->tags);
384 im->ch_mask = MAXINT;
386 if ( (im->idata=mymalloc(im->bytes)) == NULL)
387 i_fatal(2,"malloc() error\n");
388 memset(im->idata,0,(size_t)im->bytes);
392 mm_log((1,"(%p) <- i_img_empty_ch\n",im));
397 =item i_img_exorcise(im)
407 i_img_exorcise(i_img *im) {
408 mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
409 i_tags_destroy(&im->tags);
411 (im->i_f_destroy)(im);
412 if (im->idata != NULL) { myfree(im->idata); }
418 im->i_f_ppix=i_ppix_d;
419 im->i_f_gpix=i_gpix_d;
420 im->i_f_plin=i_plin_d;
421 im->i_f_glin=i_glin_d;
426 =item i_img_destroy(img)
428 =category Image creation/destruction
429 =synopsis i_img_destroy(img)
431 Destroy an image object
437 i_img_destroy(i_img *im) {
438 mm_log((1,"i_img_destroy(im %p)\n",im));
440 if (im) { myfree(im); }
444 =item i_img_info(im, info)
448 Return image information
451 info - pointer to array to return data
453 info is an array of 4 integers with the following values:
458 info[3] - channel mask
465 i_img_info(i_img *im,int *info) {
466 mm_log((1,"i_img_info(im 0x%x)\n",im));
468 mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
469 mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
472 info[2] = im->channels;
473 info[3] = im->ch_mask;
483 =item i_img_setmask(im, ch_mask)
485 =synopsis // only channel 0 writeable
486 =synopsis i_img_setmask(img, 0x01);
488 Set the image channel mask for I<im> to I<ch_mask>.
493 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
497 =item i_img_getmask(im)
499 =synopsis mask = i_img_getmask(img);
501 Get the image channel mask for I<im>.
506 i_img_getmask(i_img *im) { return im->ch_mask; }
509 =item i_img_getchannels(im)
511 =synopsis channels = i_img_getchannels(img);
513 Get the number of channels in I<im>.
518 i_img_getchannels(i_img *im) { return im->channels; }
521 =item i_img_get_width(im)
523 =synopsis width = i_img_get_width(im);
525 Returns the width in pixels of the image.
530 i_img_get_width(i_img *im) {
535 =item i_img_get_height(im)
537 =synopsis height = i_img_get_height(im);
539 Returns the height in pixels of the image.
544 i_img_get_height(i_img *im) {
549 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
553 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
554 (tx,ty) specifies the upper left corner for the target image.
555 pass NULL in trans for non transparent i_colors.
561 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,const i_color *trans) {
563 int x,y,t,ttx,tty,tt,ch;
565 mm_log((1,"i_copyto_trans(im* %p,src 0x%x, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d, trans* 0x%x)\n",
566 im, src, x1, y1, x2, y2, tx, ty, trans));
568 if (x2<x1) { t=x1; x1=x2; x2=t; }
569 if (y2<y1) { t=y1; y1=y2; y2=t; }
581 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
582 if (tt) i_ppix(im,ttx,tty,&pv);
583 } else i_ppix(im,ttx,tty,&pv);
591 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
595 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
596 a rectangle the same size with it's top-left corner at (tx,ty) in the
599 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
605 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
606 int x, y, t, ttx, tty;
608 if (x2<x1) { t=x1; x1=x2; x2=t; }
609 if (y2<y1) { t=y1; y1=y2; y2=t; }
611 /* adjust everything equally */
621 if (x1 >= src->xsize || y1 >= src->ysize)
622 return; /* nothing to do */
627 if (x1 == x2 || y1 == y2)
628 return; /* nothing to do */
630 mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
631 im, src, x1, y1, x2, y2, tx, ty));
633 if (im->bits == i_8_bits) {
634 i_color *row = mymalloc(sizeof(i_color) * (x2-x1));
636 for(y=y1; y<y2; y++) {
638 i_glin(src, x1, x2, y, row);
639 i_plin(im, tx, tx+x2-x1, tty, row);
647 for(y=y1; y<y2; y++) {
649 for(x=x1; x<x2; x++) {
650 i_gpixf(src, x, y, &pv);
651 i_ppixf(im, ttx, tty, &pv);
664 Creates a new image that is a copy of src.
666 Tags are not copied, only the image data.
676 i_img *im = i_sametype(src, src->xsize, src->ysize);
678 mm_log((1,"i_copy(src %p)\n", src));
685 if (src->type == i_direct_type) {
686 if (src->bits == i_8_bits) {
688 pv = mymalloc(sizeof(i_color) * x1);
690 for (y = 0; y < y1; ++y) {
691 i_glin(src, 0, x1, y, pv);
692 i_plin(im, 0, x1, y, pv);
699 pv = mymalloc(sizeof(i_fcolor) * x1);
700 for (y = 0; y < y1; ++y) {
701 i_glinf(src, 0, x1, y, pv);
702 i_plinf(im, 0, x1, y, pv);
714 i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
715 /* copy across the palette */
716 count = i_colorcount(src);
717 for (index = 0; index < count; ++index) {
718 i_getcolors(src, index, &temp, 1);
719 i_addcolors(im, &temp, 1);
722 vals = mymalloc(sizeof(i_palidx) * x1);
723 for (y = 0; y < y1; ++y) {
724 i_gpal(src, 0, x1, y, vals);
725 i_ppal(im, 0, x1, y, vals);
735 =item i_flipxy(im, axis)
737 Flips the image inplace around the axis specified.
738 Returns 0 if parameters are invalid.
741 axis - 0 = x, 1 = y, 2 = both
747 i_flipxy(i_img *im, int direction) {
748 int x, x2, y, y2, xm, ym;
752 mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
757 case XAXIS: /* Horizontal flip */
760 for(y=0; y<ym; y++) {
762 for(x=0; x<xm; x++) {
764 i_gpix(im, x, y, &val1);
765 i_gpix(im, x2, y, &val2);
766 i_ppix(im, x, y, &val2);
767 i_ppix(im, x2, y, &val1);
772 case YAXIS: /* Vertical flip */
776 for(y=0; y<ym; y++) {
777 for(x=0; x<xm; x++) {
779 i_gpix(im, x, y, &val1);
780 i_gpix(im, x, y2, &val2);
781 i_ppix(im, x, y, &val2);
782 i_ppix(im, x, y2, &val1);
787 case XYAXIS: /* Horizontal and Vertical flip */
791 for(y=0; y<ym; y++) {
793 for(x=0; x<xm; x++) {
795 i_gpix(im, x, y, &val1);
796 i_gpix(im, x2, y2, &val2);
797 i_ppix(im, x, y, &val2);
798 i_ppix(im, x2, y2, &val1);
800 i_gpix(im, x2, y, &val1);
801 i_gpix(im, x, y2, &val2);
802 i_ppix(im, x2, y, &val2);
803 i_ppix(im, x, y2, &val1);
808 if (xm*2 != xs) { /* odd number of column */
809 mm_log((1, "i_flipxy: odd number of columns\n"));
812 for(y=0; y<ym; y++) {
814 i_gpix(im, x, y, &val1);
815 i_gpix(im, x, y2, &val2);
816 i_ppix(im, x, y, &val2);
817 i_ppix(im, x, y2, &val1);
821 if (ym*2 != ys) { /* odd number of rows */
822 mm_log((1, "i_flipxy: odd number of rows\n"));
825 for(x=0; x<xm; x++) {
827 i_gpix(im, x, y, &val1);
828 i_gpix(im, x2, y, &val2);
829 i_ppix(im, x, y, &val2);
830 i_ppix(im, x2, y, &val1);
836 mm_log((1, "i_flipxy: direction is invalid\n" ));
854 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
855 else if (x == 0.0) return (1.0);
856 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
861 =item i_scaleaxis(im, value, axis)
863 Returns a new image object which is I<im> scaled by I<value> along
864 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
870 i_scaleaxis(i_img *im, float Value, int Axis) {
871 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
872 int LanczosWidthFactor;
873 float *l0, *l1, OldLocation;
876 float F, PictureValue[MAXCHANNELS];
878 i_color val,val1,val2;
881 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
885 hsize = (int)(0.5 + im->xsize * Value);
888 Value = 1.0 / im->xsize;
896 vsize = (int)(0.5 + im->ysize * Value);
900 Value = 1.0 / im->ysize;
907 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
909 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
910 LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value);
911 lMax = LanczosWidthFactor << 1;
913 l0 = mymalloc(lMax * sizeof(float));
914 l1 = mymalloc(lMax * sizeof(float));
916 for (j=0; j<jEnd; j++) {
917 OldLocation = ((float) j) / Value;
918 T = (int) (OldLocation);
919 F = OldLocation - (float) T;
921 for (l = 0; l<lMax; l++) {
922 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
923 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
926 /* Make sure filter is normalized */
928 for(l=0; l<lMax; l++) {
932 t /= (float)LanczosWidthFactor;
934 for(l=0; l<lMax; l++) {
941 for (i=0; i<iEnd; i++) {
942 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
943 for (l=0; l<lMax; l++) {
946 mx = (mx < 0) ? 0 : mx;
947 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
949 i_gpix(im, Mx, i, &val1);
950 i_gpix(im, mx, i, &val2);
952 for (k=0; k<im->channels; k++) {
953 PictureValue[k] += l1[l] * val1.channel[k];
954 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
957 for(k=0;k<im->channels;k++) {
958 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
959 val.channel[k]=minmax(0,255,psave);
961 i_ppix(new_img, j, i, &val);
966 for (i=0; i<iEnd; i++) {
967 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
968 for (l=0; l < lMax; l++) {
971 mx = (mx < 0) ? 0 : mx;
972 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
974 i_gpix(im, i, Mx, &val1);
975 i_gpix(im, i, mx, &val2);
976 for (k=0; k<im->channels; k++) {
977 PictureValue[k] += l1[l] * val1.channel[k];
978 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
981 for (k=0; k<im->channels; k++) {
982 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
983 val.channel[k] = minmax(0, 255, psave);
985 i_ppix(new_img, i, j, &val);
993 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
1000 =item i_scale_nn(im, scx, scy)
1002 Scale by using nearest neighbor
1003 Both axes scaled at the same time since
1004 nothing is gained by doing it in two steps
1011 i_scale_nn(i_img *im, float scx, float scy) {
1013 int nxsize,nysize,nx,ny;
1017 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1019 nxsize = (int) ((float) im->xsize * scx);
1022 scx = 1 / im->xsize;
1024 nysize = (int) ((float) im->ysize * scy);
1027 scy = 1 / im->ysize;
1030 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1032 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1033 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1034 i_ppix(new_img,nx,ny,&val);
1037 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1043 =item i_sametype(i_img *im, int xsize, int ysize)
1045 =category Image creation/destruction
1046 =synopsis i_img *img = i_sametype(src, width, height);
1048 Returns an image of the same type (sample size, channels, paletted/direct).
1050 For paletted images the palette is copied from the source.
1055 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1056 if (src->type == i_direct_type) {
1057 if (src->bits == 8) {
1058 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1060 else if (src->bits == i_16_bits) {
1061 return i_img_16_new(xsize, ysize, src->channels);
1063 else if (src->bits == i_double_bits) {
1064 return i_img_double_new(xsize, ysize, src->channels);
1067 i_push_error(0, "Unknown image bits");
1075 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1076 for (i = 0; i < i_colorcount(src); ++i) {
1077 i_getcolors(src, i, &col, 1);
1078 i_addcolors(targ, &col, 1);
1086 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
1088 =category Image creation/destruction
1089 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
1091 Returns an image of the same type (sample size).
1093 For paletted images the equivalent direct type is returned.
1098 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1099 if (src->bits == 8) {
1100 return i_img_empty_ch(NULL, xsize, ysize, channels);
1102 else if (src->bits == i_16_bits) {
1103 return i_img_16_new(xsize, ysize, channels);
1105 else if (src->bits == i_double_bits) {
1106 return i_img_double_new(xsize, ysize, channels);
1109 i_push_error(0, "Unknown image bits");
1115 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1117 Spatially transforms I<im> returning a new image.
1119 opx for a length of opxl and opy for a length of opy are arrays of
1120 operators that modify the x and y positions to retreive the pixel data from.
1122 parm and parmlen define extra parameters that the operators may use.
1124 Note that this function is largely superseded by the more flexible
1125 L<transform.c/i_transform2>.
1127 Returns the new image.
1129 The operators for this function are defined in L<stackmach.c>.
1134 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1136 int nxsize,nysize,nx,ny;
1140 mm_log((1,"i_transform(im 0x%x, opx 0x%x, opxl %d, opy 0x%x, opyl %d, parm 0x%x, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
1143 nysize = im->ysize ;
1145 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1146 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
1147 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1148 /* parm[parmlen-2]=(double)nx;
1149 parm[parmlen-1]=(double)ny; */
1154 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
1155 rx=i_op_run(opx,opxl,parm,parmlen);
1156 ry=i_op_run(opy,opyl,parm,parmlen);
1157 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
1158 i_gpix(im,rx,ry,&val);
1159 i_ppix(new_img,nx,ny,&val);
1162 mm_log((1,"(0x%x) <- i_transform\n",new_img));
1167 =item i_img_diff(im1, im2)
1169 Calculates the sum of the squares of the differences between
1170 correspoding channels in two images.
1172 If the images are not the same size then only the common area is
1173 compared, hence even if images are different sizes this function
1179 i_img_diff(i_img *im1,i_img *im2) {
1180 int x,y,ch,xb,yb,chb;
1184 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1186 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1187 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1188 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1190 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1193 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1194 i_gpix(im1,x,y,&val1);
1195 i_gpix(im2,x,y,&val2);
1197 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1199 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1203 /* just a tiny demo of haar wavelets */
1211 i_img *new_img,*new_img2;
1212 i_color val1,val2,dval1,dval2;
1220 /* horizontal pass */
1222 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1223 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1226 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1227 i_gpix(im,x*2,y,&val1);
1228 i_gpix(im,x*2+1,y,&val2);
1229 for(ch=0;ch<im->channels;ch++) {
1230 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1231 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1233 i_ppix(new_img,x,y,&dval1);
1234 i_ppix(new_img,x+fx,y,&dval2);
1237 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1238 i_gpix(new_img,x,y*2,&val1);
1239 i_gpix(new_img,x,y*2+1,&val2);
1240 for(ch=0;ch<im->channels;ch++) {
1241 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1242 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1244 i_ppix(new_img2,x,y,&dval1);
1245 i_ppix(new_img2,x,y+fy,&dval2);
1248 i_img_destroy(new_img);
1253 =item i_count_colors(im, maxc)
1255 returns number of colors or -1
1256 to indicate that it was more than max colors
1260 /* This function has been changed and is now faster. It's using
1261 * i_gsamp instead of i_gpix */
1263 i_count_colors(i_img *im,int maxc) {
1270 int xsize = im->xsize;
1271 int ysize = im->ysize;
1272 int samp_cnt = 3 * xsize;
1274 if (im->channels >= 3) {
1278 channels[0] = channels[1] = channels[2] = 0;
1279 samp_chans = channels;
1284 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1287 for(y = 0; y < ysize; ) {
1288 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1289 for(x = 0; x < samp_cnt; ) {
1290 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1292 if (colorcnt > maxc) {
1303 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
1304 * (adapted from the Numerical Recipes)
1306 /* Needed by get_anonymous_color_histo */
1308 hpsort(unsigned int n, unsigned *ra) {
1333 if (j < ir && ra[j] < ra[j+1]) j++;
1345 /* This function constructs an ordered list which represents how much the
1346 * different colors are used. So for instance (100, 100, 500) means that one
1347 * color is used for 500 pixels, another for 100 pixels and another for 100
1348 * pixels. It's tuned for performance. You might not like the way I've hardcoded
1349 * the maxc ;-) and you might want to change the name... */
1350 /* Uses octt_histo */
1352 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1356 unsigned int *col_usage_it;
1361 int xsize = im->xsize;
1362 int ysize = im->ysize;
1363 int samp_cnt = 3 * xsize;
1366 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1368 if (im->channels >= 3) {
1372 channels[0] = channels[1] = channels[2] = 0;
1373 samp_chans = channels;
1377 for(y = 0; y < ysize; ) {
1378 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1379 for(x = 0; x < samp_cnt; ) {
1380 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1382 if (colorcnt > maxc) {
1389 /* Now that we know the number of colours... */
1390 col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1391 octt_histo(ct, &col_usage_it);
1392 hpsort(colorcnt, *col_usage);
1400 =head2 8-bit per sample image internal functions
1402 These are the functions installed in an 8-bit per sample image.
1406 =item i_ppix_d(im, x, y, col)
1410 This is the function kept in the i_f_ppix member of an i_img object.
1411 It does a normal store of a pixel into the image with range checking.
1413 Returns 0 if the pixel could be set, -1 otherwise.
1419 i_ppix_d(i_img *im, int x, int y, const i_color *val) {
1422 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1423 for(ch=0;ch<im->channels;ch++)
1424 if (im->ch_mask&(1<<ch))
1425 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1428 return -1; /* error was clipped */
1432 =item i_gpix_d(im, x, y, &col)
1436 This is the function kept in the i_f_gpix member of an i_img object.
1437 It does normal retrieval of a pixel from the image with range checking.
1439 Returns 0 if the pixel could be set, -1 otherwise.
1445 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1447 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1448 for(ch=0;ch<im->channels;ch++)
1449 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1452 for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1453 return -1; /* error was cliped */
1457 =item i_glin_d(im, l, r, y, vals)
1459 Reads a line of data from the image, storing the pixels at vals.
1461 The line runs from (l,y) inclusive to (r,y) non-inclusive
1463 vals should point at space for (r-l) pixels.
1465 l should never be less than zero (to avoid confusion about where to
1466 put the pixels in vals).
1468 Returns the number of pixels copied (eg. if r, l or y is out of range)
1474 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1476 unsigned char *data;
1477 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1480 data = im->idata + (l+y*im->xsize) * im->channels;
1482 for (i = 0; i < count; ++i) {
1483 for (ch = 0; ch < im->channels; ++ch)
1484 vals[i].channel[ch] = *data++;
1494 =item i_plin_d(im, l, r, y, vals)
1496 Writes a line of data into the image, using the pixels at vals.
1498 The line runs from (l,y) inclusive to (r,y) non-inclusive
1500 vals should point at (r-l) pixels.
1502 l should never be less than zero (to avoid confusion about where to
1503 get the pixels in vals).
1505 Returns the number of pixels copied (eg. if r, l or y is out of range)
1511 i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) {
1513 unsigned char *data;
1514 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1517 data = im->idata + (l+y*im->xsize) * im->channels;
1519 for (i = 0; i < count; ++i) {
1520 for (ch = 0; ch < im->channels; ++ch) {
1521 if (im->ch_mask & (1 << ch))
1522 *data = vals[i].channel[ch];
1534 =item i_ppixf_d(im, x, y, val)
1540 i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) {
1543 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1544 for(ch=0;ch<im->channels;ch++)
1545 if (im->ch_mask&(1<<ch)) {
1546 im->idata[(x+y*im->xsize)*im->channels+ch] =
1547 SampleFTo8(val->channel[ch]);
1551 return -1; /* error was clipped */
1555 =item i_gpixf_d(im, x, y, val)
1561 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1563 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1564 for(ch=0;ch<im->channels;ch++) {
1566 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1570 return -1; /* error was cliped */
1574 =item i_glinf_d(im, l, r, y, vals)
1576 Reads a line of data from the image, storing the pixels at vals.
1578 The line runs from (l,y) inclusive to (r,y) non-inclusive
1580 vals should point at space for (r-l) pixels.
1582 l should never be less than zero (to avoid confusion about where to
1583 put the pixels in vals).
1585 Returns the number of pixels copied (eg. if r, l or y is out of range)
1591 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1593 unsigned char *data;
1594 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1597 data = im->idata + (l+y*im->xsize) * im->channels;
1599 for (i = 0; i < count; ++i) {
1600 for (ch = 0; ch < im->channels; ++ch)
1601 vals[i].channel[ch] = Sample8ToF(*data++);
1611 =item i_plinf_d(im, l, r, y, vals)
1613 Writes a line of data into the image, using the pixels at vals.
1615 The line runs from (l,y) inclusive to (r,y) non-inclusive
1617 vals should point at (r-l) pixels.
1619 l should never be less than zero (to avoid confusion about where to
1620 get the pixels in vals).
1622 Returns the number of pixels copied (eg. if r, l or y is out of range)
1628 i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) {
1630 unsigned char *data;
1631 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1634 data = im->idata + (l+y*im->xsize) * im->channels;
1636 for (i = 0; i < count; ++i) {
1637 for (ch = 0; ch < im->channels; ++ch) {
1638 if (im->ch_mask & (1 << ch))
1639 *data = SampleFTo8(vals[i].channel[ch]);
1651 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1653 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1654 for the channels specified by chans, an array of int with chan_count
1657 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1663 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
1664 const int *chans, int chan_count) {
1665 int ch, count, i, w;
1666 unsigned char *data;
1668 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1671 data = im->idata + (l+y*im->xsize) * im->channels;
1676 /* make sure we have good channel numbers */
1677 for (ch = 0; ch < chan_count; ++ch) {
1678 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1679 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1683 for (i = 0; i < w; ++i) {
1684 for (ch = 0; ch < chan_count; ++ch) {
1685 *samps++ = data[chans[ch]];
1688 data += im->channels;
1692 if (chan_count <= 0 || chan_count > im->channels) {
1693 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
1697 for (i = 0; i < w; ++i) {
1698 for (ch = 0; ch < chan_count; ++ch) {
1699 *samps++ = data[ch];
1702 data += im->channels;
1714 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1716 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1717 for the channels specified by chan_mask, where bit 0 is the first
1720 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1726 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
1727 const int *chans, int chan_count) {
1728 int ch, count, i, w;
1729 unsigned char *data;
1730 for (ch = 0; ch < chan_count; ++ch) {
1731 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1732 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1735 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1738 data = im->idata + (l+y*im->xsize) * im->channels;
1743 /* make sure we have good channel numbers */
1744 for (ch = 0; ch < chan_count; ++ch) {
1745 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1746 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1750 for (i = 0; i < w; ++i) {
1751 for (ch = 0; ch < chan_count; ++ch) {
1752 *samps++ = Sample8ToF(data[chans[ch]]);
1755 data += im->channels;
1759 if (chan_count <= 0 || chan_count > im->channels) {
1760 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
1764 for (i = 0; i < w; ++i) {
1765 for (ch = 0; ch < chan_count; ++ch) {
1766 *samps++ = Sample8ToF(data[ch]);
1769 data += im->channels;
1782 =head2 Image method wrappers
1784 These functions provide i_fsample_t functions in terms of their
1785 i_sample_t versions.
1789 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1794 int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) {
1798 for (ch = 0; ch < im->channels; ++ch)
1799 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1801 return i_ppix(im, x, y, &temp);
1805 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1809 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1813 if (i_gpix(im, x, y, &temp)) {
1814 for (ch = 0; ch < im->channels; ++ch)
1815 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1823 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1827 int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) {
1830 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1836 work = mymalloc(sizeof(i_color) * (r-l));
1837 for (i = 0; i < r-l; ++i) {
1838 for (ch = 0; ch < im->channels; ++ch)
1839 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1841 ret = i_plin(im, l, r, y, work);
1856 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1860 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1863 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1869 work = mymalloc(sizeof(i_color) * (r-l));
1870 ret = i_plin(im, l, r, y, work);
1871 for (i = 0; i < r-l; ++i) {
1872 for (ch = 0; ch < im->channels; ++ch)
1873 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1889 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1893 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
1894 int const *chans, int chan_count) {
1897 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1903 work = mymalloc(sizeof(i_sample_t) * (r-l));
1904 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1905 for (i = 0; i < ret; ++i) {
1906 samp[i] = Sample8ToF(work[i]);
1924 =head2 Palette wrapper functions
1926 Used for virtual images, these forward palette calls to a wrapped image,
1927 assuming the wrapped image is the first pointer in the structure that
1928 im->ext_data points at.
1932 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1936 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1937 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1941 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1945 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1946 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1950 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1954 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1955 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1959 =item i_colorcount_forward(i_img *im)
1963 int i_colorcount_forward(i_img *im) {
1964 return i_colorcount(*(i_img **)im->ext_data);
1968 =item i_maxcolors_forward(i_img *im)
1972 int i_maxcolors_forward(i_img *im) {
1973 return i_maxcolors(*(i_img **)im->ext_data);
1977 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1981 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1982 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1988 =head2 Stream reading and writing wrapper functions
1992 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1994 Performs general read buffering for file readers that permit reading
1995 to be done through a callback.
1997 The final callback gets two parameters, a I<need> value, and a I<want>
1998 value, where I<need> is the amount of data that the file library needs
1999 to read, and I<want> is the amount of space available in the buffer
2000 maintained by these functions.
2002 This means if you need to read from a stream that you don't know the
2003 length of, you can return I<need> bytes, taking the performance hit of
2004 possibly expensive callbacks (eg. back to perl code), or if you are
2005 reading from a stream where it doesn't matter if some data is lost, or
2006 if the total length of the stream is known, you can return I<want>
2013 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
2016 if (length < gci->length - gci->cpos) {
2018 memcpy(buf, gci->buffer+gci->cpos, length);
2019 gci->cpos += length;
2024 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
2025 total += gci->length - gci->cpos;
2026 length -= gci->length - gci->cpos;
2027 buf += gci->length - gci->cpos;
2028 if (length < (int)sizeof(gci->buffer)) {
2032 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
2033 sizeof(gci->buffer))) > 0) {
2035 gci->length = did_read;
2037 copy_size = i_min(length, gci->length);
2038 memcpy(buf, gci->buffer, copy_size);
2039 gci->cpos += copy_size;
2042 length -= copy_size;
2046 /* just read the rest - too big for our buffer*/
2048 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
2058 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
2060 For use by callback file readers to initialize the reader buffer.
2062 Allocates, initializes and returns the reader buffer.
2064 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
2069 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
2070 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
2072 self->userdata = userdata;
2080 =item i_free_gen_read_data(i_gen_read_data *)
2086 void i_free_gen_read_data(i_gen_read_data *self) {
2091 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
2093 Performs write buffering for a callback based file writer.
2095 Failures are considered fatal, if a write fails then data will be
2102 i_gen_write_data *self,
2106 if (self->filledto && self->filledto+size > self->maxlength) {
2107 if (self->cb(self->userdata, self->buffer, self->filledto)) {
2115 if (self->filledto+size <= self->maxlength) {
2117 memcpy(self->buffer+self->filledto, data, size);
2118 self->filledto += size;
2121 /* doesn't fit - hand it off */
2122 return self->cb(self->userdata, data, size);
2126 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2128 Allocates and initializes the data structure used by i_gen_writer.
2130 This should be released with L<image.c/i_free_gen_write_data>
2134 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
2135 char *userdata, int max_length)
2137 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2139 self->userdata = userdata;
2140 self->maxlength = i_min(max_length, sizeof(self->buffer));
2141 if (self->maxlength < 0)
2142 self->maxlength = sizeof(self->buffer);
2149 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2151 Cleans up the write buffer.
2153 Will flush any left-over data if I<flush> is non-zero.
2155 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2157 Return zero only if flush is non-zero and info->cb() returns zero.
2163 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2165 int result = !flush ||
2166 info->filledto == 0 ||
2167 info->cb(info->userdata, info->buffer, info->filledto);
2173 struct magic_entry {
2174 unsigned char *magic;
2177 unsigned char *mask;
2181 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
2182 if (length < magic->magic_size)
2186 unsigned char *bufp = buffer,
2187 *maskp = magic->mask,
2188 *magicp = magic->magic;
2190 for (i = 0; i < magic->magic_size; ++i) {
2191 int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
2194 if ((*bufp++ & mask) != (*magicp++ & mask))
2201 return !memcmp(magic->magic, buffer, magic->magic_size);
2206 =item i_test_format_probe(io_glue *data, int length)
2208 Check the beginning of the supplied file for a 'magic number'
2213 #define FORMAT_ENTRY(magic, type) \
2214 { (unsigned char *)(magic ""), sizeof(magic)-1, type }
2215 #define FORMAT_ENTRY2(magic, type, mask) \
2216 { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
2219 i_test_format_probe(io_glue *data, int length) {
2220 static const struct magic_entry formats[] = {
2221 FORMAT_ENTRY("\xFF\xD8", "jpeg"),
2222 FORMAT_ENTRY("GIF87a", "gif"),
2223 FORMAT_ENTRY("GIF89a", "gif"),
2224 FORMAT_ENTRY("MM\0*", "tiff"),
2225 FORMAT_ENTRY("II*\0", "tiff"),
2226 FORMAT_ENTRY("BM", "bmp"),
2227 FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
2228 FORMAT_ENTRY("P1", "pnm"),
2229 FORMAT_ENTRY("P2", "pnm"),
2230 FORMAT_ENTRY("P3", "pnm"),
2231 FORMAT_ENTRY("P4", "pnm"),
2232 FORMAT_ENTRY("P5", "pnm"),
2233 FORMAT_ENTRY("P6", "pnm"),
2234 FORMAT_ENTRY("/* XPM", "xpm"),
2235 FORMAT_ENTRY("\x8aMNG", "mng"),
2236 FORMAT_ENTRY("\x8aJNG", "jng"),
2237 /* SGI RGB - with various possible parameters to avoid false positives
2239 values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
2241 FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
2242 FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
2243 FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
2244 FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
2246 FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
2248 /* different versions of PCX format
2249 http://www.fileformat.info/format/pcx/
2251 FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
2252 FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
2253 FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
2254 FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
2255 FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
2257 /* FITS - http://fits.gsfc.nasa.gov/ */
2258 FORMAT_ENTRY("SIMPLE =", "fits"),
2260 /* PSD - Photoshop */
2261 FORMAT_ENTRY("8BPS\x00\x01", "psd"),
2263 /* EPS - Encapsulated Postscript */
2264 /* only reading 18 chars, so we don't include the F in EPSF */
2265 FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
2268 FORMAT_ENTRY("\x52\xCC", "utah"),
2270 /* GZIP compressed, only matching deflate for now */
2271 FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
2273 /* bzip2 compressed */
2274 FORMAT_ENTRY("BZh", "bzip2"),
2276 static const struct magic_entry more_formats[] = {
2277 /* these were originally both listed as ico, but cur files can
2278 include hotspot information */
2279 FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
2280 FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
2281 FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07",
2282 "xwd", " xxxx"), /* X Windows Dump */
2286 unsigned char head[18];
2289 io_glue_commit_types(data);
2290 rc = data->readcb(data, head, 18);
2291 if (rc == -1) return NULL;
2292 data->seekcb(data, -rc, SEEK_CUR);
2294 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
2295 struct magic_entry const *entry = formats + i;
2297 if (test_magic(head, rc, entry))
2302 tga_header_verify(head))
2305 for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
2306 struct magic_entry const *entry = more_formats + i;
2308 if (test_magic(head, rc, entry))
2316 =item i_img_is_monochrome(img, &zero_is_white)
2318 Tests an image to check it meets our monochrome tests.
2320 The idea is that a file writer can use this to test where it should
2321 write the image in whatever bi-level format it uses, eg. pbm for pnm.
2323 For performance of encoders we require monochrome images:
2333 have a palette of two colors, containing only (0,0,0) and
2334 (255,255,255) in either order.
2338 zero_is_white is set to non-zero iff the first palette entry is white.
2344 i_img_is_monochrome(i_img *im, int *zero_is_white) {
2345 if (im->type == i_palette_type
2346 && i_colorcount(im) == 2) {
2348 i_getcolors(im, 0, colors, 2);
2349 if (im->channels == 3) {
2350 if (colors[0].rgb.r == 255 &&
2351 colors[0].rgb.g == 255 &&
2352 colors[0].rgb.b == 255 &&
2353 colors[1].rgb.r == 0 &&
2354 colors[1].rgb.g == 0 &&
2355 colors[1].rgb.b == 0) {
2359 else if (colors[0].rgb.r == 0 &&
2360 colors[0].rgb.g == 0 &&
2361 colors[0].rgb.b == 0 &&
2362 colors[1].rgb.r == 255 &&
2363 colors[1].rgb.g == 255 &&
2364 colors[1].rgb.b == 255) {
2369 else if (im->channels == 1) {
2370 if (colors[0].channel[0] == 255 &&
2371 colors[1].channel[1] == 0) {
2375 else if (colors[0].channel[0] == 0 &&
2376 colors[0].channel[0] == 255) {
2392 Arnar M. Hrafnkelsson <addi@umich.edu>
2394 Tony Cook <tony@develop-help.com>