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); }
48 =category Image Implementation
50 Allocates a new i_img structure.
52 When implementing a new image type perform the following steps in your
53 image object creation function:
59 allocate the image with i_img_alloc().
63 initialize any function pointers or other data as needed, you can
64 overwrite the whole block if you need to.
68 initialize Imager's internal data by calling i_img_init() on the image
77 im_img_alloc(pIMCTX) {
78 return mymalloc(sizeof(i_img));
82 =item i_img_init(C<img>)
83 =category Image Implementation
85 Imager internal initialization of images.
87 Currently this does very little, in the future it may be used to
88 support threads, or color profiles.
94 im_img_init(pIMCTX, i_img *img) {
96 img->context = aIMCTX;
97 im_context_refinc(aIMCTX, "img_init");
101 =item ICL_new_internal(r, g, b, a)
103 Return a new color object with values passed to it.
105 r - red component (range: 0 - 255)
106 g - green component (range: 0 - 255)
107 b - blue component (range: 0 - 255)
108 a - alpha component (range: 0 - 255)
114 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
118 im_log((aIMCTX,1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
120 if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
125 im_log((aIMCTX,1,"(%p) <- ICL_new_internal\n",cl));
131 =item ICL_set_internal(cl, r, g, b, a)
133 Overwrite a color with new values.
135 cl - pointer to color object
136 r - red component (range: 0 - 255)
137 g - green component (range: 0 - 255)
138 b - blue component (range: 0 - 255)
139 a - alpha component (range: 0 - 255)
145 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
147 im_log((aIMCTX,1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
149 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
150 i_fatal(2,"malloc() error\n");
155 im_log((aIMCTX,1,"(%p) <- ICL_set_internal\n",cl));
161 =item ICL_add(dst, src, ch)
163 Add src to dst inplace - dst is modified.
165 dst - pointer to destination color object
166 src - pointer to color object that is added
167 ch - number of channels
173 ICL_add(i_color *dst,i_color *src,int ch) {
176 tmp=dst->channel[i]+src->channel[i];
177 dst->channel[i]= tmp>255 ? 255:tmp;
184 Dump color information to log - strictly for debugging.
186 cl - pointer to color object
192 ICL_info(i_color const *cl) {
194 im_log((aIMCTX, 1,"i_color_info(cl* %p)\n",cl));
195 im_log((aIMCTX, 1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
201 Destroy ancillary data for Color object.
203 cl - pointer to color object
209 ICL_DESTROY(i_color *cl) {
211 im_log((aIMCTX, 1,"ICL_DESTROY(cl* %p)\n",cl));
216 =item i_fcolor_new(double r, double g, double b, double a)
220 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
224 im_log((aIMCTX, 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 im_log((aIMCTX, 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 i_img_exorcise(im)
256 i_img_exorcise(i_img *im) {
258 im_log((aIMCTX,1,"i_img_exorcise(im* %p)\n",im));
259 i_tags_destroy(&im->tags);
261 (im->i_f_destroy)(im);
262 if (im->idata != NULL) { myfree(im->idata); }
272 =item i_img_destroy(C<img>)
274 =category Image creation/destruction
275 =synopsis i_img_destroy(img)
277 Destroy an image object
283 i_img_destroy(i_img *im) {
285 im_log((aIMCTX, 1,"i_img_destroy(im %p)\n",im));
287 if (im) { myfree(im); }
288 im_context_refdec(aIMCTX, "img_destroy");
292 =item i_img_info(im, info)
296 Return image information
299 info - pointer to array to return data
301 info is an array of 4 integers with the following values:
306 info[3] - channel mask
313 i_img_info(i_img *im, i_img_dim *info) {
315 im_log((aIMCTX,1,"i_img_info(im %p)\n",im));
317 im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
319 i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
320 im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata));
323 info[2] = im->channels;
324 info[3] = im->ch_mask;
334 =item i_img_setmask(C<im>, C<ch_mask>)
335 =category Image Information
336 =synopsis // only channel 0 writable
337 =synopsis i_img_setmask(img, 0x01);
339 Set the image channel mask for C<im> to C<ch_mask>.
341 The image channel mask gives some control over which channels can be
342 written to in the image.
347 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
351 =item i_img_getmask(C<im>)
352 =category Image Information
353 =synopsis int mask = i_img_getmask(img);
355 Get the image channel mask for C<im>.
360 i_img_getmask(i_img *im) { return im->ch_mask; }
363 =item i_img_getchannels(C<im>)
364 =category Image Information
365 =synopsis int channels = i_img_getchannels(img);
367 Get the number of channels in C<im>.
372 i_img_getchannels(i_img *im) { return im->channels; }
375 =item i_img_get_width(C<im>)
376 =category Image Information
377 =synopsis i_img_dim width = i_img_get_width(im);
379 Returns the width in pixels of the image.
384 i_img_get_width(i_img *im) {
389 =item i_img_get_height(C<im>)
390 =category Image Information
391 =synopsis i_img_dim height = i_img_get_height(im);
393 Returns the height in pixels of the image.
398 i_img_get_height(i_img *im) {
403 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
407 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
408 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
409 the target image. pass NULL in C<trans> for non transparent i_colors.
415 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) {
417 i_img_dim x,y,t,ttx,tty,tt;
421 im_log((aIMCTX, 1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
422 "to(" i_DFp "), trans* %p)\n",
423 im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
425 if (x2<x1) { t=x1; x1=x2; x2=t; }
426 if (y2<y1) { t=y1; y1=y2; y2=t; }
438 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
439 if (tt) i_ppix(im,ttx,tty,&pv);
440 } else i_ppix(im,ttx,tty,&pv);
452 Creates a new image that is a copy of the image C<source>.
454 Tags are not copied, only the image data.
465 i_img *im = i_sametype(src, src->xsize, src->ysize);
467 im_log((aIMCTX,1,"i_copy(src %p)\n", src));
474 if (src->type == i_direct_type) {
475 if (src->bits == i_8_bits) {
477 pv = mymalloc(sizeof(i_color) * x1);
479 for (y = 0; y < y1; ++y) {
480 i_glin(src, 0, x1, y, pv);
481 i_plin(im, 0, x1, y, pv);
488 pv = mymalloc(sizeof(i_fcolor) * x1);
489 for (y = 0; y < y1; ++y) {
490 i_glinf(src, 0, x1, y, pv);
491 i_plinf(im, 0, x1, y, pv);
499 vals = mymalloc(sizeof(i_palidx) * x1);
500 for (y = 0; y < y1; ++y) {
501 i_gpal(src, 0, x1, y, vals);
502 i_ppal(im, 0, x1, y, vals);
512 http://en.wikipedia.org/wiki/Lanczos_resampling
524 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
525 else if (x == 0.0) return (1.0);
526 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
531 =item i_scaleaxis(im, value, axis)
533 Returns a new image object which is I<im> scaled by I<value> along
534 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
540 i_scaleaxis(i_img *im, double Value, int Axis) {
541 i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
542 i_img_dim LanczosWidthFactor;
547 float F, PictureValue[MAXCHANNELS];
549 i_color val,val1,val2;
551 int has_alpha = i_img_has_alpha(im);
552 int color_chans = i_img_color_channels(im);
556 im_log((aIMCTX, 1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
559 hsize = (i_img_dim)(0.5 + im->xsize * Value);
562 Value = 1.0 / im->xsize;
570 vsize = (i_img_dim)(0.5 + im->ysize * Value);
574 Value = 1.0 / im->ysize;
581 new_img = i_img_8_new(hsize, vsize, im->channels);
583 i_push_error(0, "cannot create output image");
587 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
588 LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value);
589 lMax = LanczosWidthFactor << 1;
591 l0 = mymalloc(lMax * sizeof(float));
592 l1 = mymalloc(lMax * sizeof(float));
594 for (j=0; j<jEnd; j++) {
595 OldLocation = ((double) j) / Value;
596 T = (i_img_dim) (OldLocation);
599 for (l = 0; l<lMax; l++) {
600 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
601 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
604 /* Make sure filter is normalized */
606 for(l=0; l<lMax; l++) {
610 t /= (double)LanczosWidthFactor;
612 for(l=0; l<lMax; l++) {
619 for (i=0; i<iEnd; i++) {
620 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
621 for (l=0; l<lMax; l++) {
622 i_img_dim mx = T-lMax+l+1;
623 i_img_dim Mx = T+l+1;
624 mx = (mx < 0) ? 0 : mx;
625 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
627 i_gpix(im, Mx, i, &val1);
628 i_gpix(im, mx, i, &val2);
631 i_sample_t alpha1 = val1.channel[color_chans];
632 i_sample_t alpha2 = val2.channel[color_chans];
633 for (k=0; k < color_chans; k++) {
634 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
635 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
637 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
638 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
641 for (k=0; k<im->channels; k++) {
642 PictureValue[k] += l1[l] * val1.channel[k];
643 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
649 float fa = PictureValue[color_chans] / LanczosWidthFactor;
650 int alpha = minmax(0, 255, fa+0.5);
652 for (k = 0; k < color_chans; ++k) {
653 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
654 val.channel[k]=minmax(0,255,psave);
656 val.channel[color_chans] = alpha;
659 /* zero alpha, so the pixel has no color */
660 for (k = 0; k < im->channels; ++k)
665 for(k=0;k<im->channels;k++) {
666 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
667 val.channel[k]=minmax(0,255,psave);
670 i_ppix(new_img, j, i, &val);
675 for (i=0; i<iEnd; i++) {
676 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
677 for (l=0; l < lMax; l++) {
678 i_img_dim mx = T-lMax+l+1;
679 i_img_dim Mx = T+l+1;
680 mx = (mx < 0) ? 0 : mx;
681 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
683 i_gpix(im, i, Mx, &val1);
684 i_gpix(im, i, mx, &val2);
686 i_sample_t alpha1 = val1.channel[color_chans];
687 i_sample_t alpha2 = val2.channel[color_chans];
688 for (k=0; k < color_chans; k++) {
689 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
690 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
692 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
693 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
696 for (k=0; k<im->channels; k++) {
697 PictureValue[k] += l1[l] * val1.channel[k];
698 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
703 float fa = PictureValue[color_chans] / LanczosWidthFactor;
704 int alpha = minmax(0, 255, fa+0.5);
706 for (k = 0; k < color_chans; ++k) {
707 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
708 val.channel[k]=minmax(0,255,psave);
710 val.channel[color_chans] = alpha;
713 for (k = 0; k < im->channels; ++k)
718 for(k=0;k<im->channels;k++) {
719 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
720 val.channel[k]=minmax(0,255,psave);
723 i_ppix(new_img, i, j, &val);
731 im_log((aIMCTX, 1,"(%p) <- i_scaleaxis\n", new_img));
738 =item i_scale_nn(im, scx, scy)
740 Scale by using nearest neighbor
741 Both axes scaled at the same time since
742 nothing is gained by doing it in two steps
749 i_scale_nn(i_img *im, double scx, double scy) {
751 i_img_dim nxsize,nysize,nx,ny;
756 im_log((aIMCTX, 1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
758 nxsize = (i_img_dim) ((double) im->xsize * scx);
761 scx = 1.0 / im->xsize;
763 nysize = (i_img_dim) ((double) im->ysize * scy);
766 scy = 1.0 / im->ysize;
768 im_assert(scx != 0 && scy != 0);
770 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
772 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
773 i_gpix(im,((double)nx)/scx,((double)ny)/scy,&val);
774 i_ppix(new_img,nx,ny,&val);
777 im_log((aIMCTX, 1,"(%p) <- i_scale_nn\n",new_img));
783 =item i_sametype(C<im>, C<xsize>, C<ysize>)
785 =category Image creation/destruction
786 =synopsis i_img *img = i_sametype(src, width, height);
788 Returns an image of the same type (sample size, channels, paletted/direct).
790 For paletted images the palette is copied from the source.
796 i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
799 if (src->type == i_direct_type) {
800 if (src->bits == 8) {
801 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
803 else if (src->bits == i_16_bits) {
804 return i_img_16_new(xsize, ysize, src->channels);
806 else if (src->bits == i_double_bits) {
807 return i_img_double_new(xsize, ysize, src->channels);
810 i_push_error(0, "Unknown image bits");
818 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
819 for (i = 0; i < i_colorcount(src); ++i) {
820 i_getcolors(src, i, &col, 1);
821 i_addcolors(targ, &col, 1);
829 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
831 =category Image creation/destruction
832 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
834 Returns an image of the same type (sample size).
836 For paletted images the equivalent direct type is returned.
842 i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
845 if (src->bits == 8) {
846 return i_img_empty_ch(NULL, xsize, ysize, channels);
848 else if (src->bits == i_16_bits) {
849 return i_img_16_new(xsize, ysize, channels);
851 else if (src->bits == i_double_bits) {
852 return i_img_double_new(xsize, ysize, channels);
855 i_push_error(0, "Unknown image bits");
861 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
863 Spatially transforms I<im> returning a new image.
865 opx for a length of opxl and opy for a length of opy are arrays of
866 operators that modify the x and y positions to retreive the pixel data from.
868 parm and parmlen define extra parameters that the operators may use.
870 Note that this function is largely superseded by the more flexible
871 L<transform.c/i_transform2>.
873 Returns the new image.
875 The operators for this function are defined in L<stackmach.c>.
880 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
882 i_img_dim nxsize,nysize,nx,ny;
887 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));
892 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
893 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
894 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
895 /* parm[parmlen-2]=(double)nx;
896 parm[parmlen-1]=(double)ny; */
901 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
902 rx=i_op_run(opx,opxl,parm,parmlen);
903 ry=i_op_run(opy,opyl,parm,parmlen);
904 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
905 i_gpix(im,rx,ry,&val);
906 i_ppix(new_img,nx,ny,&val);
909 im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img));
914 =item i_img_diff(im1, im2)
916 Calculates the sum of the squares of the differences between
917 correspoding channels in two images.
919 If the images are not the same size then only the common area is
920 compared, hence even if images are different sizes this function
927 i_img_diff(i_img *im1,i_img *im2) {
928 i_img_dim x, y, xb, yb;
934 im_log((aIMCTX, 1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
936 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
937 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
938 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
940 im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
941 i_DFcp(xb,yb), chb));
944 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
945 i_gpix(im1,x,y,&val1);
946 i_gpix(im2,x,y,&val2);
948 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
950 im_log((aIMCTX, 1,"i_img_diff <- (%.2f)\n",tdiff));
955 =item i_img_diffd(im1, im2)
957 Calculates the sum of the squares of the differences between
958 correspoding channels in two images.
960 If the images are not the same size then only the common area is
961 compared, hence even if images are different sizes this function
964 This is like i_img_diff() but looks at floating point samples instead.
970 i_img_diffd(i_img *im1,i_img *im2) {
971 i_img_dim x, y, xb, yb;
977 im_log((aIMCTX, 1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
979 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
980 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
981 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
983 im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
984 i_DFcp(xb, yb), chb));
987 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
988 i_gpixf(im1,x,y,&val1);
989 i_gpixf(im2,x,y,&val2);
991 for(ch=0;ch<chb;ch++) {
992 double sdiff = val1.channel[ch]-val2.channel[ch];
993 tdiff += sdiff * sdiff;
996 im_log((aIMCTX, 1,"i_img_diffd <- (%.2f)\n",tdiff));
1002 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
1003 i_img_dim x,y,xb,yb;
1011 im_log((aIMCTX,1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
1013 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1014 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1015 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1017 im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n",
1018 i_DFcp(xb, yb), chb));
1020 for(y = 0; y < yb; y++) {
1021 for(x = 0; x < xb; x++) {
1022 i_gpixf(im1, x, y, &val1);
1023 i_gpixf(im2, x, y, &val2);
1025 for(ch = 0; ch < chb; ch++) {
1026 double sdiff = val1.channel[ch] - val2.channel[ch];
1027 if (fabs(sdiff) > epsilon) {
1028 im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n",
1029 sdiff, i_DFcp(x, y)));
1035 im_log((aIMCTX, 1,"i_img_samef <- same\n"));
1040 /* just a tiny demo of haar wavelets */
1048 i_img *new_img,*new_img2;
1049 i_color val1,val2,dval1,dval2;
1058 /* horizontal pass */
1060 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1061 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1064 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1065 i_gpix(im,x*2,y,&val1);
1066 i_gpix(im,x*2+1,y,&val2);
1067 for(ch=0;ch<im->channels;ch++) {
1068 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1069 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1071 i_ppix(new_img,x,y,&dval1);
1072 i_ppix(new_img,x+fx,y,&dval2);
1075 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1076 i_gpix(new_img,x,y*2,&val1);
1077 i_gpix(new_img,x,y*2+1,&val2);
1078 for(ch=0;ch<im->channels;ch++) {
1079 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1080 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1082 i_ppix(new_img2,x,y,&dval1);
1083 i_ppix(new_img2,x,y+fy,&dval2);
1086 i_img_destroy(new_img);
1091 =item i_count_colors(im, maxc)
1093 returns number of colors or -1
1094 to indicate that it was more than max colors
1098 /* This function has been changed and is now faster. It's using
1099 * i_gsamp instead of i_gpix */
1101 i_count_colors(i_img *im,int maxc) {
1108 i_img_dim xsize = im->xsize;
1109 i_img_dim ysize = im->ysize;
1110 int samp_cnt = 3 * xsize;
1112 if (im->channels >= 3) {
1116 channels[0] = channels[1] = channels[2] = 0;
1117 samp_chans = channels;
1122 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1125 for(y = 0; y < ysize; ) {
1126 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1127 for(x = 0; x < samp_cnt; ) {
1128 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1130 if (colorcnt > maxc) {
1141 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
1142 * (adapted from the Numerical Recipes)
1144 /* Needed by get_anonymous_color_histo */
1146 hpsort(unsigned int n, unsigned *ra) {
1171 if (j < ir && ra[j] < ra[j+1]) j++;
1183 /* This function constructs an ordered list which represents how much the
1184 * different colors are used. So for instance (100, 100, 500) means that one
1185 * color is used for 500 pixels, another for 100 pixels and another for 100
1186 * pixels. It's tuned for performance. You might not like the way I've hardcoded
1187 * the maxc ;-) and you might want to change the name... */
1188 /* Uses octt_histo */
1190 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1194 unsigned int *col_usage_it;
1199 i_img_dim xsize = im->xsize;
1200 i_img_dim ysize = im->ysize;
1201 int samp_cnt = 3 * xsize;
1204 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1206 if (im->channels >= 3) {
1210 channels[0] = channels[1] = channels[2] = 0;
1211 samp_chans = channels;
1215 for(y = 0; y < ysize; ) {
1216 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1217 for(x = 0; x < samp_cnt; ) {
1218 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1220 if (colorcnt > maxc) {
1227 /* Now that we know the number of colours... */
1228 col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1229 octt_histo(ct, &col_usage_it);
1230 hpsort(colorcnt, *col_usage);
1238 =head2 Image method wrappers
1240 These functions provide i_fsample_t functions in terms of their
1241 i_sample_t versions.
1245 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1250 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1254 for (ch = 0; ch < im->channels; ++ch)
1255 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1257 return i_ppix(im, x, y, &temp);
1261 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1265 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1269 if (i_gpix(im, x, y, &temp) == 0) {
1270 for (ch = 0; ch < im->channels; ++ch)
1271 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1279 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1284 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1287 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1294 work = mymalloc(sizeof(i_color) * (r-l));
1295 for (i = 0; i < r-l; ++i) {
1296 for (ch = 0; ch < im->channels; ++ch)
1297 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1299 ret = i_plin(im, l, r, y, work);
1314 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1319 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1322 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1329 work = mymalloc(sizeof(i_color) * (r-l));
1330 ret = i_plin(im, l, r, y, work);
1331 for (i = 0; i < r-l; ++i) {
1332 for (ch = 0; ch < im->channels; ++ch)
1333 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1349 =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)
1355 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
1356 int const *chans, int chan_count) {
1359 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1365 work = mymalloc(sizeof(i_sample_t) * (r-l));
1366 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1367 for (i = 0; i < ret; ++i) {
1368 samp[i] = Sample8ToF(work[i]);
1386 =head2 Palette wrapper functions
1388 Used for virtual images, these forward palette calls to a wrapped image,
1389 assuming the wrapped image is the first pointer in the structure that
1390 im->ext_data points at.
1394 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1398 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1399 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1403 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1407 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1408 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1412 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1416 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1417 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1421 =item i_colorcount_forward(i_img *im)
1425 int i_colorcount_forward(i_img *im) {
1426 return i_colorcount(*(i_img **)im->ext_data);
1430 =item i_maxcolors_forward(i_img *im)
1434 int i_maxcolors_forward(i_img *im) {
1435 return i_maxcolors(*(i_img **)im->ext_data);
1439 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1443 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1444 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1450 =head2 Fallback handler
1454 =item i_gsamp_bits_fb
1460 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
1461 const int *chans, int chan_count, int bits) {
1464 if (bits < 1 || bits > 32) {
1465 i_push_error(0, "Invalid bits, must be 1..32");
1469 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1472 i_img_dim count, i, w;
1475 scale = 4294967295.0;
1477 scale = (double)(1 << bits) - 1;
1485 /* make sure we have good channel numbers */
1486 for (ch = 0; ch < chan_count; ++ch) {
1487 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1488 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
1492 for (i = 0; i < w; ++i) {
1494 i_gpixf(im, l+i, y, &c);
1495 for (ch = 0; ch < chan_count; ++ch) {
1496 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1502 if (chan_count <= 0 || chan_count > im->channels) {
1503 i_push_error(0, "Invalid channel count");
1506 for (i = 0; i < w; ++i) {
1508 i_gpixf(im, l+i, y, &c);
1509 for (ch = 0; ch < chan_count; ++ch) {
1510 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1519 i_push_error(0, "Image position outside of image");
1524 struct magic_entry {
1525 unsigned char *magic;
1528 unsigned char *mask;
1532 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
1533 if (length < magic->magic_size)
1537 unsigned char *bufp = buffer,
1538 *maskp = magic->mask,
1539 *magicp = magic->magic;
1541 for (i = 0; i < magic->magic_size; ++i) {
1542 int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1545 if ((*bufp++ & mask) != (*magicp++ & mask))
1552 return !memcmp(magic->magic, buffer, magic->magic_size);
1557 =item i_test_format_probe(io_glue *data, int length)
1559 Check the beginning of the supplied file for a 'magic number'
1564 #define FORMAT_ENTRY(magic, type) \
1565 { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1566 #define FORMAT_ENTRY2(magic, type, mask) \
1567 { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1570 i_test_format_probe(io_glue *data, int length) {
1571 static const struct magic_entry formats[] = {
1572 FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1573 FORMAT_ENTRY("GIF87a", "gif"),
1574 FORMAT_ENTRY("GIF89a", "gif"),
1575 FORMAT_ENTRY("MM\0*", "tiff"),
1576 FORMAT_ENTRY("II*\0", "tiff"),
1577 FORMAT_ENTRY("BM", "bmp"),
1578 FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1579 FORMAT_ENTRY("P1", "pnm"),
1580 FORMAT_ENTRY("P2", "pnm"),
1581 FORMAT_ENTRY("P3", "pnm"),
1582 FORMAT_ENTRY("P4", "pnm"),
1583 FORMAT_ENTRY("P5", "pnm"),
1584 FORMAT_ENTRY("P6", "pnm"),
1585 FORMAT_ENTRY("/* XPM", "xpm"),
1586 FORMAT_ENTRY("\x8aMNG", "mng"),
1587 FORMAT_ENTRY("\x8aJNG", "jng"),
1588 /* SGI RGB - with various possible parameters to avoid false positives
1590 values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1592 FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1593 FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1594 FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1595 FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1597 FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
1599 /* different versions of PCX format
1600 http://www.fileformat.info/format/pcx/
1602 FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1603 FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1604 FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1605 FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1606 FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1608 /* FITS - http://fits.gsfc.nasa.gov/ */
1609 FORMAT_ENTRY("SIMPLE =", "fits"),
1611 /* PSD - Photoshop */
1612 FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1614 /* EPS - Encapsulated Postscript */
1615 /* only reading 18 chars, so we don't include the F in EPSF */
1616 FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1619 FORMAT_ENTRY("\x52\xCC", "utah"),
1621 /* GZIP compressed, only matching deflate for now */
1622 FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1624 /* bzip2 compressed */
1625 FORMAT_ENTRY("BZh", "bzip2"),
1628 http://code.google.com/speed/webp/docs/riff_container.html */
1629 FORMAT_ENTRY2("RIFF WEBP", "webp", "xxxx xxxx"),
1632 This might match a little loosely */
1633 FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"),
1635 static const struct magic_entry more_formats[] = {
1636 /* these were originally both listed as ico, but cur files can
1637 include hotspot information */
1638 FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1639 FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1640 FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07",
1641 "xwd", " xxxx"), /* X Windows Dump */
1645 unsigned char head[18];
1648 rc = i_io_peekn(data, head, 18);
1649 if (rc == -1) return NULL;
1653 fprintf(stderr, "%d bytes -", (int)rc);
1654 for (i = 0; i < rc; ++i)
1655 fprintf(stderr, " %02x", head[i]);
1656 fprintf(stderr, "\n");
1660 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
1661 struct magic_entry const *entry = formats + i;
1663 if (test_magic(head, rc, entry))
1668 tga_header_verify(head))
1671 for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
1672 struct magic_entry const *entry = more_formats + i;
1674 if (test_magic(head, rc, entry))
1682 =item i_img_is_monochrome(img, &zero_is_white)
1684 =category Image Information
1686 Tests an image to check it meets our monochrome tests.
1688 The idea is that a file writer can use this to test where it should
1689 write the image in whatever bi-level format it uses, eg. C<pbm> for
1692 For performance of encoders we require monochrome images:
1702 have a palette of two colors, containing only C<(0,0,0)> and
1703 C<(255,255,255)> in either order.
1707 C<zero_is_white> is set to non-zero if the first palette entry is white.
1713 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1714 if (im->type == i_palette_type
1715 && i_colorcount(im) == 2) {
1717 i_getcolors(im, 0, colors, 2);
1718 if (im->channels == 3) {
1719 if (colors[0].rgb.r == 255 &&
1720 colors[0].rgb.g == 255 &&
1721 colors[0].rgb.b == 255 &&
1722 colors[1].rgb.r == 0 &&
1723 colors[1].rgb.g == 0 &&
1724 colors[1].rgb.b == 0) {
1728 else if (colors[0].rgb.r == 0 &&
1729 colors[0].rgb.g == 0 &&
1730 colors[0].rgb.b == 0 &&
1731 colors[1].rgb.r == 255 &&
1732 colors[1].rgb.g == 255 &&
1733 colors[1].rgb.b == 255) {
1738 else if (im->channels == 1) {
1739 if (colors[0].channel[0] == 255 &&
1740 colors[1].channel[0] == 0) {
1744 else if (colors[0].channel[0] == 0 &&
1745 colors[1].channel[0] == 255) {
1757 =item i_get_file_background(im, &bg)
1761 Retrieve the file write background color tag from the image.
1763 If not present, C<bg> is set to black.
1765 Returns 1 if the C<i_background> tag was found and valid.
1771 i_get_file_background(i_img *im, i_color *bg) {
1772 int result = i_tags_get_color(&im->tags, "i_background", 0, bg);
1775 bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1777 /* always full alpha */
1778 bg->channel[3] = 255;
1784 =item i_get_file_backgroundf(im, &bg)
1788 Retrieve the file write background color tag from the image as a
1789 floating point color.
1791 Implemented in terms of i_get_file_background().
1793 If not present, C<bg> is set to black.
1795 Returns 1 if the C<i_background> tag was found and valid.
1801 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1803 int result = i_get_file_background(im, &bg);
1804 fbg->rgba.r = Sample8ToF(bg.rgba.r);
1805 fbg->rgba.g = Sample8ToF(bg.rgba.g);
1806 fbg->rgba.b = Sample8ToF(bg.rgba.b);
1817 Arnar M. Hrafnkelsson <addi@umich.edu>
1819 Tony Cook <tonyc@cpan.org>