1 #define IMAGER_NO_CONTEXT
9 image.c - implements most of the basic functions of Imager and much of the rest
15 c = i_color_new(red, green, blue, alpha);
23 image.c implements the basic functions to create and destroy image and
24 color objects for Imager.
26 =head1 FUNCTION REFERENCE
28 Some of these functions are internal.
35 im_context_t (*im_get_context)(void) = NULL;
41 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) )
43 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
44 void i_linker_bug_fake(void) { ceil(1); }
47 =item im_img_alloc(aIMCTX)
48 X<im_img_alloc API>X<i_img_alloc API>
49 =category Image Implementation
50 =synopsis i_img *im = im_img_alloc(aIMCTX);
51 =synopsis i_img *im = i_img_alloc();
53 Allocates a new i_img structure.
55 When implementing a new image type perform the following steps in your
56 image object creation function:
62 allocate the image with i_img_alloc().
66 initialize any function pointers or other data as needed, you can
67 overwrite the whole block if you need to.
71 initialize Imager's internal data by calling i_img_init() on the image
80 im_img_alloc(pIMCTX) {
81 return mymalloc(sizeof(i_img));
85 =item im_img_init(aIMCTX, image)
86 X<im_img_init API>X<i_img_init API>
87 =category Image Implementation
88 =synopsis im_img_init(aIMCTX, im);
89 =synopsis i_img_init(im);
91 Imager internal initialization of images.
93 See L</im_img_alloc(aIMCTX)> for more information.
99 im_img_init(pIMCTX, i_img *img) {
101 img->context = aIMCTX;
102 im_context_refinc(aIMCTX, "img_init");
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) {
123 im_log((aIMCTX,1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
125 if ( (cl=mymalloc(sizeof(i_color))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
130 im_log((aIMCTX,1,"(%p) <- ICL_new_internal\n",cl));
136 =item ICL_set_internal(cl, r, g, b, a)
138 Overwrite a color with new values.
140 cl - pointer to color object
141 r - red component (range: 0 - 255)
142 g - green component (range: 0 - 255)
143 b - blue component (range: 0 - 255)
144 a - alpha component (range: 0 - 255)
150 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
152 im_log((aIMCTX,1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
154 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
155 im_fatal(aIMCTX, 2,"malloc() error\n");
160 im_log((aIMCTX,1,"(%p) <- ICL_set_internal\n",cl));
166 =item ICL_add(dst, src, ch)
168 Add src to dst inplace - dst is modified.
170 dst - pointer to destination color object
171 src - pointer to color object that is added
172 ch - number of channels
178 ICL_add(i_color *dst,i_color *src,int ch) {
181 tmp=dst->channel[i]+src->channel[i];
182 dst->channel[i]= tmp>255 ? 255:tmp;
189 Dump color information to log - strictly for debugging.
191 cl - pointer to color object
197 ICL_info(i_color const *cl) {
199 im_log((aIMCTX, 1,"i_color_info(cl* %p)\n",cl));
200 im_log((aIMCTX, 1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
206 Destroy ancillary data for Color object.
208 cl - pointer to color object
214 ICL_DESTROY(i_color *cl) {
216 im_log((aIMCTX, 1,"ICL_DESTROY(cl* %p)\n",cl));
221 =item i_fcolor_new(double r, double g, double b, double a)
225 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
229 im_log((aIMCTX, 1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
231 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
236 im_log((aIMCTX, 1,"(%p) <- i_fcolor_new\n",cl));
242 =item i_fcolor_destroy(i_fcolor *cl)
246 void i_fcolor_destroy(i_fcolor *cl) {
251 =item i_img_exorcise(im)
261 i_img_exorcise(i_img *im) {
263 im_log((aIMCTX,1,"i_img_exorcise(im* %p)\n",im));
264 i_tags_destroy(&im->tags);
266 (im->i_f_destroy)(im);
267 if (im->idata != NULL) { myfree(im->idata); }
277 =item i_img_destroy(C<img>)
279 =category Image creation/destruction
280 =synopsis i_img_destroy(img)
282 Destroy an image object
288 i_img_destroy(i_img *im) {
290 im_log((aIMCTX, 1,"i_img_destroy(im %p)\n",im));
293 im_context_refdec(aIMCTX, "img_destroy");
297 =item i_img_info(im, info)
301 Return image information
304 info - pointer to array to return data
306 info is an array of 4 integers with the following values:
311 info[3] - channel mask
318 i_img_info(i_img *im, i_img_dim *info) {
320 im_log((aIMCTX,1,"i_img_info(im %p)\n",im));
322 im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
324 i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
325 im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata));
328 info[2] = im->channels;
329 info[3] = im->ch_mask;
333 =item i_img_setmask(C<im>, C<ch_mask>)
334 =category Image Information
335 =synopsis // only channel 0 writable
336 =synopsis i_img_setmask(img, 0x01);
338 Set the image channel mask for C<im> to C<ch_mask>.
340 The image channel mask gives some control over which channels can be
341 written to in the image.
346 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
350 =item i_img_getmask(C<im>)
351 =category Image Information
352 =synopsis int mask = i_img_getmask(img);
354 Get the image channel mask for C<im>.
359 i_img_getmask(i_img *im) { return im->ch_mask; }
362 =item i_img_getchannels(C<im>)
363 =category Image Information
364 =synopsis int channels = i_img_getchannels(img);
366 Get the number of channels in C<im>.
371 i_img_getchannels(i_img *im) { return im->channels; }
374 =item i_img_get_width(C<im>)
375 =category Image Information
376 =synopsis i_img_dim width = i_img_get_width(im);
378 Returns the width in pixels of the image.
383 i_img_get_width(i_img *im) {
388 =item i_img_get_height(C<im>)
389 =category Image Information
390 =synopsis i_img_dim height = i_img_get_height(im);
392 Returns the height in pixels of the image.
397 i_img_get_height(i_img *im) {
402 =item i_img_color_model(im)
403 =category Image Information
404 =synopsis i_color_model_t cm = i_img_color_model(im);
406 Returns the color model for the image.
408 A future version of Imager will allow for images with extra channels
409 beyond gray/rgb and alpha.
414 i_img_color_model(i_img *im) {
415 return (i_color_model_t)im->channels;
419 =item i_img_alpha_channel(im, &channel)
420 =category Image Information
421 =synopsis int alpha_channel;
422 =synopsis int has_alpha = i_img_alpha_channel(im, &alpha_channel);
424 Work out the alpha channel for an image.
426 If the image has an alpha channel, sets C<*channel> to the alpha
427 channel index and returns non-zero.
429 If the image has no alpha channel, returns zero and C<*channel> is not
432 C<channel> may be C<NULL>.
438 i_img_alpha_channel(i_img *im, int *channel) {
439 i_color_model_t model = i_img_color_model(im);
443 if (channel) *channel = (int)model - 1;
452 =item i_img_color_channels(im)
453 =category Image Information
454 =synopsis int color_channels = i_img_color_channels(im);
456 Returns the number of color channels in the image. For now this is
457 always 1 (for grayscale) or 3 (for RGB) but may be 0 in some special
458 cases in a future release of Imager.
464 i_img_color_channels(i_img *im) {
465 i_color_model_t model = i_img_color_model(im);
469 return (int)model - 1;
481 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
485 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
486 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
487 the target image. pass NULL in C<trans> for non transparent i_colors.
493 i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans) {
495 i_img_dim x,y,t,ttx,tty,tt;
499 im_log((aIMCTX, 1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
500 "to(" i_DFp "), trans* %p)\n",
501 im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
503 if (x2<x1) { t=x1; x1=x2; x2=t; }
504 if (y2<y1) { t=y1; y1=y2; y2=t; }
516 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
517 if (tt) i_ppix(im,ttx,tty,&pv);
518 } else i_ppix(im,ttx,tty,&pv);
530 Creates a new image that is a copy of the image C<source>.
532 Tags are not copied, only the image data.
543 i_img *im = i_sametype(src, src->xsize, src->ysize);
545 im_log((aIMCTX,1,"i_copy(src %p)\n", src));
552 if (src->type == i_direct_type) {
553 if (src->bits == i_8_bits) {
555 pv = mymalloc(sizeof(i_color) * x1);
557 for (y = 0; y < y1; ++y) {
558 i_glin(src, 0, x1, y, pv);
559 i_plin(im, 0, x1, y, pv);
566 pv = mymalloc(sizeof(i_fcolor) * x1);
567 for (y = 0; y < y1; ++y) {
568 i_glinf(src, 0, x1, y, pv);
569 i_plinf(im, 0, x1, y, pv);
577 vals = mymalloc(sizeof(i_palidx) * x1);
578 for (y = 0; y < y1; ++y) {
579 i_gpal(src, 0, x1, y, vals);
580 i_ppal(im, 0, x1, y, vals);
590 http://en.wikipedia.org/wiki/Lanczos_resampling
602 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
603 else if (x == 0.0) return (1.0);
604 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
609 =item i_scaleaxis(im, value, axis)
611 Returns a new image object which is I<im> scaled by I<value> along
612 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
618 i_scaleaxis(i_img *im, double Value, int Axis) {
619 i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
620 i_img_dim LanczosWidthFactor;
625 float F, PictureValue[MAXCHANNELS];
627 i_color val,val1,val2;
629 int has_alpha = i_img_has_alpha(im);
630 int color_chans = i_img_color_channels(im);
634 im_log((aIMCTX, 1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
637 hsize = (i_img_dim)(0.5 + im->xsize * Value);
640 Value = 1.0 / im->xsize;
648 vsize = (i_img_dim)(0.5 + im->ysize * Value);
652 Value = 1.0 / im->ysize;
659 new_img = i_img_8_new(hsize, vsize, im->channels);
661 i_push_error(0, "cannot create output image");
665 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
666 LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value);
667 lMax = LanczosWidthFactor << 1;
669 l0 = mymalloc(lMax * sizeof(float));
670 l1 = mymalloc(lMax * sizeof(float));
672 for (j=0; j<jEnd; j++) {
673 OldLocation = ((double) j) / Value;
674 T = (i_img_dim) (OldLocation);
677 for (l = 0; l<lMax; l++) {
678 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
679 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
682 /* Make sure filter is normalized */
684 for(l=0; l<lMax; l++) {
688 t /= (double)LanczosWidthFactor;
690 for(l=0; l<lMax; l++) {
697 for (i=0; i<iEnd; i++) {
698 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
699 for (l=0; l<lMax; l++) {
700 i_img_dim mx = T-lMax+l+1;
701 i_img_dim Mx = T+l+1;
702 mx = (mx < 0) ? 0 : mx;
703 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
705 i_gpix(im, Mx, i, &val1);
706 i_gpix(im, mx, i, &val2);
709 i_sample_t alpha1 = val1.channel[color_chans];
710 i_sample_t alpha2 = val2.channel[color_chans];
711 for (k=0; k < color_chans; k++) {
712 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
713 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
715 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
716 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
719 for (k=0; k<im->channels; k++) {
720 PictureValue[k] += l1[l] * val1.channel[k];
721 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
727 float fa = PictureValue[color_chans] / LanczosWidthFactor;
728 int alpha = minmax(0, 255, fa+0.5);
730 for (k = 0; k < color_chans; ++k) {
731 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
732 val.channel[k]=minmax(0,255,psave);
734 val.channel[color_chans] = alpha;
737 /* zero alpha, so the pixel has no color */
738 for (k = 0; k < im->channels; ++k)
743 for(k=0;k<im->channels;k++) {
744 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
745 val.channel[k]=minmax(0,255,psave);
748 i_ppix(new_img, j, i, &val);
753 for (i=0; i<iEnd; i++) {
754 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
755 for (l=0; l < lMax; l++) {
756 i_img_dim mx = T-lMax+l+1;
757 i_img_dim Mx = T+l+1;
758 mx = (mx < 0) ? 0 : mx;
759 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
761 i_gpix(im, i, Mx, &val1);
762 i_gpix(im, i, mx, &val2);
764 i_sample_t alpha1 = val1.channel[color_chans];
765 i_sample_t alpha2 = val2.channel[color_chans];
766 for (k=0; k < color_chans; k++) {
767 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
768 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
770 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
771 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
774 for (k=0; k<im->channels; k++) {
775 PictureValue[k] += l1[l] * val1.channel[k];
776 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
781 float fa = PictureValue[color_chans] / LanczosWidthFactor;
782 int alpha = minmax(0, 255, fa+0.5);
784 for (k = 0; k < color_chans; ++k) {
785 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
786 val.channel[k]=minmax(0,255,psave);
788 val.channel[color_chans] = alpha;
791 for (k = 0; k < im->channels; ++k)
796 for(k=0;k<im->channels;k++) {
797 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
798 val.channel[k]=minmax(0,255,psave);
801 i_ppix(new_img, i, j, &val);
809 im_log((aIMCTX, 1,"(%p) <- i_scaleaxis\n", new_img));
816 =item i_scale_nn(im, scx, scy)
818 Scale by using nearest neighbor
819 Both axes scaled at the same time since
820 nothing is gained by doing it in two steps
827 i_scale_nn(i_img *im, double scx, double scy) {
829 i_img_dim nxsize,nysize,nx,ny;
834 im_log((aIMCTX, 1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
836 nxsize = (i_img_dim) ((double) im->xsize * scx);
839 scx = 1.0 / im->xsize;
841 nysize = (i_img_dim) ((double) im->ysize * scy);
844 scy = 1.0 / im->ysize;
846 im_assert(scx != 0 && scy != 0);
848 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
850 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
851 i_gpix(im,((double)nx)/scx,((double)ny)/scy,&val);
852 i_ppix(new_img,nx,ny,&val);
855 im_log((aIMCTX, 1,"(%p) <- i_scale_nn\n",new_img));
861 =item i_sametype(C<im>, C<xsize>, C<ysize>)
863 =category Image creation/destruction
864 =synopsis i_img *img = i_sametype(src, width, height);
866 Returns an image of the same type (sample size, channels, paletted/direct).
868 For paletted images the palette is copied from the source.
874 i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
877 if (src->type == i_direct_type) {
878 if (src->bits == 8) {
879 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
881 else if (src->bits == i_16_bits) {
882 return i_img_16_new(xsize, ysize, src->channels);
884 else if (src->bits == i_double_bits) {
885 return i_img_double_new(xsize, ysize, src->channels);
888 i_push_error(0, "Unknown image bits");
896 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
897 for (i = 0; i < i_colorcount(src); ++i) {
898 i_getcolors(src, i, &col, 1);
899 i_addcolors(targ, &col, 1);
907 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
909 =category Image creation/destruction
910 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
912 Returns an image of the same type (sample size).
914 For paletted images the equivalent direct type is returned.
920 i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
923 if (src->bits == 8) {
924 return i_img_empty_ch(NULL, xsize, ysize, channels);
926 else if (src->bits == i_16_bits) {
927 return i_img_16_new(xsize, ysize, channels);
929 else if (src->bits == i_double_bits) {
930 return i_img_double_new(xsize, ysize, channels);
933 i_push_error(0, "Unknown image bits");
939 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
941 Spatially transforms I<im> returning a new image.
943 opx for a length of opxl and opy for a length of opy are arrays of
944 operators that modify the x and y positions to retreive the pixel data from.
946 parm and parmlen define extra parameters that the operators may use.
948 Note that this function is largely superseded by the more flexible
949 L<transform.c/i_transform2>.
951 Returns the new image.
953 The operators for this function are defined in L<stackmach.c>.
958 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
960 i_img_dim nxsize,nysize,nx,ny;
965 im_log((aIMCTX, 1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
970 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
971 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
972 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
973 /* parm[parmlen-2]=(double)nx;
974 parm[parmlen-1]=(double)ny; */
979 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
980 rx=i_op_run(opx,opxl,parm,parmlen);
981 ry=i_op_run(opy,opyl,parm,parmlen);
982 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
983 i_gpix(im,rx,ry,&val);
984 i_ppix(new_img,nx,ny,&val);
987 im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img));
992 =item i_img_diff(im1, im2)
994 Calculates the sum of the squares of the differences between
995 correspoding channels in two images.
997 If the images are not the same size then only the common area is
998 compared, hence even if images are different sizes this function
1005 i_img_diff(i_img *im1,i_img *im2) {
1006 i_img_dim x, y, xb, yb;
1012 im_log((aIMCTX, 1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
1014 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1015 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1016 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1018 im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
1019 i_DFcp(xb,yb), chb));
1022 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1023 i_gpix(im1,x,y,&val1);
1024 i_gpix(im2,x,y,&val2);
1026 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1028 im_log((aIMCTX, 1,"i_img_diff <- (%.2f)\n",tdiff));
1033 =item i_img_diffd(im1, im2)
1035 Calculates the sum of the squares of the differences between
1036 correspoding channels in two images.
1038 If the images are not the same size then only the common area is
1039 compared, hence even if images are different sizes this function
1042 This is like i_img_diff() but looks at floating point samples instead.
1048 i_img_diffd(i_img *im1,i_img *im2) {
1049 i_img_dim x, y, xb, yb;
1055 im_log((aIMCTX, 1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
1057 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1058 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1059 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1061 im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
1062 i_DFcp(xb, yb), chb));
1065 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1066 i_gpixf(im1,x,y,&val1);
1067 i_gpixf(im2,x,y,&val2);
1069 for(ch=0;ch<chb;ch++) {
1070 double sdiff = val1.channel[ch]-val2.channel[ch];
1071 tdiff += sdiff * sdiff;
1074 im_log((aIMCTX, 1,"i_img_diffd <- (%.2f)\n",tdiff));
1080 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
1081 i_img_dim x,y,xb,yb;
1089 im_log((aIMCTX,1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
1091 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1092 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1093 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1095 im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n",
1096 i_DFcp(xb, yb), chb));
1098 for(y = 0; y < yb; y++) {
1099 for(x = 0; x < xb; x++) {
1100 i_gpixf(im1, x, y, &val1);
1101 i_gpixf(im2, x, y, &val2);
1103 for(ch = 0; ch < chb; ch++) {
1104 double sdiff = val1.channel[ch] - val2.channel[ch];
1105 if (fabs(sdiff) > epsilon) {
1106 im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n",
1107 sdiff, i_DFcp(x, y)));
1113 im_log((aIMCTX, 1,"i_img_samef <- same\n"));
1118 /* just a tiny demo of haar wavelets */
1126 i_img *new_img,*new_img2;
1127 i_color val1,val2,dval1,dval2;
1136 /* horizontal pass */
1138 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1139 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1141 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1142 i_gpix(im,x*2,y,&val1);
1143 i_gpix(im,x*2+1,y,&val2);
1144 for(ch=0;ch<im->channels;ch++) {
1145 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1146 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1148 i_ppix(new_img,x,y,&dval1);
1149 i_ppix(new_img,x+fx,y,&dval2);
1152 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1153 i_gpix(new_img,x,y*2,&val1);
1154 i_gpix(new_img,x,y*2+1,&val2);
1155 for(ch=0;ch<im->channels;ch++) {
1156 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1157 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1159 i_ppix(new_img2,x,y,&dval1);
1160 i_ppix(new_img2,x,y+fy,&dval2);
1163 i_img_destroy(new_img);
1168 =item i_count_colors(im, maxc)
1170 returns number of colors or -1
1171 to indicate that it was more than max colors
1175 /* This function has been changed and is now faster. It's using
1176 * i_gsamp instead of i_gpix */
1178 i_count_colors(i_img *im,int maxc) {
1185 i_img_dim xsize = im->xsize;
1186 i_img_dim ysize = im->ysize;
1187 int samp_cnt = 3 * xsize;
1189 if (im->channels >= 3) {
1193 channels[0] = channels[1] = channels[2] = 0;
1194 samp_chans = channels;
1199 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1202 for(y = 0; y < ysize; ) {
1203 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1204 for(x = 0; x < samp_cnt; ) {
1205 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1207 if (colorcnt > maxc) {
1219 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
1220 * (adapted from the Numerical Recipes)
1222 /* Needed by get_anonymous_color_histo */
1224 hpsort(unsigned int n, unsigned *ra) {
1249 if (j < ir && ra[j] < ra[j+1]) j++;
1261 /* This function constructs an ordered list which represents how much the
1262 * different colors are used. So for instance (100, 100, 500) means that one
1263 * color is used for 500 pixels, another for 100 pixels and another for 100
1264 * pixels. It's tuned for performance. You might not like the way I've hardcoded
1265 * the maxc ;-) and you might want to change the name... */
1266 /* Uses octt_histo */
1268 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1272 unsigned int *col_usage_it;
1277 i_img_dim xsize = im->xsize;
1278 i_img_dim ysize = im->ysize;
1279 int samp_cnt = 3 * xsize;
1282 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1284 if (im->channels >= 3) {
1288 channels[0] = channels[1] = channels[2] = 0;
1289 samp_chans = channels;
1293 for(y = 0; y < ysize; ) {
1294 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1295 for(x = 0; x < samp_cnt; ) {
1296 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1298 if (colorcnt > maxc) {
1306 /* Now that we know the number of colours... */
1307 col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1308 octt_histo(ct, &col_usage_it);
1309 hpsort(colorcnt, *col_usage);
1317 =head2 Image method wrappers
1319 These functions provide i_fsample_t functions in terms of their
1320 i_sample_t versions.
1324 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1329 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1333 for (ch = 0; ch < im->channels; ++ch)
1334 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1336 return i_ppix(im, x, y, &temp);
1340 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1344 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1348 if (i_gpix(im, x, y, &temp) == 0) {
1349 for (ch = 0; ch < im->channels; ++ch)
1350 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1358 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1363 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1366 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1373 work = mymalloc(sizeof(i_color) * (r-l));
1374 for (i = 0; i < r-l; ++i) {
1375 for (ch = 0; ch < im->channels; ++ch)
1376 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1378 ret = i_plin(im, l, r, y, work);
1393 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1398 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1401 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1408 work = mymalloc(sizeof(i_color) * (r-l));
1409 ret = i_plin(im, l, r, y, work);
1410 for (i = 0; i < r-l; ++i) {
1411 for (ch = 0; ch < im->channels; ++ch)
1412 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1428 =item i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int *chans, int chan_count)
1434 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
1435 int const *chans, int chan_count) {
1438 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1444 work = mymalloc(sizeof(i_sample_t) * (r-l));
1445 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1446 for (i = 0; i < ret; ++i) {
1447 samp[i] = Sample8ToF(work[i]);
1465 =head2 Palette wrapper functions
1467 Used for virtual images, these forward palette calls to a wrapped image,
1468 assuming the wrapped image is the first pointer in the structure that
1469 im->ext_data points at.
1473 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1477 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1478 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1482 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1486 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1487 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1491 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1495 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1496 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1500 =item i_colorcount_forward(i_img *im)
1504 int i_colorcount_forward(i_img *im) {
1505 return i_colorcount(*(i_img **)im->ext_data);
1509 =item i_maxcolors_forward(i_img *im)
1513 int i_maxcolors_forward(i_img *im) {
1514 return i_maxcolors(*(i_img **)im->ext_data);
1518 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1522 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1523 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1529 =head2 Fallback handler
1533 =item i_gsamp_bits_fb
1539 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
1540 const int *chans, int chan_count, int bits) {
1543 if (bits < 1 || bits > 32) {
1544 i_push_error(0, "Invalid bits, must be 1..32");
1548 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1551 i_img_dim count, i, w;
1554 scale = 4294967295.0;
1556 scale = (double)(1 << bits) - 1;
1564 /* make sure we have good channel numbers */
1565 for (ch = 0; ch < chan_count; ++ch) {
1566 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1567 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
1571 for (i = 0; i < w; ++i) {
1573 i_gpixf(im, l+i, y, &c);
1574 for (ch = 0; ch < chan_count; ++ch) {
1575 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1581 if (chan_count <= 0 || chan_count > im->channels) {
1582 i_push_error(0, "Invalid channel count");
1585 for (i = 0; i < w; ++i) {
1587 i_gpixf(im, l+i, y, &c);
1588 for (ch = 0; ch < chan_count; ++ch) {
1589 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1598 i_push_error(0, "Image position outside of image");
1604 test_magic(unsigned char *buffer, size_t length, struct file_magic_entry const *magic) {
1605 if (length < magic->magic_size)
1609 unsigned char *bufp = buffer,
1610 *maskp = magic->mask,
1611 *magicp = magic->magic;
1613 for (i = 0; i < magic->magic_size; ++i) {
1614 int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1617 if ((*bufp++ & mask) != (*magicp++ & mask))
1624 return !memcmp(magic->magic, buffer, magic->magic_size);
1629 =item i_test_format_probe(io_glue *data, int length)
1631 Check the beginning of the supplied file for a 'magic number'
1636 #define FORMAT_ENTRY(magic, type) \
1637 { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1638 #define FORMAT_ENTRY2(magic, type, mask) \
1639 { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1642 im_test_format_probe(im_context_t ctx, io_glue *data, int length) {
1643 static const struct file_magic_entry formats[] = {
1644 FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1645 FORMAT_ENTRY("GIF87a", "gif"),
1646 FORMAT_ENTRY("GIF89a", "gif"),
1647 FORMAT_ENTRY("MM\0*", "tiff"),
1648 FORMAT_ENTRY("II*\0", "tiff"),
1649 FORMAT_ENTRY("BM", "bmp"),
1650 FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1651 FORMAT_ENTRY("P1", "pnm"),
1652 FORMAT_ENTRY("P2", "pnm"),
1653 FORMAT_ENTRY("P3", "pnm"),
1654 FORMAT_ENTRY("P4", "pnm"),
1655 FORMAT_ENTRY("P5", "pnm"),
1656 FORMAT_ENTRY("P6", "pnm"),
1657 FORMAT_ENTRY("/* XPM", "xpm"),
1658 FORMAT_ENTRY("\x8aMNG", "mng"),
1659 FORMAT_ENTRY("\x8aJNG", "jng"),
1660 /* SGI RGB - with various possible parameters to avoid false positives
1662 values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1664 FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1665 FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1666 FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1667 FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1669 FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
1671 /* different versions of PCX format
1672 http://www.fileformat.info/format/pcx/
1674 FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1675 FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1676 FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1677 FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1678 FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1680 /* FITS - http://fits.gsfc.nasa.gov/ */
1681 FORMAT_ENTRY("SIMPLE =", "fits"),
1683 /* PSD - Photoshop */
1684 FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1686 /* EPS - Encapsulated Postscript */
1687 /* only reading 18 chars, so we don't include the F in EPSF */
1688 FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1691 FORMAT_ENTRY("\x52\xCC", "utah"),
1693 /* GZIP compressed, only matching deflate for now */
1694 FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1696 /* bzip2 compressed */
1697 FORMAT_ENTRY("BZh", "bzip2"),
1700 http://code.google.com/speed/webp/docs/riff_container.html */
1701 FORMAT_ENTRY2("RIFF WEBP", "webp", "xxxx xxxx"),
1704 This might match a little loosely */
1705 FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"),
1707 /* FLIF - Free Lossless Image Format - https://flif.info/spec.html */
1708 FORMAT_ENTRY("FLIF", "flif")
1710 static const struct file_magic_entry more_formats[] = {
1711 /* these were originally both listed as ico, but cur files can
1712 include hotspot information */
1713 FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1714 FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1715 FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07",
1716 "xwd", " xxxx"), /* X Windows Dump */
1720 unsigned char head[18];
1723 rc = i_io_peekn(data, head, 18);
1724 if (rc == -1) return NULL;
1728 fprintf(stderr, "%d bytes -", (int)rc);
1729 for (i = 0; i < rc; ++i)
1730 fprintf(stderr, " %02x", head[i]);
1731 fprintf(stderr, "\n");
1736 im_file_magic *p = ctx->file_magic;
1738 if (test_magic(head, rc, &p->m)) {
1745 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
1746 struct file_magic_entry const *entry = formats + i;
1748 if (test_magic(head, rc, entry))
1753 tga_header_verify(head))
1756 for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
1757 struct file_magic_entry const *entry = more_formats + i;
1759 if (test_magic(head, rc, entry))
1767 =item i_img_is_monochrome(img, &zero_is_white)
1769 =category Image Information
1771 Tests an image to check it meets our monochrome tests.
1773 The idea is that a file writer can use this to test where it should
1774 write the image in whatever bi-level format it uses, eg. C<pbm> for
1777 For performance of encoders we require monochrome images:
1787 have a palette of two colors, containing only C<(0,0,0)> and
1788 C<(255,255,255)> in either order.
1792 C<zero_is_white> is set to non-zero if the first palette entry is white.
1798 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1799 if (im->type == i_palette_type
1800 && i_colorcount(im) == 2) {
1802 if (!i_getcolors(im, 0, colors, 2))
1804 if (im->channels == 3) {
1805 if (colors[0].rgb.r == 255 &&
1806 colors[0].rgb.g == 255 &&
1807 colors[0].rgb.b == 255 &&
1808 colors[1].rgb.r == 0 &&
1809 colors[1].rgb.g == 0 &&
1810 colors[1].rgb.b == 0) {
1814 else if (colors[0].rgb.r == 0 &&
1815 colors[0].rgb.g == 0 &&
1816 colors[0].rgb.b == 0 &&
1817 colors[1].rgb.r == 255 &&
1818 colors[1].rgb.g == 255 &&
1819 colors[1].rgb.b == 255) {
1824 else if (im->channels == 1) {
1825 if (colors[0].channel[0] == 255 &&
1826 colors[1].channel[0] == 0) {
1830 else if (colors[0].channel[0] == 0 &&
1831 colors[1].channel[0] == 255) {
1843 =item i_get_file_background(im, &bg)
1847 Retrieve the file write background color tag from the image.
1849 If not present, C<bg> is set to black.
1851 Returns 1 if the C<i_background> tag was found and valid.
1857 i_get_file_background(i_img *im, i_color *bg) {
1858 int result = i_tags_get_color(&im->tags, "i_background", 0, bg);
1861 bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1863 /* always full alpha */
1864 bg->channel[3] = 255;
1870 =item i_get_file_backgroundf(im, &bg)
1874 Retrieve the file write background color tag from the image as a
1875 floating point color.
1877 Implemented in terms of i_get_file_background().
1879 If not present, C<bg> is set to black.
1881 Returns 1 if the C<i_background> tag was found and valid.
1887 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1889 int result = i_get_file_background(im, &bg);
1890 fbg->rgba.r = Sample8ToF(bg.rgba.r);
1891 fbg->rgba.g = Sample8ToF(bg.rgba.g);
1892 fbg->rgba.b = Sample8ToF(bg.rgba.b);
1903 Arnar M. Hrafnkelsson <addi@umich.edu>
1905 Tony Cook <tonyc@cpan.org>