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));
292 if (im) { myfree(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;
339 =item i_img_setmask(C<im>, C<ch_mask>)
340 =category Image Information
341 =synopsis // only channel 0 writable
342 =synopsis i_img_setmask(img, 0x01);
344 Set the image channel mask for C<im> to C<ch_mask>.
346 The image channel mask gives some control over which channels can be
347 written to in the image.
352 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
356 =item i_img_getmask(C<im>)
357 =category Image Information
358 =synopsis int mask = i_img_getmask(img);
360 Get the image channel mask for C<im>.
365 i_img_getmask(i_img *im) { return im->ch_mask; }
368 =item i_img_getchannels(C<im>)
369 =category Image Information
370 =synopsis int channels = i_img_getchannels(img);
372 Get the number of channels in C<im>.
377 i_img_getchannels(i_img *im) { return im->channels; }
380 =item i_img_get_width(C<im>)
381 =category Image Information
382 =synopsis i_img_dim width = i_img_get_width(im);
384 Returns the width in pixels of the image.
389 i_img_get_width(i_img *im) {
394 =item i_img_get_height(C<im>)
395 =category Image Information
396 =synopsis i_img_dim height = i_img_get_height(im);
398 Returns the height in pixels of the image.
403 i_img_get_height(i_img *im) {
408 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
412 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
413 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
414 the target image. pass NULL in C<trans> for non transparent i_colors.
420 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) {
422 i_img_dim x,y,t,ttx,tty,tt;
426 im_log((aIMCTX, 1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
427 "to(" i_DFp "), trans* %p)\n",
428 im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
430 if (x2<x1) { t=x1; x1=x2; x2=t; }
431 if (y2<y1) { t=y1; y1=y2; y2=t; }
443 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
444 if (tt) i_ppix(im,ttx,tty,&pv);
445 } else i_ppix(im,ttx,tty,&pv);
457 Creates a new image that is a copy of the image C<source>.
459 Tags are not copied, only the image data.
470 i_img *im = i_sametype(src, src->xsize, src->ysize);
472 im_log((aIMCTX,1,"i_copy(src %p)\n", src));
479 if (src->type == i_direct_type) {
480 if (src->bits == i_8_bits) {
482 pv = mymalloc(sizeof(i_color) * x1);
484 for (y = 0; y < y1; ++y) {
485 i_glin(src, 0, x1, y, pv);
486 i_plin(im, 0, x1, y, pv);
493 pv = mymalloc(sizeof(i_fcolor) * x1);
494 for (y = 0; y < y1; ++y) {
495 i_glinf(src, 0, x1, y, pv);
496 i_plinf(im, 0, x1, y, pv);
504 vals = mymalloc(sizeof(i_palidx) * x1);
505 for (y = 0; y < y1; ++y) {
506 i_gpal(src, 0, x1, y, vals);
507 i_ppal(im, 0, x1, y, vals);
517 http://en.wikipedia.org/wiki/Lanczos_resampling
529 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
530 else if (x == 0.0) return (1.0);
531 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
536 =item i_scaleaxis(im, value, axis)
538 Returns a new image object which is I<im> scaled by I<value> along
539 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
545 i_scaleaxis(i_img *im, double Value, int Axis) {
546 i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
547 i_img_dim LanczosWidthFactor;
552 float F, PictureValue[MAXCHANNELS];
554 i_color val,val1,val2;
556 int has_alpha = i_img_has_alpha(im);
557 int color_chans = i_img_color_channels(im);
561 im_log((aIMCTX, 1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
564 hsize = (i_img_dim)(0.5 + im->xsize * Value);
567 Value = 1.0 / im->xsize;
575 vsize = (i_img_dim)(0.5 + im->ysize * Value);
579 Value = 1.0 / im->ysize;
586 new_img = i_img_8_new(hsize, vsize, im->channels);
588 i_push_error(0, "cannot create output image");
592 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
593 LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value);
594 lMax = LanczosWidthFactor << 1;
596 l0 = mymalloc(lMax * sizeof(float));
597 l1 = mymalloc(lMax * sizeof(float));
599 for (j=0; j<jEnd; j++) {
600 OldLocation = ((double) j) / Value;
601 T = (i_img_dim) (OldLocation);
604 for (l = 0; l<lMax; l++) {
605 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
606 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
609 /* Make sure filter is normalized */
611 for(l=0; l<lMax; l++) {
615 t /= (double)LanczosWidthFactor;
617 for(l=0; l<lMax; l++) {
624 for (i=0; i<iEnd; i++) {
625 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
626 for (l=0; l<lMax; l++) {
627 i_img_dim mx = T-lMax+l+1;
628 i_img_dim Mx = T+l+1;
629 mx = (mx < 0) ? 0 : mx;
630 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
632 i_gpix(im, Mx, i, &val1);
633 i_gpix(im, mx, i, &val2);
636 i_sample_t alpha1 = val1.channel[color_chans];
637 i_sample_t alpha2 = val2.channel[color_chans];
638 for (k=0; k < color_chans; k++) {
639 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
640 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
642 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
643 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
646 for (k=0; k<im->channels; k++) {
647 PictureValue[k] += l1[l] * val1.channel[k];
648 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
654 float fa = PictureValue[color_chans] / LanczosWidthFactor;
655 int alpha = minmax(0, 255, fa+0.5);
657 for (k = 0; k < color_chans; ++k) {
658 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
659 val.channel[k]=minmax(0,255,psave);
661 val.channel[color_chans] = alpha;
664 /* zero alpha, so the pixel has no color */
665 for (k = 0; k < im->channels; ++k)
670 for(k=0;k<im->channels;k++) {
671 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
672 val.channel[k]=minmax(0,255,psave);
675 i_ppix(new_img, j, i, &val);
680 for (i=0; i<iEnd; i++) {
681 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
682 for (l=0; l < lMax; l++) {
683 i_img_dim mx = T-lMax+l+1;
684 i_img_dim Mx = T+l+1;
685 mx = (mx < 0) ? 0 : mx;
686 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
688 i_gpix(im, i, Mx, &val1);
689 i_gpix(im, i, mx, &val2);
691 i_sample_t alpha1 = val1.channel[color_chans];
692 i_sample_t alpha2 = val2.channel[color_chans];
693 for (k=0; k < color_chans; k++) {
694 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
695 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
697 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
698 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
701 for (k=0; k<im->channels; k++) {
702 PictureValue[k] += l1[l] * val1.channel[k];
703 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
708 float fa = PictureValue[color_chans] / LanczosWidthFactor;
709 int alpha = minmax(0, 255, fa+0.5);
711 for (k = 0; k < color_chans; ++k) {
712 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
713 val.channel[k]=minmax(0,255,psave);
715 val.channel[color_chans] = alpha;
718 for (k = 0; k < im->channels; ++k)
723 for(k=0;k<im->channels;k++) {
724 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
725 val.channel[k]=minmax(0,255,psave);
728 i_ppix(new_img, i, j, &val);
736 im_log((aIMCTX, 1,"(%p) <- i_scaleaxis\n", new_img));
743 =item i_scale_nn(im, scx, scy)
745 Scale by using nearest neighbor
746 Both axes scaled at the same time since
747 nothing is gained by doing it in two steps
754 i_scale_nn(i_img *im, double scx, double scy) {
756 i_img_dim nxsize,nysize,nx,ny;
761 im_log((aIMCTX, 1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
763 nxsize = (i_img_dim) ((double) im->xsize * scx);
766 scx = 1.0 / im->xsize;
768 nysize = (i_img_dim) ((double) im->ysize * scy);
771 scy = 1.0 / im->ysize;
773 im_assert(scx != 0 && scy != 0);
775 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
777 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
778 i_gpix(im,((double)nx)/scx,((double)ny)/scy,&val);
779 i_ppix(new_img,nx,ny,&val);
782 im_log((aIMCTX, 1,"(%p) <- i_scale_nn\n",new_img));
788 =item i_sametype(C<im>, C<xsize>, C<ysize>)
790 =category Image creation/destruction
791 =synopsis i_img *img = i_sametype(src, width, height);
793 Returns an image of the same type (sample size, channels, paletted/direct).
795 For paletted images the palette is copied from the source.
801 i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
804 if (src->type == i_direct_type) {
805 if (src->bits == 8) {
806 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
808 else if (src->bits == i_16_bits) {
809 return i_img_16_new(xsize, ysize, src->channels);
811 else if (src->bits == i_double_bits) {
812 return i_img_double_new(xsize, ysize, src->channels);
815 i_push_error(0, "Unknown image bits");
823 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
824 for (i = 0; i < i_colorcount(src); ++i) {
825 i_getcolors(src, i, &col, 1);
826 i_addcolors(targ, &col, 1);
834 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
836 =category Image creation/destruction
837 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
839 Returns an image of the same type (sample size).
841 For paletted images the equivalent direct type is returned.
847 i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
850 if (src->bits == 8) {
851 return i_img_empty_ch(NULL, xsize, ysize, channels);
853 else if (src->bits == i_16_bits) {
854 return i_img_16_new(xsize, ysize, channels);
856 else if (src->bits == i_double_bits) {
857 return i_img_double_new(xsize, ysize, channels);
860 i_push_error(0, "Unknown image bits");
866 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
868 Spatially transforms I<im> returning a new image.
870 opx for a length of opxl and opy for a length of opy are arrays of
871 operators that modify the x and y positions to retreive the pixel data from.
873 parm and parmlen define extra parameters that the operators may use.
875 Note that this function is largely superseded by the more flexible
876 L<transform.c/i_transform2>.
878 Returns the new image.
880 The operators for this function are defined in L<stackmach.c>.
885 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
887 i_img_dim nxsize,nysize,nx,ny;
892 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));
897 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
898 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
899 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
900 /* parm[parmlen-2]=(double)nx;
901 parm[parmlen-1]=(double)ny; */
906 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
907 rx=i_op_run(opx,opxl,parm,parmlen);
908 ry=i_op_run(opy,opyl,parm,parmlen);
909 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
910 i_gpix(im,rx,ry,&val);
911 i_ppix(new_img,nx,ny,&val);
914 im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img));
919 =item i_img_diff(im1, im2)
921 Calculates the sum of the squares of the differences between
922 correspoding channels in two images.
924 If the images are not the same size then only the common area is
925 compared, hence even if images are different sizes this function
932 i_img_diff(i_img *im1,i_img *im2) {
933 i_img_dim x, y, xb, yb;
939 im_log((aIMCTX, 1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
941 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
942 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
943 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
945 im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
946 i_DFcp(xb,yb), chb));
949 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
950 i_gpix(im1,x,y,&val1);
951 i_gpix(im2,x,y,&val2);
953 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
955 im_log((aIMCTX, 1,"i_img_diff <- (%.2f)\n",tdiff));
960 =item i_img_diffd(im1, im2)
962 Calculates the sum of the squares of the differences between
963 correspoding channels in two images.
965 If the images are not the same size then only the common area is
966 compared, hence even if images are different sizes this function
969 This is like i_img_diff() but looks at floating point samples instead.
975 i_img_diffd(i_img *im1,i_img *im2) {
976 i_img_dim x, y, xb, yb;
982 im_log((aIMCTX, 1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
984 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
985 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
986 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
988 im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
989 i_DFcp(xb, yb), chb));
992 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
993 i_gpixf(im1,x,y,&val1);
994 i_gpixf(im2,x,y,&val2);
996 for(ch=0;ch<chb;ch++) {
997 double sdiff = val1.channel[ch]-val2.channel[ch];
998 tdiff += sdiff * sdiff;
1001 im_log((aIMCTX, 1,"i_img_diffd <- (%.2f)\n",tdiff));
1007 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
1008 i_img_dim x,y,xb,yb;
1016 im_log((aIMCTX,1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
1018 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1019 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1020 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1022 im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n",
1023 i_DFcp(xb, yb), chb));
1025 for(y = 0; y < yb; y++) {
1026 for(x = 0; x < xb; x++) {
1027 i_gpixf(im1, x, y, &val1);
1028 i_gpixf(im2, x, y, &val2);
1030 for(ch = 0; ch < chb; ch++) {
1031 double sdiff = val1.channel[ch] - val2.channel[ch];
1032 if (fabs(sdiff) > epsilon) {
1033 im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n",
1034 sdiff, i_DFcp(x, y)));
1040 im_log((aIMCTX, 1,"i_img_samef <- same\n"));
1045 /* just a tiny demo of haar wavelets */
1053 i_img *new_img,*new_img2;
1054 i_color val1,val2,dval1,dval2;
1063 /* horizontal pass */
1065 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1066 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1068 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1069 i_gpix(im,x*2,y,&val1);
1070 i_gpix(im,x*2+1,y,&val2);
1071 for(ch=0;ch<im->channels;ch++) {
1072 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1073 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1075 i_ppix(new_img,x,y,&dval1);
1076 i_ppix(new_img,x+fx,y,&dval2);
1079 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1080 i_gpix(new_img,x,y*2,&val1);
1081 i_gpix(new_img,x,y*2+1,&val2);
1082 for(ch=0;ch<im->channels;ch++) {
1083 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1084 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1086 i_ppix(new_img2,x,y,&dval1);
1087 i_ppix(new_img2,x,y+fy,&dval2);
1090 i_img_destroy(new_img);
1095 =item i_count_colors(im, maxc)
1097 returns number of colors or -1
1098 to indicate that it was more than max colors
1102 /* This function has been changed and is now faster. It's using
1103 * i_gsamp instead of i_gpix */
1105 i_count_colors(i_img *im,int maxc) {
1112 i_img_dim xsize = im->xsize;
1113 i_img_dim ysize = im->ysize;
1114 int samp_cnt = 3 * xsize;
1116 if (im->channels >= 3) {
1120 channels[0] = channels[1] = channels[2] = 0;
1121 samp_chans = channels;
1126 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1129 for(y = 0; y < ysize; ) {
1130 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1131 for(x = 0; x < samp_cnt; ) {
1132 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1134 if (colorcnt > maxc) {
1145 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
1146 * (adapted from the Numerical Recipes)
1148 /* Needed by get_anonymous_color_histo */
1150 hpsort(unsigned int n, unsigned *ra) {
1175 if (j < ir && ra[j] < ra[j+1]) j++;
1187 /* This function constructs an ordered list which represents how much the
1188 * different colors are used. So for instance (100, 100, 500) means that one
1189 * color is used for 500 pixels, another for 100 pixels and another for 100
1190 * pixels. It's tuned for performance. You might not like the way I've hardcoded
1191 * the maxc ;-) and you might want to change the name... */
1192 /* Uses octt_histo */
1194 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1198 unsigned int *col_usage_it;
1203 i_img_dim xsize = im->xsize;
1204 i_img_dim ysize = im->ysize;
1205 int samp_cnt = 3 * xsize;
1208 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1210 if (im->channels >= 3) {
1214 channels[0] = channels[1] = channels[2] = 0;
1215 samp_chans = channels;
1219 for(y = 0; y < ysize; ) {
1220 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1221 for(x = 0; x < samp_cnt; ) {
1222 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1224 if (colorcnt > maxc) {
1231 /* Now that we know the number of colours... */
1232 col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1233 octt_histo(ct, &col_usage_it);
1234 hpsort(colorcnt, *col_usage);
1242 =head2 Image method wrappers
1244 These functions provide i_fsample_t functions in terms of their
1245 i_sample_t versions.
1249 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1254 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1258 for (ch = 0; ch < im->channels; ++ch)
1259 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1261 return i_ppix(im, x, y, &temp);
1265 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1269 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1273 if (i_gpix(im, x, y, &temp) == 0) {
1274 for (ch = 0; ch < im->channels; ++ch)
1275 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1283 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1288 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1291 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1298 work = mymalloc(sizeof(i_color) * (r-l));
1299 for (i = 0; i < r-l; ++i) {
1300 for (ch = 0; ch < im->channels; ++ch)
1301 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1303 ret = i_plin(im, l, r, y, work);
1318 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1323 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1326 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1333 work = mymalloc(sizeof(i_color) * (r-l));
1334 ret = i_plin(im, l, r, y, work);
1335 for (i = 0; i < r-l; ++i) {
1336 for (ch = 0; ch < im->channels; ++ch)
1337 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1353 =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)
1359 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
1360 int const *chans, int chan_count) {
1363 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1369 work = mymalloc(sizeof(i_sample_t) * (r-l));
1370 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1371 for (i = 0; i < ret; ++i) {
1372 samp[i] = Sample8ToF(work[i]);
1390 =head2 Palette wrapper functions
1392 Used for virtual images, these forward palette calls to a wrapped image,
1393 assuming the wrapped image is the first pointer in the structure that
1394 im->ext_data points at.
1398 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1402 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1403 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1407 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1411 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1412 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1416 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1420 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1421 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1425 =item i_colorcount_forward(i_img *im)
1429 int i_colorcount_forward(i_img *im) {
1430 return i_colorcount(*(i_img **)im->ext_data);
1434 =item i_maxcolors_forward(i_img *im)
1438 int i_maxcolors_forward(i_img *im) {
1439 return i_maxcolors(*(i_img **)im->ext_data);
1443 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1447 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1448 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1454 =head2 Fallback handler
1458 =item i_gsamp_bits_fb
1464 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
1465 const int *chans, int chan_count, int bits) {
1468 if (bits < 1 || bits > 32) {
1469 i_push_error(0, "Invalid bits, must be 1..32");
1473 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1476 i_img_dim count, i, w;
1479 scale = 4294967295.0;
1481 scale = (double)(1 << bits) - 1;
1489 /* make sure we have good channel numbers */
1490 for (ch = 0; ch < chan_count; ++ch) {
1491 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1492 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
1496 for (i = 0; i < w; ++i) {
1498 i_gpixf(im, l+i, y, &c);
1499 for (ch = 0; ch < chan_count; ++ch) {
1500 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1506 if (chan_count <= 0 || chan_count > im->channels) {
1507 i_push_error(0, "Invalid channel count");
1510 for (i = 0; i < w; ++i) {
1512 i_gpixf(im, l+i, y, &c);
1513 for (ch = 0; ch < chan_count; ++ch) {
1514 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1523 i_push_error(0, "Image position outside of image");
1528 struct magic_entry {
1529 unsigned char *magic;
1532 unsigned char *mask;
1536 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
1537 if (length < magic->magic_size)
1541 unsigned char *bufp = buffer,
1542 *maskp = magic->mask,
1543 *magicp = magic->magic;
1545 for (i = 0; i < magic->magic_size; ++i) {
1546 int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1549 if ((*bufp++ & mask) != (*magicp++ & mask))
1556 return !memcmp(magic->magic, buffer, magic->magic_size);
1561 =item i_test_format_probe(io_glue *data, int length)
1563 Check the beginning of the supplied file for a 'magic number'
1568 #define FORMAT_ENTRY(magic, type) \
1569 { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1570 #define FORMAT_ENTRY2(magic, type, mask) \
1571 { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1574 i_test_format_probe(io_glue *data, int length) {
1575 static const struct magic_entry formats[] = {
1576 FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1577 FORMAT_ENTRY("GIF87a", "gif"),
1578 FORMAT_ENTRY("GIF89a", "gif"),
1579 FORMAT_ENTRY("MM\0*", "tiff"),
1580 FORMAT_ENTRY("II*\0", "tiff"),
1581 FORMAT_ENTRY("BM", "bmp"),
1582 FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1583 FORMAT_ENTRY("P1", "pnm"),
1584 FORMAT_ENTRY("P2", "pnm"),
1585 FORMAT_ENTRY("P3", "pnm"),
1586 FORMAT_ENTRY("P4", "pnm"),
1587 FORMAT_ENTRY("P5", "pnm"),
1588 FORMAT_ENTRY("P6", "pnm"),
1589 FORMAT_ENTRY("/* XPM", "xpm"),
1590 FORMAT_ENTRY("\x8aMNG", "mng"),
1591 FORMAT_ENTRY("\x8aJNG", "jng"),
1592 /* SGI RGB - with various possible parameters to avoid false positives
1594 values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1596 FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1597 FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1598 FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1599 FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1601 FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
1603 /* different versions of PCX format
1604 http://www.fileformat.info/format/pcx/
1606 FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1607 FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1608 FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1609 FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1610 FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1612 /* FITS - http://fits.gsfc.nasa.gov/ */
1613 FORMAT_ENTRY("SIMPLE =", "fits"),
1615 /* PSD - Photoshop */
1616 FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1618 /* EPS - Encapsulated Postscript */
1619 /* only reading 18 chars, so we don't include the F in EPSF */
1620 FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1623 FORMAT_ENTRY("\x52\xCC", "utah"),
1625 /* GZIP compressed, only matching deflate for now */
1626 FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1628 /* bzip2 compressed */
1629 FORMAT_ENTRY("BZh", "bzip2"),
1632 http://code.google.com/speed/webp/docs/riff_container.html */
1633 FORMAT_ENTRY2("RIFF WEBP", "webp", "xxxx xxxx"),
1636 This might match a little loosely */
1637 FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"),
1639 static const struct magic_entry more_formats[] = {
1640 /* these were originally both listed as ico, but cur files can
1641 include hotspot information */
1642 FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1643 FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1644 FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07",
1645 "xwd", " xxxx"), /* X Windows Dump */
1649 unsigned char head[18];
1652 rc = i_io_peekn(data, head, 18);
1653 if (rc == -1) return NULL;
1657 fprintf(stderr, "%d bytes -", (int)rc);
1658 for (i = 0; i < rc; ++i)
1659 fprintf(stderr, " %02x", head[i]);
1660 fprintf(stderr, "\n");
1664 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
1665 struct magic_entry const *entry = formats + i;
1667 if (test_magic(head, rc, entry))
1672 tga_header_verify(head))
1675 for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
1676 struct magic_entry const *entry = more_formats + i;
1678 if (test_magic(head, rc, entry))
1686 =item i_img_is_monochrome(img, &zero_is_white)
1688 =category Image Information
1690 Tests an image to check it meets our monochrome tests.
1692 The idea is that a file writer can use this to test where it should
1693 write the image in whatever bi-level format it uses, eg. C<pbm> for
1696 For performance of encoders we require monochrome images:
1706 have a palette of two colors, containing only C<(0,0,0)> and
1707 C<(255,255,255)> in either order.
1711 C<zero_is_white> is set to non-zero if the first palette entry is white.
1717 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1718 if (im->type == i_palette_type
1719 && i_colorcount(im) == 2) {
1721 i_getcolors(im, 0, colors, 2);
1722 if (im->channels == 3) {
1723 if (colors[0].rgb.r == 255 &&
1724 colors[0].rgb.g == 255 &&
1725 colors[0].rgb.b == 255 &&
1726 colors[1].rgb.r == 0 &&
1727 colors[1].rgb.g == 0 &&
1728 colors[1].rgb.b == 0) {
1732 else if (colors[0].rgb.r == 0 &&
1733 colors[0].rgb.g == 0 &&
1734 colors[0].rgb.b == 0 &&
1735 colors[1].rgb.r == 255 &&
1736 colors[1].rgb.g == 255 &&
1737 colors[1].rgb.b == 255) {
1742 else if (im->channels == 1) {
1743 if (colors[0].channel[0] == 255 &&
1744 colors[1].channel[0] == 0) {
1748 else if (colors[0].channel[0] == 0 &&
1749 colors[1].channel[0] == 255) {
1761 =item i_get_file_background(im, &bg)
1765 Retrieve the file write background color tag from the image.
1767 If not present, C<bg> is set to black.
1769 Returns 1 if the C<i_background> tag was found and valid.
1775 i_get_file_background(i_img *im, i_color *bg) {
1776 int result = i_tags_get_color(&im->tags, "i_background", 0, bg);
1779 bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1781 /* always full alpha */
1782 bg->channel[3] = 255;
1788 =item i_get_file_backgroundf(im, &bg)
1792 Retrieve the file write background color tag from the image as a
1793 floating point color.
1795 Implemented in terms of i_get_file_background().
1797 If not present, C<bg> is set to black.
1799 Returns 1 if the C<i_background> tag was found and valid.
1805 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1807 int result = i_get_file_background(im, &bg);
1808 fbg->rgba.r = Sample8ToF(bg.rgba.r);
1809 fbg->rgba.g = Sample8ToF(bg.rgba.g);
1810 fbg->rgba.b = Sample8ToF(bg.rgba.b);
1821 Arnar M. Hrafnkelsson <addi@umich.edu>
1823 Tony Cook <tonyc@cpan.org>