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);
55 =category Image Implementation
57 Allocates a new i_img structure.
59 When implementing a new image type perform the following steps in your
60 image object creation function:
66 allocate the image with i_img_alloc().
70 initialize any function pointers or other data as needed, you can
71 overwrite the whole block if you need to.
75 initialize Imager's internal data by calling i_img_init() on the image
85 return mymalloc(sizeof(i_img));
89 =item i_img_init(C<img>)
90 =category Image Implementation
92 Imager internal initialization of images.
94 Currently this does very little, in the future it may be used to
95 support threads, or color profiles.
101 i_img_init(i_img *img) {
106 =item ICL_new_internal(r, g, b, a)
108 Return a new color object with values passed to it.
110 r - red component (range: 0 - 255)
111 g - green component (range: 0 - 255)
112 b - blue component (range: 0 - 255)
113 a - alpha component (range: 0 - 255)
119 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
122 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
124 if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
129 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
135 =item ICL_set_internal(cl, r, g, b, a)
137 Overwrite a color with new values.
139 cl - pointer to color object
140 r - red component (range: 0 - 255)
141 g - green component (range: 0 - 255)
142 b - blue component (range: 0 - 255)
143 a - alpha component (range: 0 - 255)
149 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
150 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
152 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
153 i_fatal(2,"malloc() error\n");
158 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
164 =item ICL_add(dst, src, ch)
166 Add src to dst inplace - dst is modified.
168 dst - pointer to destination color object
169 src - pointer to color object that is added
170 ch - number of channels
176 ICL_add(i_color *dst,i_color *src,int ch) {
179 tmp=dst->channel[i]+src->channel[i];
180 dst->channel[i]= tmp>255 ? 255:tmp;
187 Dump color information to log - strictly for debugging.
189 cl - pointer to color object
195 ICL_info(i_color const *cl) {
196 mm_log((1,"i_color_info(cl* %p)\n",cl));
197 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
203 Destroy ancillary data for Color object.
205 cl - pointer to color object
211 ICL_DESTROY(i_color *cl) {
212 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
217 =item i_fcolor_new(double r, double g, double b, double a)
221 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
224 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
226 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
231 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
237 =item i_fcolor_destroy(i_fcolor *cl)
241 void i_fcolor_destroy(i_fcolor *cl) {
246 =item IIM_base_8bit_direct (static)
248 A static i_img object used to initialize direct 8-bit per sample images.
252 static i_img IIM_base_8bit_direct =
254 0, /* channels set */
255 0, 0, 0, /* xsize, ysize, bytes */
258 i_direct_type, /* type */
261 { 0, 0, NULL }, /* tags */
264 i_ppix_d, /* i_f_ppix */
265 i_ppixf_d, /* i_f_ppixf */
266 i_plin_d, /* i_f_plin */
267 i_plinf_d, /* i_f_plinf */
268 i_gpix_d, /* i_f_gpix */
269 i_gpixf_d, /* i_f_gpixf */
270 i_glin_d, /* i_f_glin */
271 i_glinf_d, /* i_f_glinf */
272 i_gsamp_d, /* i_f_gsamp */
273 i_gsampf_d, /* i_f_gsampf */
277 NULL, /* i_f_addcolors */
278 NULL, /* i_f_getcolors */
279 NULL, /* i_f_colorcount */
280 NULL, /* i_f_maxcolors */
281 NULL, /* i_f_findcolor */
282 NULL, /* i_f_setcolors */
284 NULL, /* i_f_destroy */
287 NULL, /* i_f_psamp_bits */
290 /*static void set_8bit_direct(i_img *im) {
291 im->i_f_ppix = i_ppix_d;
292 im->i_f_ppixf = i_ppixf_d;
293 im->i_f_plin = i_plin_d;
294 im->i_f_plinf = i_plinf_d;
295 im->i_f_gpix = i_gpix_d;
296 im->i_f_gpixf = i_gpixf_d;
297 im->i_f_glin = i_glin_d;
298 im->i_f_glinf = i_glinf_d;
301 im->i_f_addcolor = NULL;
302 im->i_f_getcolor = NULL;
303 im->i_f_colorcount = NULL;
304 im->i_f_findcolor = NULL;
308 =item IIM_new(x, y, ch)
310 =item i_img_8_new(x, y, ch)
312 =category Image creation/destruction
314 =synopsis i_img *img = i_img_8_new(width, height, channels);
316 Creates a new image object I<x> pixels wide, and I<y> pixels high with
324 IIM_new(int x,int y,int ch) {
326 mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
328 im=i_img_empty_ch(NULL,x,y,ch);
330 mm_log((1,"(%p) <- IIM_new\n",im));
336 IIM_DESTROY(i_img *im) {
337 mm_log((1,"IIM_DESTROY(im* %p)\n",im));
345 Create new image reference - notice that this isn't an object yet and
346 this should be fixed asap.
356 mm_log((1,"i_img_struct()\n"));
360 *im = IIM_base_8bit_direct;
370 mm_log((1,"(%p) <- i_img_struct\n",im));
375 =item i_img_empty(im, x, y)
377 Re-new image reference (assumes 3 channels)
380 x - xsize of destination image
381 y - ysize of destination image
383 **FIXME** what happens if a live image is passed in here?
385 Should this just call i_img_empty_ch()?
391 i_img_empty(i_img *im,int x,int y) {
392 mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
393 return i_img_empty_ch(im, x, y, 3);
397 =item i_img_empty_ch(im, x, y, ch)
399 Re-new image reference
402 x - xsize of destination image
403 y - ysize of destination image
404 ch - number of channels
410 i_img_empty_ch(i_img *im,int x,int y,int ch) {
413 mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
415 if (x < 1 || y < 1) {
416 i_push_error(0, "Image sizes must be positive");
419 if (ch < 1 || ch > MAXCHANNELS) {
420 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
423 /* check this multiplication doesn't overflow */
425 if (bytes / y / ch != x) {
426 i_push_errorf(0, "integer overflow calculating image allocation");
433 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
434 i_tags_new(&im->tags);
438 im->ch_mask = MAXINT;
440 if ( (im->idata=mymalloc(im->bytes)) == NULL)
441 i_fatal(2,"malloc() error\n");
442 memset(im->idata,0,(size_t)im->bytes);
448 mm_log((1,"(%p) <- i_img_empty_ch\n",im));
453 =item i_img_exorcise(im)
463 i_img_exorcise(i_img *im) {
464 mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
465 i_tags_destroy(&im->tags);
467 (im->i_f_destroy)(im);
468 if (im->idata != NULL) { myfree(im->idata); }
474 im->i_f_ppix=i_ppix_d;
475 im->i_f_gpix=i_gpix_d;
476 im->i_f_plin=i_plin_d;
477 im->i_f_glin=i_glin_d;
482 =item i_img_destroy(C<img>)
484 =category Image creation/destruction
485 =synopsis i_img_destroy(img)
487 Destroy an image object
493 i_img_destroy(i_img *im) {
494 mm_log((1,"i_img_destroy(im %p)\n",im));
496 if (im) { myfree(im); }
500 =item i_img_info(im, info)
504 Return image information
507 info - pointer to array to return data
509 info is an array of 4 integers with the following values:
514 info[3] - channel mask
521 i_img_info(i_img *im,int *info) {
522 mm_log((1,"i_img_info(im 0x%x)\n",im));
524 mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
525 mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
528 info[2] = im->channels;
529 info[3] = im->ch_mask;
539 =item i_img_setmask(C<im>, C<ch_mask>)
540 =category Image Information
541 =synopsis // only channel 0 writeable
542 =synopsis i_img_setmask(img, 0x01);
544 Set the image channel mask for C<im> to C<ch_mask>.
546 The image channel mask gives some control over which channels can be
547 written to in the image.
552 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
556 =item i_img_getmask(C<im>)
557 =category Image Information
558 =synopsis int mask = i_img_getmask(img);
560 Get the image channel mask for C<im>.
565 i_img_getmask(i_img *im) { return im->ch_mask; }
568 =item i_img_getchannels(C<im>)
569 =category Image Information
570 =synopsis int channels = i_img_getchannels(img);
572 Get the number of channels in C<im>.
577 i_img_getchannels(i_img *im) { return im->channels; }
580 =item i_img_get_width(C<im>)
581 =category Image Information
582 =synopsis i_img_dim width = i_img_get_width(im);
584 Returns the width in pixels of the image.
589 i_img_get_width(i_img *im) {
594 =item i_img_get_height(C<im>)
595 =category Image Information
596 =synopsis i_img_dim height = i_img_get_height(im);
598 Returns the height in pixels of the image.
603 i_img_get_height(i_img *im) {
608 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
612 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
613 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
614 the target image. pass NULL in C<trans> for non transparent i_colors.
620 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) {
622 int x,y,t,ttx,tty,tt,ch;
624 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",
625 im, src, x1, y1, x2, y2, tx, ty, trans));
627 if (x2<x1) { t=x1; x1=x2; x2=t; }
628 if (y2<y1) { t=y1; y1=y2; y2=t; }
640 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
641 if (tt) i_ppix(im,ttx,tty,&pv);
642 } else i_ppix(im,ttx,tty,&pv);
654 Creates a new image that is a copy of the image C<source>.
656 Tags are not copied, only the image data.
666 i_img *im = i_sametype(src, src->xsize, src->ysize);
668 mm_log((1,"i_copy(src %p)\n", src));
675 if (src->type == i_direct_type) {
676 if (src->bits == i_8_bits) {
678 pv = mymalloc(sizeof(i_color) * x1);
680 for (y = 0; y < y1; ++y) {
681 i_glin(src, 0, x1, y, pv);
682 i_plin(im, 0, x1, y, pv);
689 pv = mymalloc(sizeof(i_fcolor) * x1);
690 for (y = 0; y < y1; ++y) {
691 i_glinf(src, 0, x1, y, pv);
692 i_plinf(im, 0, x1, y, pv);
700 vals = mymalloc(sizeof(i_palidx) * x1);
701 for (y = 0; y < y1; ++y) {
702 i_gpal(src, 0, x1, y, vals);
703 i_ppal(im, 0, x1, y, vals);
724 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
725 else if (x == 0.0) return (1.0);
726 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
731 =item i_scaleaxis(im, value, axis)
733 Returns a new image object which is I<im> scaled by I<value> along
734 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
740 i_scaleaxis(i_img *im, float Value, int Axis) {
741 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
742 int LanczosWidthFactor;
743 float *l0, *l1, OldLocation;
746 float F, PictureValue[MAXCHANNELS];
748 i_color val,val1,val2;
750 int has_alpha = i_img_has_alpha(im);
751 int color_chans = i_img_color_channels(im);
754 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
757 hsize = (int)(0.5 + im->xsize * Value);
760 Value = 1.0 / im->xsize;
768 vsize = (int)(0.5 + im->ysize * Value);
772 Value = 1.0 / im->ysize;
779 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
781 i_push_error(0, "cannot create output image");
785 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
786 LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value);
787 lMax = LanczosWidthFactor << 1;
789 l0 = mymalloc(lMax * sizeof(float));
790 l1 = mymalloc(lMax * sizeof(float));
792 for (j=0; j<jEnd; j++) {
793 OldLocation = ((float) j) / Value;
794 T = (int) (OldLocation);
795 F = OldLocation - (float) T;
797 for (l = 0; l<lMax; l++) {
798 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
799 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
802 /* Make sure filter is normalized */
804 for(l=0; l<lMax; l++) {
808 t /= (float)LanczosWidthFactor;
810 for(l=0; l<lMax; l++) {
817 for (i=0; i<iEnd; i++) {
818 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
819 for (l=0; l<lMax; l++) {
822 mx = (mx < 0) ? 0 : mx;
823 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
825 i_gpix(im, Mx, i, &val1);
826 i_gpix(im, mx, i, &val2);
829 i_sample_t alpha1 = val1.channel[color_chans];
830 i_sample_t alpha2 = val2.channel[color_chans];
831 for (k=0; k < color_chans; k++) {
832 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
833 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
835 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
836 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
839 for (k=0; k<im->channels; k++) {
840 PictureValue[k] += l1[l] * val1.channel[k];
841 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
847 float fa = PictureValue[color_chans] / LanczosWidthFactor;
848 int alpha = minmax(0, 255, fa+0.5);
850 for (k = 0; k < color_chans; ++k) {
851 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
852 val.channel[k]=minmax(0,255,psave);
854 val.channel[color_chans] = alpha;
857 /* zero alpha, so the pixel has no color */
858 for (k = 0; k < im->channels; ++k)
863 for(k=0;k<im->channels;k++) {
864 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
865 val.channel[k]=minmax(0,255,psave);
868 i_ppix(new_img, j, i, &val);
873 for (i=0; i<iEnd; i++) {
874 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
875 for (l=0; l < lMax; l++) {
878 mx = (mx < 0) ? 0 : mx;
879 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
881 i_gpix(im, i, Mx, &val1);
882 i_gpix(im, i, mx, &val2);
884 i_sample_t alpha1 = val1.channel[color_chans];
885 i_sample_t alpha2 = val2.channel[color_chans];
886 for (k=0; k < color_chans; k++) {
887 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
888 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
890 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
891 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
894 for (k=0; k<im->channels; k++) {
895 PictureValue[k] += l1[l] * val1.channel[k];
896 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
901 float fa = PictureValue[color_chans] / LanczosWidthFactor;
902 int alpha = minmax(0, 255, fa+0.5);
904 for (k = 0; k < color_chans; ++k) {
905 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
906 val.channel[k]=minmax(0,255,psave);
908 val.channel[color_chans] = alpha;
911 for (k = 0; k < im->channels; ++k)
916 for(k=0;k<im->channels;k++) {
917 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
918 val.channel[k]=minmax(0,255,psave);
921 i_ppix(new_img, i, j, &val);
929 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
936 =item i_scale_nn(im, scx, scy)
938 Scale by using nearest neighbor
939 Both axes scaled at the same time since
940 nothing is gained by doing it in two steps
947 i_scale_nn(i_img *im, float scx, float scy) {
949 int nxsize,nysize,nx,ny;
953 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
955 nxsize = (int) ((float) im->xsize * scx);
958 scx = 1.0 / im->xsize;
960 nysize = (int) ((float) im->ysize * scy);
963 scy = 1.0 / im->ysize;
965 im_assert(scx != 0 && scy != 0);
967 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
969 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
970 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
971 i_ppix(new_img,nx,ny,&val);
974 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
980 =item i_sametype(C<im>, C<xsize>, C<ysize>)
982 =category Image creation/destruction
983 =synopsis i_img *img = i_sametype(src, width, height);
985 Returns an image of the same type (sample size, channels, paletted/direct).
987 For paletted images the palette is copied from the source.
992 i_img *i_sametype(i_img *src, int xsize, int ysize) {
993 if (src->type == i_direct_type) {
994 if (src->bits == 8) {
995 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
997 else if (src->bits == i_16_bits) {
998 return i_img_16_new(xsize, ysize, src->channels);
1000 else if (src->bits == i_double_bits) {
1001 return i_img_double_new(xsize, ysize, src->channels);
1004 i_push_error(0, "Unknown image bits");
1012 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1013 for (i = 0; i < i_colorcount(src); ++i) {
1014 i_getcolors(src, i, &col, 1);
1015 i_addcolors(targ, &col, 1);
1023 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
1025 =category Image creation/destruction
1026 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
1028 Returns an image of the same type (sample size).
1030 For paletted images the equivalent direct type is returned.
1035 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1036 if (src->bits == 8) {
1037 return i_img_empty_ch(NULL, xsize, ysize, channels);
1039 else if (src->bits == i_16_bits) {
1040 return i_img_16_new(xsize, ysize, channels);
1042 else if (src->bits == i_double_bits) {
1043 return i_img_double_new(xsize, ysize, channels);
1046 i_push_error(0, "Unknown image bits");
1052 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1054 Spatially transforms I<im> returning a new image.
1056 opx for a length of opxl and opy for a length of opy are arrays of
1057 operators that modify the x and y positions to retreive the pixel data from.
1059 parm and parmlen define extra parameters that the operators may use.
1061 Note that this function is largely superseded by the more flexible
1062 L<transform.c/i_transform2>.
1064 Returns the new image.
1066 The operators for this function are defined in L<stackmach.c>.
1071 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1073 int nxsize,nysize,nx,ny;
1077 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));
1080 nysize = im->ysize ;
1082 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1083 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
1084 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1085 /* parm[parmlen-2]=(double)nx;
1086 parm[parmlen-1]=(double)ny; */
1091 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
1092 rx=i_op_run(opx,opxl,parm,parmlen);
1093 ry=i_op_run(opy,opyl,parm,parmlen);
1094 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
1095 i_gpix(im,rx,ry,&val);
1096 i_ppix(new_img,nx,ny,&val);
1099 mm_log((1,"(0x%x) <- i_transform\n",new_img));
1104 =item i_img_diff(im1, im2)
1106 Calculates the sum of the squares of the differences between
1107 correspoding channels in two images.
1109 If the images are not the same size then only the common area is
1110 compared, hence even if images are different sizes this function
1117 i_img_diff(i_img *im1,i_img *im2) {
1118 int x,y,ch,xb,yb,chb;
1122 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1124 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1125 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1126 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1128 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1131 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1132 i_gpix(im1,x,y,&val1);
1133 i_gpix(im2,x,y,&val2);
1135 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1137 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1142 =item i_img_diffd(im1, im2)
1144 Calculates the sum of the squares of the differences between
1145 correspoding channels in two images.
1147 If the images are not the same size then only the common area is
1148 compared, hence even if images are different sizes this function
1151 This is like i_img_diff() but looks at floating point samples instead.
1157 i_img_diffd(i_img *im1,i_img *im2) {
1158 int x,y,ch,xb,yb,chb;
1162 mm_log((1,"i_img_diffd(im1 0x%x,im2 0x%x)\n",im1,im2));
1164 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1165 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1166 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1168 mm_log((1,"i_img_diffd: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1171 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1172 i_gpixf(im1,x,y,&val1);
1173 i_gpixf(im2,x,y,&val2);
1175 for(ch=0;ch<chb;ch++) {
1176 double sdiff = val1.channel[ch]-val2.channel[ch];
1177 tdiff += sdiff * sdiff;
1180 mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
1186 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
1187 int x,y,ch,xb,yb,chb;
1193 mm_log((1,"i_img_samef(im1 0x%x,im2 0x%x, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
1195 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1196 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1197 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1199 mm_log((1,"i_img_samef: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1201 for(y = 0; y < yb; y++) {
1202 for(x = 0; x < xb; x++) {
1203 i_gpixf(im1, x, y, &val1);
1204 i_gpixf(im2, x, y, &val2);
1206 for(ch = 0; ch < chb; ch++) {
1207 double sdiff = val1.channel[ch] - val2.channel[ch];
1208 if (fabs(sdiff) > epsilon) {
1209 mm_log((1,"i_img_samef <- different %g @(%d,%d)\n", sdiff, x, y));
1215 mm_log((1,"i_img_samef <- same\n"));
1220 /* just a tiny demo of haar wavelets */
1228 i_img *new_img,*new_img2;
1229 i_color val1,val2,dval1,dval2;
1237 /* horizontal pass */
1239 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1240 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1243 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1244 i_gpix(im,x*2,y,&val1);
1245 i_gpix(im,x*2+1,y,&val2);
1246 for(ch=0;ch<im->channels;ch++) {
1247 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1248 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1250 i_ppix(new_img,x,y,&dval1);
1251 i_ppix(new_img,x+fx,y,&dval2);
1254 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1255 i_gpix(new_img,x,y*2,&val1);
1256 i_gpix(new_img,x,y*2+1,&val2);
1257 for(ch=0;ch<im->channels;ch++) {
1258 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1259 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1261 i_ppix(new_img2,x,y,&dval1);
1262 i_ppix(new_img2,x,y+fy,&dval2);
1265 i_img_destroy(new_img);
1270 =item i_count_colors(im, maxc)
1272 returns number of colors or -1
1273 to indicate that it was more than max colors
1277 /* This function has been changed and is now faster. It's using
1278 * i_gsamp instead of i_gpix */
1280 i_count_colors(i_img *im,int maxc) {
1287 int xsize = im->xsize;
1288 int ysize = im->ysize;
1289 int samp_cnt = 3 * xsize;
1291 if (im->channels >= 3) {
1295 channels[0] = channels[1] = channels[2] = 0;
1296 samp_chans = channels;
1301 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1304 for(y = 0; y < ysize; ) {
1305 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1306 for(x = 0; x < samp_cnt; ) {
1307 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1309 if (colorcnt > maxc) {
1320 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
1321 * (adapted from the Numerical Recipes)
1323 /* Needed by get_anonymous_color_histo */
1325 hpsort(unsigned int n, unsigned *ra) {
1350 if (j < ir && ra[j] < ra[j+1]) j++;
1362 /* This function constructs an ordered list which represents how much the
1363 * different colors are used. So for instance (100, 100, 500) means that one
1364 * color is used for 500 pixels, another for 100 pixels and another for 100
1365 * pixels. It's tuned for performance. You might not like the way I've hardcoded
1366 * the maxc ;-) and you might want to change the name... */
1367 /* Uses octt_histo */
1369 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1373 unsigned int *col_usage_it;
1378 int xsize = im->xsize;
1379 int ysize = im->ysize;
1380 int samp_cnt = 3 * xsize;
1383 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1385 if (im->channels >= 3) {
1389 channels[0] = channels[1] = channels[2] = 0;
1390 samp_chans = channels;
1394 for(y = 0; y < ysize; ) {
1395 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1396 for(x = 0; x < samp_cnt; ) {
1397 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1399 if (colorcnt > maxc) {
1406 /* Now that we know the number of colours... */
1407 col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1408 octt_histo(ct, &col_usage_it);
1409 hpsort(colorcnt, *col_usage);
1417 =head2 8-bit per sample image internal functions
1419 These are the functions installed in an 8-bit per sample image.
1423 =item i_ppix_d(im, x, y, col)
1427 This is the function kept in the i_f_ppix member of an i_img object.
1428 It does a normal store of a pixel into the image with range checking.
1430 Returns 0 if the pixel could be set, -1 otherwise.
1436 i_ppix_d(i_img *im, int x, int y, const i_color *val) {
1439 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1440 for(ch=0;ch<im->channels;ch++)
1441 if (im->ch_mask&(1<<ch))
1442 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1445 return -1; /* error was clipped */
1449 =item i_gpix_d(im, x, y, &col)
1453 This is the function kept in the i_f_gpix member of an i_img object.
1454 It does normal retrieval of a pixel from the image with range checking.
1456 Returns 0 if the pixel could be set, -1 otherwise.
1462 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1464 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1465 for(ch=0;ch<im->channels;ch++)
1466 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1469 for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1470 return -1; /* error was cliped */
1474 =item i_glin_d(im, l, r, y, vals)
1476 Reads a line of data from the image, storing the pixels at vals.
1478 The line runs from (l,y) inclusive to (r,y) non-inclusive
1480 vals should point at space for (r-l) pixels.
1482 l should never be less than zero (to avoid confusion about where to
1483 put the pixels in vals).
1485 Returns the number of pixels copied (eg. if r, l or y is out of range)
1491 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1493 unsigned char *data;
1494 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1497 data = im->idata + (l+y*im->xsize) * im->channels;
1499 for (i = 0; i < count; ++i) {
1500 for (ch = 0; ch < im->channels; ++ch)
1501 vals[i].channel[ch] = *data++;
1511 =item i_plin_d(im, l, r, y, vals)
1513 Writes a line of data into the image, using the pixels at vals.
1515 The line runs from (l,y) inclusive to (r,y) non-inclusive
1517 vals should point at (r-l) pixels.
1519 l should never be less than zero (to avoid confusion about where to
1520 get the pixels in vals).
1522 Returns the number of pixels copied (eg. if r, l or y is out of range)
1528 i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) {
1530 unsigned char *data;
1531 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1534 data = im->idata + (l+y*im->xsize) * im->channels;
1536 for (i = 0; i < count; ++i) {
1537 for (ch = 0; ch < im->channels; ++ch) {
1538 if (im->ch_mask & (1 << ch))
1539 *data = vals[i].channel[ch];
1551 =item i_ppixf_d(im, x, y, val)
1557 i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) {
1560 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1561 for(ch=0;ch<im->channels;ch++)
1562 if (im->ch_mask&(1<<ch)) {
1563 im->idata[(x+y*im->xsize)*im->channels+ch] =
1564 SampleFTo8(val->channel[ch]);
1568 return -1; /* error was clipped */
1572 =item i_gpixf_d(im, x, y, val)
1578 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1580 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1581 for(ch=0;ch<im->channels;ch++) {
1583 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1587 return -1; /* error was cliped */
1591 =item i_glinf_d(im, l, r, y, vals)
1593 Reads a line of data from the image, storing the pixels at vals.
1595 The line runs from (l,y) inclusive to (r,y) non-inclusive
1597 vals should point at space for (r-l) pixels.
1599 l should never be less than zero (to avoid confusion about where to
1600 put the pixels in vals).
1602 Returns the number of pixels copied (eg. if r, l or y is out of range)
1608 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1610 unsigned char *data;
1611 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1614 data = im->idata + (l+y*im->xsize) * im->channels;
1616 for (i = 0; i < count; ++i) {
1617 for (ch = 0; ch < im->channels; ++ch)
1618 vals[i].channel[ch] = Sample8ToF(*data++);
1628 =item i_plinf_d(im, l, r, y, vals)
1630 Writes a line of data into the image, using the pixels at vals.
1632 The line runs from (l,y) inclusive to (r,y) non-inclusive
1634 vals should point at (r-l) pixels.
1636 l should never be less than zero (to avoid confusion about where to
1637 get the pixels in vals).
1639 Returns the number of pixels copied (eg. if r, l or y is out of range)
1645 i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) {
1647 unsigned char *data;
1648 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1651 data = im->idata + (l+y*im->xsize) * im->channels;
1653 for (i = 0; i < count; ++i) {
1654 for (ch = 0; ch < im->channels; ++ch) {
1655 if (im->ch_mask & (1 << ch))
1656 *data = SampleFTo8(vals[i].channel[ch]);
1668 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1670 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1671 for the channels specified by chans, an array of int with chan_count
1674 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1680 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
1681 const int *chans, int chan_count) {
1682 int ch, count, i, w;
1683 unsigned char *data;
1685 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1688 data = im->idata + (l+y*im->xsize) * im->channels;
1693 /* make sure we have good channel numbers */
1694 for (ch = 0; ch < chan_count; ++ch) {
1695 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1696 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1700 for (i = 0; i < w; ++i) {
1701 for (ch = 0; ch < chan_count; ++ch) {
1702 *samps++ = data[chans[ch]];
1705 data += im->channels;
1709 if (chan_count <= 0 || chan_count > im->channels) {
1710 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
1714 for (i = 0; i < w; ++i) {
1715 for (ch = 0; ch < chan_count; ++ch) {
1716 *samps++ = data[ch];
1719 data += im->channels;
1731 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1733 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1734 for the channels specified by chan_mask, where bit 0 is the first
1737 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1743 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
1744 const int *chans, int chan_count) {
1745 int ch, count, i, w;
1746 unsigned char *data;
1747 for (ch = 0; ch < chan_count; ++ch) {
1748 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1749 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1752 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1755 data = im->idata + (l+y*im->xsize) * im->channels;
1760 /* make sure we have good channel numbers */
1761 for (ch = 0; ch < chan_count; ++ch) {
1762 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1763 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1767 for (i = 0; i < w; ++i) {
1768 for (ch = 0; ch < chan_count; ++ch) {
1769 *samps++ = Sample8ToF(data[chans[ch]]);
1772 data += im->channels;
1776 if (chan_count <= 0 || chan_count > im->channels) {
1777 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
1781 for (i = 0; i < w; ++i) {
1782 for (ch = 0; ch < chan_count; ++ch) {
1783 *samps++ = Sample8ToF(data[ch]);
1786 data += im->channels;
1799 =head2 Image method wrappers
1801 These functions provide i_fsample_t functions in terms of their
1802 i_sample_t versions.
1806 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1811 int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) {
1815 for (ch = 0; ch < im->channels; ++ch)
1816 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1818 return i_ppix(im, x, y, &temp);
1822 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1826 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1830 if (i_gpix(im, x, y, &temp)) {
1831 for (ch = 0; ch < im->channels; ++ch)
1832 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1840 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1844 int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) {
1847 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1853 work = mymalloc(sizeof(i_color) * (r-l));
1854 for (i = 0; i < r-l; ++i) {
1855 for (ch = 0; ch < im->channels; ++ch)
1856 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1858 ret = i_plin(im, l, r, y, work);
1873 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1877 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1880 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1886 work = mymalloc(sizeof(i_color) * (r-l));
1887 ret = i_plin(im, l, r, y, work);
1888 for (i = 0; i < r-l; ++i) {
1889 for (ch = 0; ch < im->channels; ++ch)
1890 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1906 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1910 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
1911 int const *chans, int chan_count) {
1914 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1920 work = mymalloc(sizeof(i_sample_t) * (r-l));
1921 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1922 for (i = 0; i < ret; ++i) {
1923 samp[i] = Sample8ToF(work[i]);
1941 =head2 Palette wrapper functions
1943 Used for virtual images, these forward palette calls to a wrapped image,
1944 assuming the wrapped image is the first pointer in the structure that
1945 im->ext_data points at.
1949 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1953 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1954 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1958 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1962 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1963 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1967 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1971 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1972 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1976 =item i_colorcount_forward(i_img *im)
1980 int i_colorcount_forward(i_img *im) {
1981 return i_colorcount(*(i_img **)im->ext_data);
1985 =item i_maxcolors_forward(i_img *im)
1989 int i_maxcolors_forward(i_img *im) {
1990 return i_maxcolors(*(i_img **)im->ext_data);
1994 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1998 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1999 return i_findcolor(*(i_img **)im->ext_data, color, entry);
2005 =head2 Fallback handler
2009 =item i_gsamp_bits_fb
2015 i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps,
2016 const int *chans, int chan_count, int bits) {
2017 if (bits < 1 || bits > 32) {
2018 i_push_error(0, "Invalid bits, must be 1..32");
2022 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
2024 int ch, count, i, w;
2027 scale = 4294967295.0;
2029 scale = (double)(1 << bits) - 1;
2037 /* make sure we have good channel numbers */
2038 for (ch = 0; ch < chan_count; ++ch) {
2039 if (chans[ch] < 0 || chans[ch] >= im->channels) {
2040 i_push_errorf(0, "No channel %d in this image", chans[ch]);
2044 for (i = 0; i < w; ++i) {
2046 i_gpixf(im, l+i, y, &c);
2047 for (ch = 0; ch < chan_count; ++ch) {
2048 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
2054 if (chan_count <= 0 || chan_count > im->channels) {
2055 i_push_error(0, "Invalid channel count");
2058 for (i = 0; i < w; ++i) {
2060 i_gpixf(im, l+i, y, &c);
2061 for (ch = 0; ch < chan_count; ++ch) {
2062 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
2071 i_push_error(0, "Image position outside of image");
2079 =head2 Stream reading and writing wrapper functions
2083 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
2085 Performs general read buffering for file readers that permit reading
2086 to be done through a callback.
2088 The final callback gets two parameters, a I<need> value, and a I<want>
2089 value, where I<need> is the amount of data that the file library needs
2090 to read, and I<want> is the amount of space available in the buffer
2091 maintained by these functions.
2093 This means if you need to read from a stream that you don't know the
2094 length of, you can return I<need> bytes, taking the performance hit of
2095 possibly expensive callbacks (eg. back to perl code), or if you are
2096 reading from a stream where it doesn't matter if some data is lost, or
2097 if the total length of the stream is known, you can return I<want>
2104 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
2107 if (length < gci->length - gci->cpos) {
2109 memcpy(buf, gci->buffer+gci->cpos, length);
2110 gci->cpos += length;
2115 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
2116 total += gci->length - gci->cpos;
2117 length -= gci->length - gci->cpos;
2118 buf += gci->length - gci->cpos;
2119 if (length < (int)sizeof(gci->buffer)) {
2123 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
2124 sizeof(gci->buffer))) > 0) {
2126 gci->length = did_read;
2128 copy_size = i_min(length, gci->length);
2129 memcpy(buf, gci->buffer, copy_size);
2130 gci->cpos += copy_size;
2133 length -= copy_size;
2137 /* just read the rest - too big for our buffer*/
2139 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
2149 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
2151 For use by callback file readers to initialize the reader buffer.
2153 Allocates, initializes and returns the reader buffer.
2155 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
2160 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
2161 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
2163 self->userdata = userdata;
2171 =item i_free_gen_read_data(i_gen_read_data *)
2177 void i_free_gen_read_data(i_gen_read_data *self) {
2182 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
2184 Performs write buffering for a callback based file writer.
2186 Failures are considered fatal, if a write fails then data will be
2193 i_gen_write_data *self,
2197 if (self->filledto && self->filledto+size > self->maxlength) {
2198 if (self->cb(self->userdata, self->buffer, self->filledto)) {
2206 if (self->filledto+size <= self->maxlength) {
2208 memcpy(self->buffer+self->filledto, data, size);
2209 self->filledto += size;
2212 /* doesn't fit - hand it off */
2213 return self->cb(self->userdata, data, size);
2217 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2219 Allocates and initializes the data structure used by i_gen_writer.
2221 This should be released with L<image.c/i_free_gen_write_data>
2225 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
2226 char *userdata, int max_length)
2228 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2230 self->userdata = userdata;
2231 self->maxlength = i_min(max_length, sizeof(self->buffer));
2232 if (self->maxlength < 0)
2233 self->maxlength = sizeof(self->buffer);
2240 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2242 Cleans up the write buffer.
2244 Will flush any left-over data if I<flush> is non-zero.
2246 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2248 Return zero only if flush is non-zero and info->cb() returns zero.
2254 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2256 int result = !flush ||
2257 info->filledto == 0 ||
2258 info->cb(info->userdata, info->buffer, info->filledto);
2264 struct magic_entry {
2265 unsigned char *magic;
2268 unsigned char *mask;
2272 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
2273 if (length < magic->magic_size)
2277 unsigned char *bufp = buffer,
2278 *maskp = magic->mask,
2279 *magicp = magic->magic;
2281 for (i = 0; i < magic->magic_size; ++i) {
2282 int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
2285 if ((*bufp++ & mask) != (*magicp++ & mask))
2292 return !memcmp(magic->magic, buffer, magic->magic_size);
2297 =item i_test_format_probe(io_glue *data, int length)
2299 Check the beginning of the supplied file for a 'magic number'
2304 #define FORMAT_ENTRY(magic, type) \
2305 { (unsigned char *)(magic ""), sizeof(magic)-1, type }
2306 #define FORMAT_ENTRY2(magic, type, mask) \
2307 { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
2310 i_test_format_probe(io_glue *data, int length) {
2311 static const struct magic_entry formats[] = {
2312 FORMAT_ENTRY("\xFF\xD8", "jpeg"),
2313 FORMAT_ENTRY("GIF87a", "gif"),
2314 FORMAT_ENTRY("GIF89a", "gif"),
2315 FORMAT_ENTRY("MM\0*", "tiff"),
2316 FORMAT_ENTRY("II*\0", "tiff"),
2317 FORMAT_ENTRY("BM", "bmp"),
2318 FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
2319 FORMAT_ENTRY("P1", "pnm"),
2320 FORMAT_ENTRY("P2", "pnm"),
2321 FORMAT_ENTRY("P3", "pnm"),
2322 FORMAT_ENTRY("P4", "pnm"),
2323 FORMAT_ENTRY("P5", "pnm"),
2324 FORMAT_ENTRY("P6", "pnm"),
2325 FORMAT_ENTRY("/* XPM", "xpm"),
2326 FORMAT_ENTRY("\x8aMNG", "mng"),
2327 FORMAT_ENTRY("\x8aJNG", "jng"),
2328 /* SGI RGB - with various possible parameters to avoid false positives
2330 values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
2332 FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
2333 FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
2334 FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
2335 FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
2337 FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
2339 /* different versions of PCX format
2340 http://www.fileformat.info/format/pcx/
2342 FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
2343 FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
2344 FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
2345 FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
2346 FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
2348 /* FITS - http://fits.gsfc.nasa.gov/ */
2349 FORMAT_ENTRY("SIMPLE =", "fits"),
2351 /* PSD - Photoshop */
2352 FORMAT_ENTRY("8BPS\x00\x01", "psd"),
2354 /* EPS - Encapsulated Postscript */
2355 /* only reading 18 chars, so we don't include the F in EPSF */
2356 FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
2359 FORMAT_ENTRY("\x52\xCC", "utah"),
2361 /* GZIP compressed, only matching deflate for now */
2362 FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
2364 /* bzip2 compressed */
2365 FORMAT_ENTRY("BZh", "bzip2"),
2368 http://code.google.com/speed/webp/docs/riff_container.html */
2369 FORMAT_ENTRY2("RIFF WEBP", "webp", "xxxx xxxx"),
2372 This might match a little loosely */
2373 FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"),
2375 static const struct magic_entry more_formats[] = {
2376 /* these were originally both listed as ico, but cur files can
2377 include hotspot information */
2378 FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
2379 FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
2380 FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07",
2381 "xwd", " xxxx"), /* X Windows Dump */
2385 unsigned char head[18];
2388 io_glue_commit_types(data);
2389 rc = data->readcb(data, head, 18);
2390 if (rc == -1) return NULL;
2391 data->seekcb(data, -rc, SEEK_CUR);
2393 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
2394 struct magic_entry const *entry = formats + i;
2396 if (test_magic(head, rc, entry))
2401 tga_header_verify(head))
2404 for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
2405 struct magic_entry const *entry = more_formats + i;
2407 if (test_magic(head, rc, entry))
2415 =item i_img_is_monochrome(img, &zero_is_white)
2417 =category Image Information
2419 Tests an image to check it meets our monochrome tests.
2421 The idea is that a file writer can use this to test where it should
2422 write the image in whatever bi-level format it uses, eg. C<pbm> for
2425 For performance of encoders we require monochrome images:
2435 have a palette of two colors, containing only C<(0,0,0)> and
2436 C<(255,255,255)> in either order.
2440 C<zero_is_white> is set to non-zero if the first palette entry is white.
2446 i_img_is_monochrome(i_img *im, int *zero_is_white) {
2447 if (im->type == i_palette_type
2448 && i_colorcount(im) == 2) {
2450 i_getcolors(im, 0, colors, 2);
2451 if (im->channels == 3) {
2452 if (colors[0].rgb.r == 255 &&
2453 colors[0].rgb.g == 255 &&
2454 colors[0].rgb.b == 255 &&
2455 colors[1].rgb.r == 0 &&
2456 colors[1].rgb.g == 0 &&
2457 colors[1].rgb.b == 0) {
2461 else if (colors[0].rgb.r == 0 &&
2462 colors[0].rgb.g == 0 &&
2463 colors[0].rgb.b == 0 &&
2464 colors[1].rgb.r == 255 &&
2465 colors[1].rgb.g == 255 &&
2466 colors[1].rgb.b == 255) {
2471 else if (im->channels == 1) {
2472 if (colors[0].channel[0] == 255 &&
2473 colors[1].channel[0] == 0) {
2477 else if (colors[0].channel[0] == 0 &&
2478 colors[1].channel[0] == 255) {
2490 =item i_get_file_background(im, &bg)
2494 Retrieve the file write background color tag from the image.
2496 If not present, returns black.
2502 i_get_file_background(i_img *im, i_color *bg) {
2503 if (!i_tags_get_color(&im->tags, "i_background", 0, bg)) {
2505 bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
2507 /* always full alpha */
2508 bg->channel[3] = 255;
2512 =item i_get_file_backgroundf(im, &bg)
2516 Retrieve the file write background color tag from the image as a
2517 floating point color.
2519 Implemented in terms of i_get_file_background().
2521 If not present, returns black.
2527 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
2530 i_get_file_background(im, &bg);
2531 fbg->rgba.r = Sample8ToF(bg.rgba.r);
2532 fbg->rgba.g = Sample8ToF(bg.rgba.g);
2533 fbg->rgba.b = Sample8ToF(bg.rgba.b);
2542 Arnar M. Hrafnkelsson <addi@umich.edu>
2544 Tony Cook <tony@develop-help.com>