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;
100 =item ICL_new_internal(r, g, b, a)
102 Return a new color object with values passed to it.
104 r - red component (range: 0 - 255)
105 g - green component (range: 0 - 255)
106 b - blue component (range: 0 - 255)
107 a - alpha component (range: 0 - 255)
113 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
116 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
118 if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
123 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
129 =item ICL_set_internal(cl, r, g, b, a)
131 Overwrite a color with new values.
133 cl - pointer to color object
134 r - red component (range: 0 - 255)
135 g - green component (range: 0 - 255)
136 b - blue component (range: 0 - 255)
137 a - alpha component (range: 0 - 255)
143 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
144 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
146 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
147 i_fatal(2,"malloc() error\n");
152 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
158 =item ICL_add(dst, src, ch)
160 Add src to dst inplace - dst is modified.
162 dst - pointer to destination color object
163 src - pointer to color object that is added
164 ch - number of channels
170 ICL_add(i_color *dst,i_color *src,int ch) {
173 tmp=dst->channel[i]+src->channel[i];
174 dst->channel[i]= tmp>255 ? 255:tmp;
181 Dump color information to log - strictly for debugging.
183 cl - pointer to color object
189 ICL_info(i_color const *cl) {
190 mm_log((1,"i_color_info(cl* %p)\n",cl));
191 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
197 Destroy ancillary data for Color object.
199 cl - pointer to color object
205 ICL_DESTROY(i_color *cl) {
206 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
211 =item i_fcolor_new(double r, double g, double b, double a)
215 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
218 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
220 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
225 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
231 =item i_fcolor_destroy(i_fcolor *cl)
235 void i_fcolor_destroy(i_fcolor *cl) {
240 =item i_img_exorcise(im)
250 i_img_exorcise(i_img *im) {
251 mm_log((1,"i_img_exorcise(im* %p)\n",im));
252 i_tags_destroy(&im->tags);
254 (im->i_f_destroy)(im);
255 if (im->idata != NULL) { myfree(im->idata); }
265 =item i_img_destroy(C<img>)
267 =category Image creation/destruction
268 =synopsis i_img_destroy(img)
270 Destroy an image object
276 i_img_destroy(i_img *im) {
277 mm_log((1,"i_img_destroy(im %p)\n",im));
279 if (im) { myfree(im); }
283 =item i_img_info(im, info)
287 Return image information
290 info - pointer to array to return data
292 info is an array of 4 integers with the following values:
297 info[3] - channel mask
304 i_img_info(i_img *im, i_img_dim *info) {
305 mm_log((1,"i_img_info(im %p)\n",im));
307 mm_log((1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
309 i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
310 mm_log((1,"i_img_info: idata=%p\n",im->idata));
313 info[2] = im->channels;
314 info[3] = im->ch_mask;
324 =item i_img_setmask(C<im>, C<ch_mask>)
325 =category Image Information
326 =synopsis // only channel 0 writable
327 =synopsis i_img_setmask(img, 0x01);
329 Set the image channel mask for C<im> to C<ch_mask>.
331 The image channel mask gives some control over which channels can be
332 written to in the image.
337 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
341 =item i_img_getmask(C<im>)
342 =category Image Information
343 =synopsis int mask = i_img_getmask(img);
345 Get the image channel mask for C<im>.
350 i_img_getmask(i_img *im) { return im->ch_mask; }
353 =item i_img_getchannels(C<im>)
354 =category Image Information
355 =synopsis int channels = i_img_getchannels(img);
357 Get the number of channels in C<im>.
362 i_img_getchannels(i_img *im) { return im->channels; }
365 =item i_img_get_width(C<im>)
366 =category Image Information
367 =synopsis i_img_dim width = i_img_get_width(im);
369 Returns the width in pixels of the image.
374 i_img_get_width(i_img *im) {
379 =item i_img_get_height(C<im>)
380 =category Image Information
381 =synopsis i_img_dim height = i_img_get_height(im);
383 Returns the height in pixels of the image.
388 i_img_get_height(i_img *im) {
393 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
397 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
398 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
399 the target image. pass NULL in C<trans> for non transparent i_colors.
405 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) {
407 i_img_dim x,y,t,ttx,tty,tt;
410 mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
411 "to(" i_DFp "), trans* %p)\n",
412 im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
414 if (x2<x1) { t=x1; x1=x2; x2=t; }
415 if (y2<y1) { t=y1; y1=y2; y2=t; }
427 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
428 if (tt) i_ppix(im,ttx,tty,&pv);
429 } else i_ppix(im,ttx,tty,&pv);
441 Creates a new image that is a copy of the image C<source>.
443 Tags are not copied, only the image data.
453 i_img *im = i_sametype(src, src->xsize, src->ysize);
455 mm_log((1,"i_copy(src %p)\n", src));
462 if (src->type == i_direct_type) {
463 if (src->bits == i_8_bits) {
465 pv = mymalloc(sizeof(i_color) * x1);
467 for (y = 0; y < y1; ++y) {
468 i_glin(src, 0, x1, y, pv);
469 i_plin(im, 0, x1, y, pv);
476 pv = mymalloc(sizeof(i_fcolor) * x1);
477 for (y = 0; y < y1; ++y) {
478 i_glinf(src, 0, x1, y, pv);
479 i_plinf(im, 0, x1, y, pv);
487 vals = mymalloc(sizeof(i_palidx) * x1);
488 for (y = 0; y < y1; ++y) {
489 i_gpal(src, 0, x1, y, vals);
490 i_ppal(im, 0, x1, y, vals);
500 http://en.wikipedia.org/wiki/Lanczos_resampling
512 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
513 else if (x == 0.0) return (1.0);
514 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
519 =item i_scaleaxis(im, value, axis)
521 Returns a new image object which is I<im> scaled by I<value> along
522 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
528 i_scaleaxis(i_img *im, double Value, int Axis) {
529 i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
530 i_img_dim LanczosWidthFactor;
535 float F, PictureValue[MAXCHANNELS];
537 i_color val,val1,val2;
539 int has_alpha = i_img_has_alpha(im);
540 int color_chans = i_img_color_channels(im);
544 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
547 hsize = (i_img_dim)(0.5 + im->xsize * Value);
550 Value = 1.0 / im->xsize;
558 vsize = (i_img_dim)(0.5 + im->ysize * Value);
562 Value = 1.0 / im->ysize;
569 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
571 i_push_error(0, "cannot create output image");
575 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
576 LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value);
577 lMax = LanczosWidthFactor << 1;
579 l0 = mymalloc(lMax * sizeof(float));
580 l1 = mymalloc(lMax * sizeof(float));
582 for (j=0; j<jEnd; j++) {
583 OldLocation = ((double) j) / Value;
584 T = (i_img_dim) (OldLocation);
587 for (l = 0; l<lMax; l++) {
588 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
589 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
592 /* Make sure filter is normalized */
594 for(l=0; l<lMax; l++) {
598 t /= (double)LanczosWidthFactor;
600 for(l=0; l<lMax; l++) {
607 for (i=0; i<iEnd; i++) {
608 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
609 for (l=0; l<lMax; l++) {
610 i_img_dim mx = T-lMax+l+1;
611 i_img_dim Mx = T+l+1;
612 mx = (mx < 0) ? 0 : mx;
613 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
615 i_gpix(im, Mx, i, &val1);
616 i_gpix(im, mx, i, &val2);
619 i_sample_t alpha1 = val1.channel[color_chans];
620 i_sample_t alpha2 = val2.channel[color_chans];
621 for (k=0; k < color_chans; k++) {
622 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
623 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
625 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
626 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
629 for (k=0; k<im->channels; k++) {
630 PictureValue[k] += l1[l] * val1.channel[k];
631 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
637 float fa = PictureValue[color_chans] / LanczosWidthFactor;
638 int alpha = minmax(0, 255, fa+0.5);
640 for (k = 0; k < color_chans; ++k) {
641 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
642 val.channel[k]=minmax(0,255,psave);
644 val.channel[color_chans] = alpha;
647 /* zero alpha, so the pixel has no color */
648 for (k = 0; k < im->channels; ++k)
653 for(k=0;k<im->channels;k++) {
654 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
655 val.channel[k]=minmax(0,255,psave);
658 i_ppix(new_img, j, i, &val);
663 for (i=0; i<iEnd; i++) {
664 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
665 for (l=0; l < lMax; l++) {
666 i_img_dim mx = T-lMax+l+1;
667 i_img_dim Mx = T+l+1;
668 mx = (mx < 0) ? 0 : mx;
669 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
671 i_gpix(im, i, Mx, &val1);
672 i_gpix(im, i, mx, &val2);
674 i_sample_t alpha1 = val1.channel[color_chans];
675 i_sample_t alpha2 = val2.channel[color_chans];
676 for (k=0; k < color_chans; k++) {
677 PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255;
678 PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
680 PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
681 PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
684 for (k=0; k<im->channels; k++) {
685 PictureValue[k] += l1[l] * val1.channel[k];
686 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
691 float fa = PictureValue[color_chans] / LanczosWidthFactor;
692 int alpha = minmax(0, 255, fa+0.5);
694 for (k = 0; k < color_chans; ++k) {
695 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
696 val.channel[k]=minmax(0,255,psave);
698 val.channel[color_chans] = alpha;
701 for (k = 0; k < im->channels; ++k)
706 for(k=0;k<im->channels;k++) {
707 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
708 val.channel[k]=minmax(0,255,psave);
711 i_ppix(new_img, i, j, &val);
719 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
726 =item i_scale_nn(im, scx, scy)
728 Scale by using nearest neighbor
729 Both axes scaled at the same time since
730 nothing is gained by doing it in two steps
737 i_scale_nn(i_img *im, double scx, double scy) {
739 i_img_dim nxsize,nysize,nx,ny;
744 mm_log((1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
746 nxsize = (i_img_dim) ((double) im->xsize * scx);
749 scx = 1.0 / im->xsize;
751 nysize = (i_img_dim) ((double) im->ysize * scy);
754 scy = 1.0 / im->ysize;
756 im_assert(scx != 0 && scy != 0);
758 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
760 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
761 i_gpix(im,((double)nx)/scx,((double)ny)/scy,&val);
762 i_ppix(new_img,nx,ny,&val);
765 mm_log((1,"(%p) <- i_scale_nn\n",new_img));
771 =item i_sametype(C<im>, C<xsize>, C<ysize>)
773 =category Image creation/destruction
774 =synopsis i_img *img = i_sametype(src, width, height);
776 Returns an image of the same type (sample size, channels, paletted/direct).
778 For paletted images the palette is copied from the source.
784 i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
787 if (src->type == i_direct_type) {
788 if (src->bits == 8) {
789 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
791 else if (src->bits == i_16_bits) {
792 return i_img_16_new(xsize, ysize, src->channels);
794 else if (src->bits == i_double_bits) {
795 return i_img_double_new(xsize, ysize, src->channels);
798 i_push_error(0, "Unknown image bits");
806 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
807 for (i = 0; i < i_colorcount(src); ++i) {
808 i_getcolors(src, i, &col, 1);
809 i_addcolors(targ, &col, 1);
817 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
819 =category Image creation/destruction
820 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
822 Returns an image of the same type (sample size).
824 For paletted images the equivalent direct type is returned.
830 i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
833 if (src->bits == 8) {
834 return i_img_empty_ch(NULL, xsize, ysize, channels);
836 else if (src->bits == i_16_bits) {
837 return i_img_16_new(xsize, ysize, channels);
839 else if (src->bits == i_double_bits) {
840 return i_img_double_new(xsize, ysize, channels);
843 i_push_error(0, "Unknown image bits");
849 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
851 Spatially transforms I<im> returning a new image.
853 opx for a length of opxl and opy for a length of opy are arrays of
854 operators that modify the x and y positions to retreive the pixel data from.
856 parm and parmlen define extra parameters that the operators may use.
858 Note that this function is largely superseded by the more flexible
859 L<transform.c/i_transform2>.
861 Returns the new image.
863 The operators for this function are defined in L<stackmach.c>.
868 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
870 i_img_dim nxsize,nysize,nx,ny;
875 mm_log((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));
880 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
881 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
882 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
883 /* parm[parmlen-2]=(double)nx;
884 parm[parmlen-1]=(double)ny; */
889 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
890 rx=i_op_run(opx,opxl,parm,parmlen);
891 ry=i_op_run(opy,opyl,parm,parmlen);
892 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
893 i_gpix(im,rx,ry,&val);
894 i_ppix(new_img,nx,ny,&val);
897 mm_log((1,"(%p) <- i_transform\n",new_img));
902 =item i_img_diff(im1, im2)
904 Calculates the sum of the squares of the differences between
905 correspoding channels in two images.
907 If the images are not the same size then only the common area is
908 compared, hence even if images are different sizes this function
915 i_img_diff(i_img *im1,i_img *im2) {
916 i_img_dim x, y, xb, yb;
922 mm_log((1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
924 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
925 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
926 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
928 mm_log((1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
929 i_DFcp(xb,yb), chb));
932 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
933 i_gpix(im1,x,y,&val1);
934 i_gpix(im2,x,y,&val2);
936 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
938 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
943 =item i_img_diffd(im1, im2)
945 Calculates the sum of the squares of the differences between
946 correspoding channels in two images.
948 If the images are not the same size then only the common area is
949 compared, hence even if images are different sizes this function
952 This is like i_img_diff() but looks at floating point samples instead.
958 i_img_diffd(i_img *im1,i_img *im2) {
959 i_img_dim x, y, xb, yb;
964 mm_log((1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
966 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
967 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
968 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
970 mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
971 i_DFcp(xb, yb), chb));
974 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
975 i_gpixf(im1,x,y,&val1);
976 i_gpixf(im2,x,y,&val2);
978 for(ch=0;ch<chb;ch++) {
979 double sdiff = val1.channel[ch]-val2.channel[ch];
980 tdiff += sdiff * sdiff;
983 mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
989 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
997 mm_log((1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
999 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1000 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1001 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1003 mm_log((1,"i_img_samef: b(" i_DFp ") chb=%d\n",
1004 i_DFcp(xb, yb), chb));
1006 for(y = 0; y < yb; y++) {
1007 for(x = 0; x < xb; x++) {
1008 i_gpixf(im1, x, y, &val1);
1009 i_gpixf(im2, x, y, &val2);
1011 for(ch = 0; ch < chb; ch++) {
1012 double sdiff = val1.channel[ch] - val2.channel[ch];
1013 if (fabs(sdiff) > epsilon) {
1014 mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n",
1015 sdiff, i_DFcp(x, y)));
1021 mm_log((1,"i_img_samef <- same\n"));
1026 /* just a tiny demo of haar wavelets */
1034 i_img *new_img,*new_img2;
1035 i_color val1,val2,dval1,dval2;
1044 /* horizontal pass */
1046 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1047 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1050 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1051 i_gpix(im,x*2,y,&val1);
1052 i_gpix(im,x*2+1,y,&val2);
1053 for(ch=0;ch<im->channels;ch++) {
1054 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1055 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1057 i_ppix(new_img,x,y,&dval1);
1058 i_ppix(new_img,x+fx,y,&dval2);
1061 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1062 i_gpix(new_img,x,y*2,&val1);
1063 i_gpix(new_img,x,y*2+1,&val2);
1064 for(ch=0;ch<im->channels;ch++) {
1065 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1066 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1068 i_ppix(new_img2,x,y,&dval1);
1069 i_ppix(new_img2,x,y+fy,&dval2);
1072 i_img_destroy(new_img);
1077 =item i_count_colors(im, maxc)
1079 returns number of colors or -1
1080 to indicate that it was more than max colors
1084 /* This function has been changed and is now faster. It's using
1085 * i_gsamp instead of i_gpix */
1087 i_count_colors(i_img *im,int maxc) {
1094 i_img_dim xsize = im->xsize;
1095 i_img_dim ysize = im->ysize;
1096 int samp_cnt = 3 * xsize;
1098 if (im->channels >= 3) {
1102 channels[0] = channels[1] = channels[2] = 0;
1103 samp_chans = channels;
1108 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1111 for(y = 0; y < ysize; ) {
1112 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1113 for(x = 0; x < samp_cnt; ) {
1114 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1116 if (colorcnt > maxc) {
1127 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm
1128 * (adapted from the Numerical Recipes)
1130 /* Needed by get_anonymous_color_histo */
1132 hpsort(unsigned int n, unsigned *ra) {
1157 if (j < ir && ra[j] < ra[j+1]) j++;
1169 /* This function constructs an ordered list which represents how much the
1170 * different colors are used. So for instance (100, 100, 500) means that one
1171 * color is used for 500 pixels, another for 100 pixels and another for 100
1172 * pixels. It's tuned for performance. You might not like the way I've hardcoded
1173 * the maxc ;-) and you might want to change the name... */
1174 /* Uses octt_histo */
1176 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1180 unsigned int *col_usage_it;
1185 i_img_dim xsize = im->xsize;
1186 i_img_dim ysize = im->ysize;
1187 int samp_cnt = 3 * xsize;
1190 samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1192 if (im->channels >= 3) {
1196 channels[0] = channels[1] = channels[2] = 0;
1197 samp_chans = channels;
1201 for(y = 0; y < ysize; ) {
1202 i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1203 for(x = 0; x < samp_cnt; ) {
1204 colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1206 if (colorcnt > maxc) {
1213 /* Now that we know the number of colours... */
1214 col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1215 octt_histo(ct, &col_usage_it);
1216 hpsort(colorcnt, *col_usage);
1224 =head2 Image method wrappers
1226 These functions provide i_fsample_t functions in terms of their
1227 i_sample_t versions.
1231 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1236 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1240 for (ch = 0; ch < im->channels; ++ch)
1241 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1243 return i_ppix(im, x, y, &temp);
1247 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1251 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1255 if (i_gpix(im, x, y, &temp) == 0) {
1256 for (ch = 0; ch < im->channels; ++ch)
1257 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1265 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1270 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1273 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1280 work = mymalloc(sizeof(i_color) * (r-l));
1281 for (i = 0; i < r-l; ++i) {
1282 for (ch = 0; ch < im->channels; ++ch)
1283 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1285 ret = i_plin(im, l, r, y, work);
1300 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1305 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1308 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1315 work = mymalloc(sizeof(i_color) * (r-l));
1316 ret = i_plin(im, l, r, y, work);
1317 for (i = 0; i < r-l; ++i) {
1318 for (ch = 0; ch < im->channels; ++ch)
1319 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1335 =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)
1341 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
1342 int const *chans, int chan_count) {
1345 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1351 work = mymalloc(sizeof(i_sample_t) * (r-l));
1352 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1353 for (i = 0; i < ret; ++i) {
1354 samp[i] = Sample8ToF(work[i]);
1372 =head2 Palette wrapper functions
1374 Used for virtual images, these forward palette calls to a wrapped image,
1375 assuming the wrapped image is the first pointer in the structure that
1376 im->ext_data points at.
1380 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1384 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1385 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1389 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1393 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1394 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1398 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1402 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1403 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1407 =item i_colorcount_forward(i_img *im)
1411 int i_colorcount_forward(i_img *im) {
1412 return i_colorcount(*(i_img **)im->ext_data);
1416 =item i_maxcolors_forward(i_img *im)
1420 int i_maxcolors_forward(i_img *im) {
1421 return i_maxcolors(*(i_img **)im->ext_data);
1425 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1429 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1430 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1436 =head2 Fallback handler
1440 =item i_gsamp_bits_fb
1446 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
1447 const int *chans, int chan_count, int bits) {
1450 if (bits < 1 || bits > 32) {
1451 i_push_error(0, "Invalid bits, must be 1..32");
1455 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1458 i_img_dim count, i, w;
1461 scale = 4294967295.0;
1463 scale = (double)(1 << bits) - 1;
1471 /* make sure we have good channel numbers */
1472 for (ch = 0; ch < chan_count; ++ch) {
1473 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1474 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1478 for (i = 0; i < w; ++i) {
1480 i_gpixf(im, l+i, y, &c);
1481 for (ch = 0; ch < chan_count; ++ch) {
1482 *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1488 if (chan_count <= 0 || chan_count > im->channels) {
1489 i_push_error(0, "Invalid channel count");
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);
1505 i_push_error(0, "Image position outside of image");
1510 struct magic_entry {
1511 unsigned char *magic;
1514 unsigned char *mask;
1518 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
1519 if (length < magic->magic_size)
1523 unsigned char *bufp = buffer,
1524 *maskp = magic->mask,
1525 *magicp = magic->magic;
1527 for (i = 0; i < magic->magic_size; ++i) {
1528 int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1531 if ((*bufp++ & mask) != (*magicp++ & mask))
1538 return !memcmp(magic->magic, buffer, magic->magic_size);
1543 =item i_test_format_probe(io_glue *data, int length)
1545 Check the beginning of the supplied file for a 'magic number'
1550 #define FORMAT_ENTRY(magic, type) \
1551 { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1552 #define FORMAT_ENTRY2(magic, type, mask) \
1553 { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1556 i_test_format_probe(io_glue *data, int length) {
1557 static const struct magic_entry formats[] = {
1558 FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1559 FORMAT_ENTRY("GIF87a", "gif"),
1560 FORMAT_ENTRY("GIF89a", "gif"),
1561 FORMAT_ENTRY("MM\0*", "tiff"),
1562 FORMAT_ENTRY("II*\0", "tiff"),
1563 FORMAT_ENTRY("BM", "bmp"),
1564 FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1565 FORMAT_ENTRY("P1", "pnm"),
1566 FORMAT_ENTRY("P2", "pnm"),
1567 FORMAT_ENTRY("P3", "pnm"),
1568 FORMAT_ENTRY("P4", "pnm"),
1569 FORMAT_ENTRY("P5", "pnm"),
1570 FORMAT_ENTRY("P6", "pnm"),
1571 FORMAT_ENTRY("/* XPM", "xpm"),
1572 FORMAT_ENTRY("\x8aMNG", "mng"),
1573 FORMAT_ENTRY("\x8aJNG", "jng"),
1574 /* SGI RGB - with various possible parameters to avoid false positives
1576 values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1578 FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1579 FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1580 FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1581 FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1583 FORMAT_ENTRY2("FORM ILBM", "ilbm", "xxxx xxxx"),
1585 /* different versions of PCX format
1586 http://www.fileformat.info/format/pcx/
1588 FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1589 FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1590 FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1591 FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1592 FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1594 /* FITS - http://fits.gsfc.nasa.gov/ */
1595 FORMAT_ENTRY("SIMPLE =", "fits"),
1597 /* PSD - Photoshop */
1598 FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1600 /* EPS - Encapsulated Postscript */
1601 /* only reading 18 chars, so we don't include the F in EPSF */
1602 FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1605 FORMAT_ENTRY("\x52\xCC", "utah"),
1607 /* GZIP compressed, only matching deflate for now */
1608 FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1610 /* bzip2 compressed */
1611 FORMAT_ENTRY("BZh", "bzip2"),
1614 http://code.google.com/speed/webp/docs/riff_container.html */
1615 FORMAT_ENTRY2("RIFF WEBP", "webp", "xxxx xxxx"),
1618 This might match a little loosely */
1619 FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"),
1621 static const struct magic_entry more_formats[] = {
1622 /* these were originally both listed as ico, but cur files can
1623 include hotspot information */
1624 FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1625 FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1626 FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07",
1627 "xwd", " xxxx"), /* X Windows Dump */
1631 unsigned char head[18];
1634 rc = i_io_peekn(data, head, 18);
1635 if (rc == -1) return NULL;
1639 fprintf(stderr, "%d bytes -", (int)rc);
1640 for (i = 0; i < rc; ++i)
1641 fprintf(stderr, " %02x", head[i]);
1642 fprintf(stderr, "\n");
1646 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
1647 struct magic_entry const *entry = formats + i;
1649 if (test_magic(head, rc, entry))
1654 tga_header_verify(head))
1657 for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
1658 struct magic_entry const *entry = more_formats + i;
1660 if (test_magic(head, rc, entry))
1668 =item i_img_is_monochrome(img, &zero_is_white)
1670 =category Image Information
1672 Tests an image to check it meets our monochrome tests.
1674 The idea is that a file writer can use this to test where it should
1675 write the image in whatever bi-level format it uses, eg. C<pbm> for
1678 For performance of encoders we require monochrome images:
1688 have a palette of two colors, containing only C<(0,0,0)> and
1689 C<(255,255,255)> in either order.
1693 C<zero_is_white> is set to non-zero if the first palette entry is white.
1699 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1700 if (im->type == i_palette_type
1701 && i_colorcount(im) == 2) {
1703 i_getcolors(im, 0, colors, 2);
1704 if (im->channels == 3) {
1705 if (colors[0].rgb.r == 255 &&
1706 colors[0].rgb.g == 255 &&
1707 colors[0].rgb.b == 255 &&
1708 colors[1].rgb.r == 0 &&
1709 colors[1].rgb.g == 0 &&
1710 colors[1].rgb.b == 0) {
1714 else if (colors[0].rgb.r == 0 &&
1715 colors[0].rgb.g == 0 &&
1716 colors[0].rgb.b == 0 &&
1717 colors[1].rgb.r == 255 &&
1718 colors[1].rgb.g == 255 &&
1719 colors[1].rgb.b == 255) {
1724 else if (im->channels == 1) {
1725 if (colors[0].channel[0] == 255 &&
1726 colors[1].channel[0] == 0) {
1730 else if (colors[0].channel[0] == 0 &&
1731 colors[1].channel[0] == 255) {
1743 =item i_get_file_background(im, &bg)
1747 Retrieve the file write background color tag from the image.
1749 If not present, C<bg> is set to black.
1751 Returns 1 if the C<i_background> tag was found and valid.
1757 i_get_file_background(i_img *im, i_color *bg) {
1758 int result = i_tags_get_color(&im->tags, "i_background", 0, bg);
1761 bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1763 /* always full alpha */
1764 bg->channel[3] = 255;
1770 =item i_get_file_backgroundf(im, &bg)
1774 Retrieve the file write background color tag from the image as a
1775 floating point color.
1777 Implemented in terms of i_get_file_background().
1779 If not present, C<bg> is set to black.
1781 Returns 1 if the C<i_background> tag was found and valid.
1787 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1789 int result = i_get_file_background(im, &bg);
1790 fbg->rgba.r = Sample8ToF(bg.rgba.r);
1791 fbg->rgba.g = Sample8ToF(bg.rgba.g);
1792 fbg->rgba.b = Sample8ToF(bg.rgba.b);
1803 Arnar M. Hrafnkelsson <addi@umich.edu>
1805 Tony Cook <tonyc@cpan.org>