8 image.c - implements most of the basic functions of Imager and much of the rest
14 c = i_color_new(red, green, blue, alpha);
22 image.c implements the basic functions to create and destroy image and
23 color objects for Imager.
25 =head1 FUNCTION REFERENCE
27 Some of these functions are internal.
38 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) )
40 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
41 void fake(void) { ceil(1); }
43 static int i_ppix_d(i_img *im, int x, int y, i_color *val);
44 static int i_gpix_d(i_img *im, int x, int y, i_color *val);
45 static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
46 static int i_plin_d(i_img *im, int l, int r, int y, i_color *vals);
47 static int i_ppixf_d(i_img *im, int x, int y, i_fcolor *val);
48 static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
49 static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
50 static int i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
51 static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
52 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);
55 =item ICL_new_internal(r, g, b, a)
57 Return a new color object with values passed to it.
59 r - red component (range: 0 - 255)
60 g - green component (range: 0 - 255)
61 b - blue component (range: 0 - 255)
62 a - alpha component (range: 0 - 255)
68 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
71 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
73 if ( (cl=mymalloc(sizeof(i_color))) == NULL) m_fatal(2,"malloc() error\n");
78 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
84 =item ICL_set_internal(cl, r, g, b, a)
86 Overwrite a color with new values.
88 cl - pointer to color object
89 r - red component (range: 0 - 255)
90 g - green component (range: 0 - 255)
91 b - blue component (range: 0 - 255)
92 a - alpha component (range: 0 - 255)
98 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
99 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
101 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
102 m_fatal(2,"malloc() error\n");
107 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
113 =item ICL_add(dst, src, ch)
115 Add src to dst inplace - dst is modified.
117 dst - pointer to destination color object
118 src - pointer to color object that is added
119 ch - number of channels
125 ICL_add(i_color *dst,i_color *src,int ch) {
128 tmp=dst->channel[i]+src->channel[i];
129 dst->channel[i]= tmp>255 ? 255:tmp;
136 Dump color information to log - strictly for debugging.
138 cl - pointer to color object
144 ICL_info(i_color *cl) {
145 mm_log((1,"i_color_info(cl* %p)\n",cl));
146 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
152 Destroy ancillary data for Color object.
154 cl - pointer to color object
160 ICL_DESTROY(i_color *cl) {
161 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
166 =item i_fcolor_new(double r, double g, double b, double a)
170 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
173 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
175 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) m_fatal(2,"malloc() error\n");
180 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
186 =item i_fcolor_destroy(i_fcolor *cl)
190 void i_fcolor_destroy(i_fcolor *cl) {
195 =item IIM_base_8bit_direct (static)
197 A static i_img object used to initialize direct 8-bit per sample images.
201 static i_img IIM_base_8bit_direct =
203 0, /* channels set */
204 0, 0, 0, /* xsize, ysize, bytes */
207 i_direct_type, /* type */
210 { 0, 0, NULL }, /* tags */
213 i_ppix_d, /* i_f_ppix */
214 i_ppixf_d, /* i_f_ppixf */
215 i_plin_d, /* i_f_plin */
216 i_plinf_d, /* i_f_plinf */
217 i_gpix_d, /* i_f_gpix */
218 i_gpixf_d, /* i_f_gpixf */
219 i_glin_d, /* i_f_glin */
220 i_glinf_d, /* i_f_glinf */
221 i_gsamp_d, /* i_f_gsamp */
222 i_gsampf_d, /* i_f_gsampf */
226 NULL, /* i_f_addcolors */
227 NULL, /* i_f_getcolors */
228 NULL, /* i_f_colorcount */
229 NULL, /* i_f_maxcolors */
230 NULL, /* i_f_findcolor */
231 NULL, /* i_f_setcolors */
233 NULL, /* i_f_destroy */
236 /*static void set_8bit_direct(i_img *im) {
237 im->i_f_ppix = i_ppix_d;
238 im->i_f_ppixf = i_ppixf_d;
239 im->i_f_plin = i_plin_d;
240 im->i_f_plinf = i_plinf_d;
241 im->i_f_gpix = i_gpix_d;
242 im->i_f_gpixf = i_gpixf_d;
243 im->i_f_glin = i_glin_d;
244 im->i_f_glinf = i_glinf_d;
247 im->i_f_addcolor = NULL;
248 im->i_f_getcolor = NULL;
249 im->i_f_colorcount = NULL;
250 im->i_f_findcolor = NULL;
254 =item IIM_new(x, y, ch)
256 Creates a new image object I<x> pixels wide, and I<y> pixels high with I<ch> channels.
263 IIM_new(int x,int y,int ch) {
265 mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
267 im=i_img_empty_ch(NULL,x,y,ch);
269 mm_log((1,"(%p) <- IIM_new\n",im));
275 IIM_DESTROY(i_img *im) {
276 mm_log((1,"IIM_DESTROY(im* %p)\n",im));
286 Create new image reference - notice that this isn't an object yet and
287 this should be fixed asap.
297 mm_log((1,"i_img_struct()\n"));
298 if ( (im=mymalloc(sizeof(i_img))) == NULL)
299 m_fatal(2,"malloc() error\n");
301 *im = IIM_base_8bit_direct;
309 mm_log((1,"(%p) <- i_img_struct\n",im));
314 =item i_img_empty(im, x, y)
316 Re-new image reference (assumes 3 channels)
319 x - xsize of destination image
320 y - ysize of destination image
322 **FIXME** what happens if a live image is passed in here?
324 Should this just call i_img_empty_ch()?
330 i_img_empty(i_img *im,int x,int y) {
331 mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
332 return i_img_empty_ch(im, x, y, 3);
336 =item i_img_empty_ch(im, x, y, ch)
338 Re-new image reference
341 x - xsize of destination image
342 y - ysize of destination image
343 ch - number of channels
349 i_img_empty_ch(i_img *im,int x,int y,int ch) {
350 mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
352 if ( (im=mymalloc(sizeof(i_img))) == NULL)
353 m_fatal(2,"malloc() error\n");
355 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
356 i_tags_new(&im->tags);
360 im->ch_mask = MAXINT;
361 im->bytes=x*y*im->channels;
362 if ( (im->idata=mymalloc(im->bytes)) == NULL) m_fatal(2,"malloc() error\n");
363 memset(im->idata,0,(size_t)im->bytes);
367 mm_log((1,"(%p) <- i_img_empty_ch\n",im));
372 =item i_img_exorcise(im)
382 i_img_exorcise(i_img *im) {
383 mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
384 i_tags_destroy(&im->tags);
386 (im->i_f_destroy)(im);
387 if (im->idata != NULL) { myfree(im->idata); }
393 im->i_f_ppix=i_ppix_d;
394 im->i_f_gpix=i_gpix_d;
395 im->i_f_plin=i_plin_d;
396 im->i_f_glin=i_glin_d;
401 =item i_img_destroy(im)
403 Destroy image and free data via exorcise.
411 i_img_destroy(i_img *im) {
412 mm_log((1,"i_img_destroy(im* 0x%x)\n",im));
414 if (im) { myfree(im); }
418 =item i_img_info(im, info)
420 Return image information
423 info - pointer to array to return data
425 info is an array of 4 integers with the following values:
430 info[3] - channel mask
437 i_img_info(i_img *im,int *info) {
438 mm_log((1,"i_img_info(im 0x%x)\n",im));
440 mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
441 mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
444 info[2] = im->channels;
445 info[3] = im->ch_mask;
455 =item i_img_setmask(im, ch_mask)
457 Set the image channel mask for I<im> to I<ch_mask>.
462 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
466 =item i_img_getmask(im)
468 Get the image channel mask for I<im>.
473 i_img_getmask(i_img *im) { return im->ch_mask; }
476 =item i_img_getchannels(im)
478 Get the number of channels in I<im>.
483 i_img_getchannels(i_img *im) { return im->channels; }
487 =item i_ppix(im, x, y, col)
489 Sets the pixel at (I<x>,I<y>) in I<im> to I<col>.
491 Returns true if the pixel could be set, false if x or y is out of
497 (i_ppix)(i_img *im, int x, int y, i_color *val) { return im->i_f_ppix(im, x, y, val); }
500 =item i_gpix(im, x, y, &col)
502 Get the pixel at (I<x>,I<y>) in I<im> into I<col>.
504 Returns true if the pixel could be retrieved, false otherwise.
509 (i_gpix)(i_img *im, int x, int y, i_color *val) { return im->i_f_gpix(im, x, y, val); }
512 =item i_ppix_pch(im, x, y, ch)
514 Get the value from the channel I<ch> for pixel (I<x>,I<y>) from I<im>
517 Returns zero if x or y is out of range.
519 Warning: this ignores the vptr interface for images.
524 i_gpix_pch(i_img *im,int x,int y,int ch) {
526 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) return ((float)im->idata[(x+y*im->xsize)*im->channels+ch]/255);
532 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
534 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
535 (tx,ty) specifies the upper left corner for the target image.
536 pass NULL in trans for non transparent i_colors.
542 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans) {
544 int x,y,t,ttx,tty,tt,ch;
546 mm_log((1,"i_copyto_trans(im* %p,src 0x%x, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d, trans* 0x%x)\n",
547 im, src, x1, y1, x2, y2, tx, ty, trans));
549 if (x2<x1) { t=x1; x1=x2; x2=t; }
550 if (y2<y1) { t=y1; y1=y2; y2=t; }
562 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
563 if (tt) i_ppix(im,ttx,tty,&pv);
564 } else i_ppix(im,ttx,tty,&pv);
572 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
574 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
575 a rectangle the same size with it's top-left corner at (tx,ty) in the
578 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
584 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
585 int x, y, t, ttx, tty;
587 if (x2<x1) { t=x1; x1=x2; x2=t; }
588 if (y2<y1) { t=y1; y1=y2; y2=t; }
590 mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
591 im, src, x1, y1, x2, y2, tx, ty));
593 if (im->bits == i_8_bits) {
596 for(y=y1; y<y2; y++) {
598 for(x=x1; x<x2; x++) {
599 i_gpix(src, x, y, &pv);
600 i_ppix(im, ttx, tty, &pv);
609 for(y=y1; y<y2; y++) {
611 for(x=x1; x<x2; x++) {
612 i_gpixf(src, x, y, &pv);
613 i_ppixf(im, ttx, tty, &pv);
622 =item i_copy(im, src)
624 Copies the contents of the image I<src> over the image I<im>.
630 i_copy(i_img *im, i_img *src) {
633 mm_log((1,"i_copy(im* %p,src %p)\n", im, src));
637 if (src->type == i_direct_type) {
638 if (src->bits == i_8_bits) {
640 i_img_empty_ch(im, x1, y1, src->channels);
641 pv = mymalloc(sizeof(i_color) * x1);
643 for (y = 0; y < y1; ++y) {
644 i_glin(src, 0, x1, y, pv);
645 i_plin(im, 0, x1, y, pv);
650 /* currently the only other depth is 16 */
652 i_img_16_new_low(im, x1, y1, src->channels);
653 pv = mymalloc(sizeof(i_fcolor) * x1);
654 for (y = 0; y < y1; ++y) {
655 i_glinf(src, 0, x1, y, pv);
656 i_plinf(im, 0, x1, y, pv);
668 i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
669 /* copy across the palette */
670 count = i_colorcount(src);
671 for (index = 0; index < count; ++index) {
672 i_getcolors(src, index, &temp, 1);
673 i_addcolors(im, &temp, 1);
676 vals = mymalloc(sizeof(i_palidx) * x1);
677 for (y = 0; y < y1; ++y) {
678 i_gpal(src, 0, x1, y, vals);
679 i_ppal(im, 0, x1, y, vals);
687 =item i_rubthru(im, src, tx, ty)
689 Takes the image I<src> and applies it at an original (I<tx>,I<ty>) in I<im>.
691 The alpha channel of each pixel in I<src> is used to control how much
692 the existing colour in I<im> is replaced, if it is 255 then the colour
693 is completely replaced, if it is 0 then the original colour is left
700 i_rubthru(i_img *im,i_img *src,int tx,int ty) {
707 mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d)\n", im, src, tx, ty));
710 if (im->channels == 3 && src->channels == 4) {
712 chans[0] = 0; chans[1] = 1; chans[2] = 2;
715 else if (im->channels == 3 && src->channels == 2) {
717 chans[0] = chans[1] = chans[2] = 0;
720 else if (im->channels == 1 && src->channels == 2) {
726 i_push_error(0, "rubthru can only work where (dest, src) channels are (3,4), (3,2) or (1,2)");
731 /* if you change this code, please make sure the else branch is
732 changed in a similar fashion - TC */
734 i_color pv, orig, dest;
736 for(x=0; x<src->xsize; x++) {
738 for(y=0;y<src->ysize;y++) {
739 /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
740 i_gpix(src, x, y, &pv);
741 i_gpix(im, ttx, tty, &orig);
742 alpha = pv.channel[alphachan];
743 for (ch = 0; ch < chancount; ++ch) {
744 dest.channel[ch] = (alpha * pv.channel[chans[ch]]
745 + (255 - alpha) * orig.channel[ch])/255;
747 i_ppix(im, ttx, tty, &dest);
755 i_fcolor pv, orig, dest;
758 for(x=0; x<src->xsize; x++) {
760 for(y=0;y<src->ysize;y++) {
761 /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
762 i_gpixf(src, x, y, &pv);
763 i_gpixf(im, ttx, tty, &orig);
764 alpha = pv.channel[alphachan];
765 for (ch = 0; ch < chancount; ++ch) {
766 dest.channel[ch] = alpha * pv.channel[chans[ch]]
767 + (1 - alpha) * orig.channel[ch];
769 i_ppixf(im, ttx, tty, &dest);
781 =item i_flipxy(im, axis)
783 Flips the image inplace around the axis specified.
784 Returns 0 if parameters are invalid.
787 axis - 0 = x, 1 = y, 2 = both
793 i_flipxy(i_img *im, int direction) {
794 int x, x2, y, y2, xm, ym;
798 mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
803 case XAXIS: /* Horizontal flip */
806 for(y=0; y<ym; y++) {
808 for(x=0; x<xm; x++) {
810 i_gpix(im, x, y, &val1);
811 i_gpix(im, x2, y, &val2);
812 i_ppix(im, x, y, &val2);
813 i_ppix(im, x2, y, &val1);
818 case YAXIS: /* Vertical flip */
822 for(y=0; y<ym; y++) {
823 for(x=0; x<xm; x++) {
825 i_gpix(im, x, y, &val1);
826 i_gpix(im, x, y2, &val2);
827 i_ppix(im, x, y, &val2);
828 i_ppix(im, x, y2, &val1);
833 case XYAXIS: /* Horizontal and Vertical flip */
837 for(y=0; y<ym; y++) {
839 for(x=0; x<xm; x++) {
841 i_gpix(im, x, y, &val1);
842 i_gpix(im, x2, y2, &val2);
843 i_ppix(im, x, y, &val2);
844 i_ppix(im, x2, y2, &val1);
846 i_gpix(im, x2, y, &val1);
847 i_gpix(im, x, y2, &val2);
848 i_ppix(im, x2, y, &val2);
849 i_ppix(im, x, y2, &val1);
854 if (xm*2 != xs) { /* odd number of column */
855 mm_log((1, "i_flipxy: odd number of columns\n"));
858 for(y=0; y<ym; y++) {
860 i_gpix(im, x, y, &val1);
861 i_gpix(im, x, y2, &val2);
862 i_ppix(im, x, y, &val2);
863 i_ppix(im, x, y2, &val1);
867 if (ym*2 != ys) { /* odd number of rows */
868 mm_log((1, "i_flipxy: odd number of rows\n"));
871 for(x=0; x<xm; x++) {
873 i_gpix(im, x, y, &val1);
874 i_gpix(im, x2, y, &val2);
875 i_ppix(im, x, y, &val2);
876 i_ppix(im, x2, y, &val1);
882 mm_log((1, "i_flipxy: direction is invalid\n" ));
900 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
901 else if (x == 0.0) return (1.0);
902 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
906 =item i_scaleaxis(im, value, axis)
908 Returns a new image object which is I<im> scaled by I<value> along
909 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
915 i_scaleaxis(i_img *im, float Value, int Axis) {
916 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
917 int LanczosWidthFactor;
918 float *l0, *l1, OldLocation;
919 int T, TempJump1, TempJump2;
920 float F, PictureValue[MAXCHANNELS];
922 i_color val,val1,val2;
925 mm_log((1,"i_scaleaxis(im 0x%x,Value %.2f,Axis %d)\n",im,Value,Axis));
928 hsize = (int) ((float) im->xsize * Value);
934 TempJump1 = (hsize - 1) * 3;
935 TempJump2 = hsize * (vsize - 1) * 3 + TempJump1;
938 vsize = (int) ((float) im->ysize * Value);
947 new_img=i_img_empty_ch(NULL,hsize,vsize,im->channels);
949 if (Value >=1) LanczosWidthFactor = 1;
950 else LanczosWidthFactor = (int) (1.0/Value);
952 lMax = LanczosWidthFactor << 1;
954 l0 = (float *) mymalloc(lMax * sizeof(float));
955 l1 = (float *) mymalloc(lMax * sizeof(float));
957 for (j=0; j<jEnd; j++) {
958 OldLocation = ((float) j) / Value;
959 T = (int) (OldLocation);
960 F = OldLocation - (float) T;
962 for (l = 0; l < lMax; l++) {
963 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
964 l1[l] = Lanczos(((float) (l + 1) - F) / (float) LanczosWidthFactor);
969 for (i=0; i<iEnd; i++) {
970 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
971 for (l=0; l < lMax; l++) {
972 i_gpix(im,T+l+1, i, &val1);
973 i_gpix(im,T-lMax+l+1, i, &val2);
974 for (k=0; k<im->channels; k++) {
975 PictureValue[k] += l1[l] * val1.channel[k];
976 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
979 for(k=0;k<im->channels;k++) {
980 psave = (short)( PictureValue[k] / LanczosWidthFactor);
981 val.channel[k]=minmax(0,255,psave);
983 i_ppix(new_img,j,i,&val);
988 for (i=0; i<iEnd; i++) {
989 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
990 for (l=0; l < lMax; l++) {
991 i_gpix(im,i, T+l+1, &val1);
992 i_gpix(im,i, T-lMax+l+1, &val2);
993 for (k=0; k<im->channels; k++) {
994 PictureValue[k] += l1[l] * val1.channel[k];
995 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
998 for (k=0; k<im->channels; k++) {
999 psave = (short)( PictureValue[k] / LanczosWidthFactor);
1000 val.channel[k]=minmax(0,255,psave);
1002 i_ppix(new_img,i,j,&val);
1010 mm_log((1,"(0x%x) <- i_scaleaxis\n",new_img));
1017 =item i_scale_nn(im, scx, scy)
1019 Scale by using nearest neighbor
1020 Both axes scaled at the same time since
1021 nothing is gained by doing it in two steps
1028 i_scale_nn(i_img *im, float scx, float scy) {
1030 int nxsize,nysize,nx,ny;
1034 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1036 nxsize = (int) ((float) im->xsize * scx);
1037 nysize = (int) ((float) im->ysize * scy);
1039 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1041 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1042 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1043 i_ppix(new_img,nx,ny,&val);
1046 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1052 =item i_sametype(i_img *im, int xsize, int ysize)
1054 Returns an image of the same type (sample size, channels, paletted/direct).
1056 For paletted images the palette is copied from the source.
1061 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1062 if (src->type == i_direct_type) {
1063 if (src->bits == 8) {
1064 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1066 else if (src->bits == 16) {
1067 return i_img_16_new(xsize, ysize, src->channels);
1070 i_push_error(0, "Unknown image bits");
1078 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1079 for (i = 0; i < i_colorcount(src); ++i) {
1080 i_getcolors(src, i, &col, 1);
1081 i_addcolors(targ, &col, 1);
1089 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1091 Spatially transforms I<im> returning a new image.
1093 opx for a length of opxl and opy for a length of opy are arrays of
1094 operators that modify the x and y positions to retreive the pixel data from.
1096 parm and parmlen define extra parameters that the operators may use.
1098 Note that this function is largely superseded by the more flexible
1099 L<transform.c/i_transform2>.
1101 Returns the new image.
1103 The operators for this function are defined in L<stackmach.c>.
1108 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1110 int nxsize,nysize,nx,ny;
1114 mm_log((1,"i_transform(im 0x%x, opx 0x%x, opxl %d, opy 0x%x, opyl %d, parm 0x%x, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
1117 nysize = im->ysize ;
1119 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1120 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
1121 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1122 /* parm[parmlen-2]=(double)nx;
1123 parm[parmlen-1]=(double)ny; */
1128 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
1129 rx=op_run(opx,opxl,parm,parmlen);
1130 ry=op_run(opy,opyl,parm,parmlen);
1131 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
1132 i_gpix(im,rx,ry,&val);
1133 i_ppix(new_img,nx,ny,&val);
1136 mm_log((1,"(0x%x) <- i_transform\n",new_img));
1141 =item i_img_diff(im1, im2)
1143 Calculates the sum of the squares of the differences between
1144 correspoding channels in two images.
1146 If the images are not the same size then only the common area is
1147 compared, hence even if images are different sizes this function
1153 i_img_diff(i_img *im1,i_img *im2) {
1154 int x,y,ch,xb,yb,chb;
1158 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1160 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1161 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1162 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1164 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1167 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1168 i_gpix(im1,x,y,&val1);
1169 i_gpix(im2,x,y,&val2);
1171 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1173 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1177 /* just a tiny demo of haar wavelets */
1185 i_img *new_img,*new_img2;
1186 i_color val1,val2,dval1,dval2;
1194 /* horizontal pass */
1196 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1197 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1200 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1201 i_gpix(im,x*2,y,&val1);
1202 i_gpix(im,x*2+1,y,&val2);
1203 for(ch=0;ch<im->channels;ch++) {
1204 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1205 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1207 i_ppix(new_img,x,y,&dval1);
1208 i_ppix(new_img,x+fx,y,&dval2);
1211 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1212 i_gpix(new_img,x,y*2,&val1);
1213 i_gpix(new_img,x,y*2+1,&val2);
1214 for(ch=0;ch<im->channels;ch++) {
1215 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1216 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1218 i_ppix(new_img2,x,y,&dval1);
1219 i_ppix(new_img2,x,y+fy,&dval2);
1222 i_img_destroy(new_img);
1227 =item i_count_colors(im, maxc)
1229 returns number of colors or -1
1230 to indicate that it was more than max colors
1235 i_count_colors(i_img *im,int maxc) {
1242 mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
1249 for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
1250 i_gpix(im,x,y,&val);
1251 colorcnt+=octt_add(ct,val.rgb.r,val.rgb.g,val.rgb.b);
1252 if (colorcnt > maxc) { octt_delete(ct); return -1; }
1259 symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
1260 i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
1261 i_img_info,i_img_setmask,i_img_getmask,i_ppix,i_gpix,
1262 i_box,i_draw,i_arc,i_copyto,i_copyto_trans,i_rubthru};
1268 =head2 8-bit per sample image internal functions
1270 These are the functions installed in an 8-bit per sample image.
1274 =item i_ppix_d(im, x, y, col)
1278 This is the function kept in the i_f_ppix member of an i_img object.
1279 It does a normal store of a pixel into the image with range checking.
1281 Returns 0 if the pixel could be set, -1 otherwise.
1286 i_ppix_d(i_img *im, int x, int y, i_color *val) {
1289 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1290 for(ch=0;ch<im->channels;ch++)
1291 if (im->ch_mask&(1<<ch))
1292 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1295 return -1; /* error was clipped */
1299 =item i_gpix_d(im, x, y, &col)
1303 This is the function kept in the i_f_gpix member of an i_img object.
1304 It does normal retrieval of a pixel from the image with range checking.
1306 Returns 0 if the pixel could be set, -1 otherwise.
1311 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1313 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1314 for(ch=0;ch<im->channels;ch++)
1315 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1318 return -1; /* error was cliped */
1322 =item i_glin_d(im, l, r, y, vals)
1324 Reads a line of data from the image, storing the pixels at vals.
1326 The line runs from (l,y) inclusive to (r,y) non-inclusive
1328 vals should point at space for (r-l) pixels.
1330 l should never be less than zero (to avoid confusion about where to
1331 put the pixels in vals).
1333 Returns the number of pixels copied (eg. if r, l or y is out of range)
1338 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1340 unsigned char *data;
1341 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1344 data = im->idata + (l+y*im->xsize) * im->channels;
1346 for (i = 0; i < count; ++i) {
1347 for (ch = 0; ch < im->channels; ++ch)
1348 vals[i].channel[ch] = *data++;
1358 =item i_plin_d(im, l, r, y, vals)
1360 Writes a line of data into the image, using the pixels at vals.
1362 The line runs from (l,y) inclusive to (r,y) non-inclusive
1364 vals should point at (r-l) pixels.
1366 l should never be less than zero (to avoid confusion about where to
1367 get the pixels in vals).
1369 Returns the number of pixels copied (eg. if r, l or y is out of range)
1374 i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
1376 unsigned char *data;
1377 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1380 data = im->idata + (l+y*im->xsize) * im->channels;
1382 for (i = 0; i < count; ++i) {
1383 for (ch = 0; ch < im->channels; ++ch) {
1384 if (im->ch_mask & (1 << ch))
1385 *data = vals[i].channel[ch];
1397 =item i_ppixf_d(im, x, y, val)
1402 i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
1405 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1406 for(ch=0;ch<im->channels;ch++)
1407 if (im->ch_mask&(1<<ch)) {
1408 im->idata[(x+y*im->xsize)*im->channels+ch] =
1409 SampleFTo8(val->channel[ch]);
1413 return -1; /* error was clipped */
1417 =item i_gpixf_d(im, x, y, val)
1422 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1424 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1425 for(ch=0;ch<im->channels;ch++) {
1427 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1431 return -1; /* error was cliped */
1435 =item i_glinf_d(im, l, r, y, vals)
1437 Reads a line of data from the image, storing the pixels at vals.
1439 The line runs from (l,y) inclusive to (r,y) non-inclusive
1441 vals should point at space for (r-l) pixels.
1443 l should never be less than zero (to avoid confusion about where to
1444 put the pixels in vals).
1446 Returns the number of pixels copied (eg. if r, l or y is out of range)
1451 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1453 unsigned char *data;
1454 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1457 data = im->idata + (l+y*im->xsize) * im->channels;
1459 for (i = 0; i < count; ++i) {
1460 for (ch = 0; ch < im->channels; ++ch)
1461 vals[i].channel[ch] = Sample8ToF(*data++);
1471 =item i_plinf_d(im, l, r, y, vals)
1473 Writes a line of data into the image, using the pixels at vals.
1475 The line runs from (l,y) inclusive to (r,y) non-inclusive
1477 vals should point at (r-l) pixels.
1479 l should never be less than zero (to avoid confusion about where to
1480 get the pixels in vals).
1482 Returns the number of pixels copied (eg. if r, l or y is out of range)
1487 i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1489 unsigned char *data;
1490 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1493 data = im->idata + (l+y*im->xsize) * im->channels;
1495 for (i = 0; i < count; ++i) {
1496 for (ch = 0; ch < im->channels; ++ch) {
1497 if (im->ch_mask & (1 << ch))
1498 *data = SampleFTo8(vals[i].channel[ch]);
1510 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1512 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1513 for the channels specified by chans, an array of int with chan_count
1516 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1520 int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
1521 int *chans, int chan_count) {
1522 int ch, count, i, w;
1523 unsigned char *data;
1525 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1528 data = im->idata + (l+y*im->xsize) * im->channels;
1533 /* make sure we have good channel numbers */
1534 for (ch = 0; ch < chan_count; ++ch) {
1535 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1536 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1540 for (i = 0; i < w; ++i) {
1541 for (ch = 0; ch < chan_count; ++ch) {
1542 *samps++ = data[chans[ch]];
1545 data += im->channels;
1549 for (i = 0; i < w; ++i) {
1550 for (ch = 0; ch < chan_count; ++ch) {
1551 *samps++ = data[ch];
1554 data += im->channels;
1566 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1568 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1569 for the channels specified by chan_mask, where bit 0 is the first
1572 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1576 int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
1577 int *chans, int chan_count) {
1578 int ch, count, i, w;
1579 unsigned char *data;
1580 for (ch = 0; ch < chan_count; ++ch) {
1581 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1582 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1585 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1588 data = im->idata + (l+y*im->xsize) * im->channels;
1593 /* make sure we have good channel numbers */
1594 for (ch = 0; ch < chan_count; ++ch) {
1595 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1596 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1600 for (i = 0; i < w; ++i) {
1601 for (ch = 0; ch < chan_count; ++ch) {
1602 *samps++ = Sample8ToF(data[chans[ch]]);
1605 data += im->channels;
1609 for (i = 0; i < w; ++i) {
1610 for (ch = 0; ch < chan_count; ++ch) {
1611 *samps++ = Sample8ToF(data[ch]);
1614 data += im->channels;
1627 =head2 Image method wrappers
1629 These functions provide i_fsample_t functions in terms of their
1630 i_sample_t versions.
1634 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1639 int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1643 for (ch = 0; ch < im->channels; ++ch)
1644 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1646 return i_ppix(im, x, y, &temp);
1650 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1654 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1658 if (i_gpix(im, x, y, &temp)) {
1659 for (ch = 0; ch < im->channels; ++ch)
1660 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1668 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1672 int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1675 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1681 work = mymalloc(sizeof(i_color) * (r-l));
1682 for (i = 0; i < r-l; ++i) {
1683 for (ch = 0; ch < im->channels; ++ch)
1684 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1686 ret = i_plin(im, l, r, y, work);
1701 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1705 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1708 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1714 work = mymalloc(sizeof(i_color) * (r-l));
1715 ret = i_plin(im, l, r, y, work);
1716 for (i = 0; i < r-l; ++i) {
1717 for (ch = 0; ch < im->channels; ++ch)
1718 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1734 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1738 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
1739 int *chans, int chan_count) {
1742 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1748 work = mymalloc(sizeof(i_sample_t) * (r-l));
1749 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1750 for (i = 0; i < ret; ++i) {
1751 samp[i] = Sample8ToF(work[i]);
1769 =head2 Palette wrapper functions
1771 Used for virtual images, these forward palette calls to a wrapped image,
1772 assuming the wrapped image is the first pointer in the structure that
1773 im->ext_data points at.
1777 =item i_addcolors_forward(i_img *im, i_color *colors, int count)
1781 int i_addcolors_forward(i_img *im, i_color *colors, int count) {
1782 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1786 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1790 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1791 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1795 =item i_setcolors_forward(i_img *im, int i, i_color *color, int count)
1799 int i_setcolors_forward(i_img *im, int i, i_color *color, int count) {
1800 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1804 =item i_colorcount_forward(i_img *im)
1808 int i_colorcount_forward(i_img *im) {
1809 return i_colorcount(*(i_img **)im->ext_data);
1813 =item i_maxcolors_forward(i_img *im)
1817 int i_maxcolors_forward(i_img *im) {
1818 return i_maxcolors(*(i_img **)im->ext_data);
1822 =item i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry)
1826 int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry) {
1827 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1833 =head2 Stream reading and writing wrapper functions
1837 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1839 Performs general read buffering for file readers that permit reading
1840 to be done through a callback.
1842 The final callback gets two parameters, a I<need> value, and a I<want>
1843 value, where I<need> is the amount of data that the file library needs
1844 to read, and I<want> is the amount of space available in the buffer
1845 maintained by these functions.
1847 This means if you need to read from a stream that you don't know the
1848 length of, you can return I<need> bytes, taking the performance hit of
1849 possibly expensive callbacks (eg. back to perl code), or if you are
1850 reading from a stream where it doesn't matter if some data is lost, or
1851 if the total length of the stream is known, you can return I<want>
1858 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1861 if (length < gci->length - gci->cpos) {
1863 memcpy(buf, gci->buffer+gci->cpos, length);
1864 gci->cpos += length;
1869 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
1870 total += gci->length - gci->cpos;
1871 length -= gci->length - gci->cpos;
1872 buf += gci->length - gci->cpos;
1873 if (length < (int)sizeof(gci->buffer)) {
1877 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
1878 sizeof(gci->buffer))) > 0) {
1880 gci->length = did_read;
1882 copy_size = min(length, gci->length);
1883 memcpy(buf, gci->buffer, copy_size);
1884 gci->cpos += copy_size;
1887 length -= copy_size;
1891 /* just read the rest - too big for our buffer*/
1893 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1903 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1905 For use by callback file readers to initialize the reader buffer.
1907 Allocates, initializes and returns the reader buffer.
1909 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1914 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1915 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1917 self->userdata = userdata;
1925 =item free_gen_read_data(i_gen_read_data *)
1931 void free_gen_read_data(i_gen_read_data *self) {
1936 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1938 Performs write buffering for a callback based file writer.
1940 Failures are considered fatal, if a write fails then data will be
1947 i_gen_write_data *self,
1951 if (self->filledto && self->filledto+size > self->maxlength) {
1952 if (self->cb(self->userdata, self->buffer, self->filledto)) {
1960 if (self->filledto+size <= self->maxlength) {
1962 memcpy(self->buffer+self->filledto, data, size);
1963 self->filledto += size;
1966 /* doesn't fit - hand it off */
1967 return self->cb(self->userdata, data, size);
1971 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
1973 Allocates and initializes the data structure used by i_gen_writer.
1975 This should be released with L<image.c/free_gen_write_data>
1979 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
1980 char *userdata, int max_length)
1982 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
1984 self->userdata = userdata;
1985 self->maxlength = min(max_length, sizeof(self->buffer));
1986 if (self->maxlength < 0)
1987 self->maxlength = sizeof(self->buffer);
1994 =item free_gen_write_data(i_gen_write_data *info, int flush)
1996 Cleans up the write buffer.
1998 Will flush any left-over data if I<flush> is non-zero.
2000 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2002 Return zero only if flush is non-zero and info->cb() returns zero.
2008 int free_gen_write_data(i_gen_write_data *info, int flush)
2010 int result = !flush ||
2011 info->filledto == 0 ||
2012 info->cb(info->userdata, info->buffer, info->filledto);