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 %p)\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);
651 if (src->bits == i_16_bits)
652 i_img_16_new_low(im, x1, y1, src->channels);
653 else if (src->bits == i_double_bits)
654 i_img_double_new_low(im, x1, y1, src->channels);
656 fprintf(stderr, "i_copy(): Unknown image bit size %d\n", src->bits);
657 return; /* I dunno */
660 pv = mymalloc(sizeof(i_fcolor) * x1);
661 for (y = 0; y < y1; ++y) {
662 i_glinf(src, 0, x1, y, pv);
663 i_plinf(im, 0, x1, y, pv);
675 i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
676 /* copy across the palette */
677 count = i_colorcount(src);
678 for (index = 0; index < count; ++index) {
679 i_getcolors(src, index, &temp, 1);
680 i_addcolors(im, &temp, 1);
683 vals = mymalloc(sizeof(i_palidx) * x1);
684 for (y = 0; y < y1; ++y) {
685 i_gpal(src, 0, x1, y, vals);
686 i_ppal(im, 0, x1, y, vals);
694 =item i_rubthru(im, src, tx, ty)
696 Takes the image I<src> and applies it at an original (I<tx>,I<ty>) in I<im>.
698 The alpha channel of each pixel in I<src> is used to control how much
699 the existing colour in I<im> is replaced, if it is 255 then the colour
700 is completely replaced, if it is 0 then the original colour is left
707 i_rubthru(i_img *im,i_img *src,int tx,int ty) {
714 mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d)\n", im, src, tx, ty));
717 if (im->channels == 3 && src->channels == 4) {
719 chans[0] = 0; chans[1] = 1; chans[2] = 2;
722 else if (im->channels == 3 && src->channels == 2) {
724 chans[0] = chans[1] = chans[2] = 0;
727 else if (im->channels == 1 && src->channels == 2) {
733 i_push_error(0, "rubthru can only work where (dest, src) channels are (3,4), (3,2) or (1,2)");
738 /* if you change this code, please make sure the else branch is
739 changed in a similar fashion - TC */
741 i_color pv, orig, dest;
743 for(x=0; x<src->xsize; x++) {
745 for(y=0;y<src->ysize;y++) {
746 /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
747 i_gpix(src, x, y, &pv);
748 i_gpix(im, ttx, tty, &orig);
749 alpha = pv.channel[alphachan];
750 for (ch = 0; ch < chancount; ++ch) {
751 dest.channel[ch] = (alpha * pv.channel[chans[ch]]
752 + (255 - alpha) * orig.channel[ch])/255;
754 i_ppix(im, ttx, tty, &dest);
762 i_fcolor pv, orig, dest;
765 for(x=0; x<src->xsize; x++) {
767 for(y=0;y<src->ysize;y++) {
768 /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
769 i_gpixf(src, x, y, &pv);
770 i_gpixf(im, ttx, tty, &orig);
771 alpha = pv.channel[alphachan];
772 for (ch = 0; ch < chancount; ++ch) {
773 dest.channel[ch] = alpha * pv.channel[chans[ch]]
774 + (1 - alpha) * orig.channel[ch];
776 i_ppixf(im, ttx, tty, &dest);
788 =item i_flipxy(im, axis)
790 Flips the image inplace around the axis specified.
791 Returns 0 if parameters are invalid.
794 axis - 0 = x, 1 = y, 2 = both
800 i_flipxy(i_img *im, int direction) {
801 int x, x2, y, y2, xm, ym;
805 mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
810 case XAXIS: /* Horizontal flip */
813 for(y=0; y<ym; y++) {
815 for(x=0; x<xm; x++) {
817 i_gpix(im, x, y, &val1);
818 i_gpix(im, x2, y, &val2);
819 i_ppix(im, x, y, &val2);
820 i_ppix(im, x2, y, &val1);
825 case YAXIS: /* Vertical flip */
829 for(y=0; y<ym; y++) {
830 for(x=0; x<xm; x++) {
832 i_gpix(im, x, y, &val1);
833 i_gpix(im, x, y2, &val2);
834 i_ppix(im, x, y, &val2);
835 i_ppix(im, x, y2, &val1);
840 case XYAXIS: /* Horizontal and Vertical flip */
844 for(y=0; y<ym; y++) {
846 for(x=0; x<xm; x++) {
848 i_gpix(im, x, y, &val1);
849 i_gpix(im, x2, y2, &val2);
850 i_ppix(im, x, y, &val2);
851 i_ppix(im, x2, y2, &val1);
853 i_gpix(im, x2, y, &val1);
854 i_gpix(im, x, y2, &val2);
855 i_ppix(im, x2, y, &val2);
856 i_ppix(im, x, y2, &val1);
861 if (xm*2 != xs) { /* odd number of column */
862 mm_log((1, "i_flipxy: odd number of columns\n"));
865 for(y=0; y<ym; y++) {
867 i_gpix(im, x, y, &val1);
868 i_gpix(im, x, y2, &val2);
869 i_ppix(im, x, y, &val2);
870 i_ppix(im, x, y2, &val1);
874 if (ym*2 != ys) { /* odd number of rows */
875 mm_log((1, "i_flipxy: odd number of rows\n"));
878 for(x=0; x<xm; x++) {
880 i_gpix(im, x, y, &val1);
881 i_gpix(im, x2, y, &val2);
882 i_ppix(im, x, y, &val2);
883 i_ppix(im, x2, y, &val1);
889 mm_log((1, "i_flipxy: direction is invalid\n" ));
907 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
908 else if (x == 0.0) return (1.0);
909 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
913 =item i_scaleaxis(im, value, axis)
915 Returns a new image object which is I<im> scaled by I<value> along
916 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
922 i_scaleaxis(i_img *im, float Value, int Axis) {
923 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
924 int LanczosWidthFactor;
925 float *l0, *l1, OldLocation;
928 float F, PictureValue[MAXCHANNELS];
930 i_color val,val1,val2;
933 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
936 hsize = (int)(0.5 + im->xsize * Value);
943 vsize = (int)(0.5 + im->ysize * Value);
949 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
951 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
952 LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value);
953 lMax = LanczosWidthFactor << 1;
955 l0 = mymalloc(lMax * sizeof(float));
956 l1 = mymalloc(lMax * sizeof(float));
958 for (j=0; j<jEnd; j++) {
959 OldLocation = ((float) j) / Value;
960 T = (int) (OldLocation);
961 F = OldLocation - (float) T;
963 for (l = 0; l<lMax; l++) {
964 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
965 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
968 /* Make sure filter is normalized */
970 for(l=0; l<lMax; l++) {
974 t /= (float)LanczosWidthFactor;
976 for(l=0; l<lMax; l++) {
983 for (i=0; i<iEnd; i++) {
984 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
985 for (l=0; l<lMax; l++) {
988 mx = (mx < 0) ? 0 : mx;
989 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
991 i_gpix(im, Mx, i, &val1);
992 i_gpix(im, mx, i, &val2);
994 for (k=0; k<im->channels; k++) {
995 PictureValue[k] += l1[l] * val1.channel[k];
996 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
999 for(k=0;k<im->channels;k++) {
1000 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
1001 val.channel[k]=minmax(0,255,psave);
1003 i_ppix(new_img, j, i, &val);
1008 for (i=0; i<iEnd; i++) {
1009 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
1010 for (l=0; l < lMax; l++) {
1011 int mx = T-lMax+l+1;
1013 mx = (mx < 0) ? 0 : mx;
1014 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
1016 i_gpix(im, i, Mx, &val1);
1017 i_gpix(im, i, mx, &val2);
1018 for (k=0; k<im->channels; k++) {
1019 PictureValue[k] += l1[l] * val1.channel[k];
1020 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
1023 for (k=0; k<im->channels; k++) {
1024 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
1025 val.channel[k] = minmax(0, 255, psave);
1027 i_ppix(new_img, i, j, &val);
1035 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
1042 =item i_scale_nn(im, scx, scy)
1044 Scale by using nearest neighbor
1045 Both axes scaled at the same time since
1046 nothing is gained by doing it in two steps
1053 i_scale_nn(i_img *im, float scx, float scy) {
1055 int nxsize,nysize,nx,ny;
1059 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1061 nxsize = (int) ((float) im->xsize * scx);
1062 nysize = (int) ((float) im->ysize * scy);
1064 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1066 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1067 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1068 i_ppix(new_img,nx,ny,&val);
1071 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1077 =item i_sametype(i_img *im, int xsize, int ysize)
1079 Returns an image of the same type (sample size, channels, paletted/direct).
1081 For paletted images the palette is copied from the source.
1086 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1087 if (src->type == i_direct_type) {
1088 if (src->bits == 8) {
1089 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1091 else if (src->bits == i_16_bits) {
1092 return i_img_16_new(xsize, ysize, src->channels);
1094 else if (src->bits == i_double_bits) {
1095 return i_img_double_new(xsize, ysize, src->channels);
1098 i_push_error(0, "Unknown image bits");
1106 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1107 for (i = 0; i < i_colorcount(src); ++i) {
1108 i_getcolors(src, i, &col, 1);
1109 i_addcolors(targ, &col, 1);
1117 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1119 Spatially transforms I<im> returning a new image.
1121 opx for a length of opxl and opy for a length of opy are arrays of
1122 operators that modify the x and y positions to retreive the pixel data from.
1124 parm and parmlen define extra parameters that the operators may use.
1126 Note that this function is largely superseded by the more flexible
1127 L<transform.c/i_transform2>.
1129 Returns the new image.
1131 The operators for this function are defined in L<stackmach.c>.
1136 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1138 int nxsize,nysize,nx,ny;
1142 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));
1145 nysize = im->ysize ;
1147 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1148 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
1149 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1150 /* parm[parmlen-2]=(double)nx;
1151 parm[parmlen-1]=(double)ny; */
1156 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
1157 rx=op_run(opx,opxl,parm,parmlen);
1158 ry=op_run(opy,opyl,parm,parmlen);
1159 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
1160 i_gpix(im,rx,ry,&val);
1161 i_ppix(new_img,nx,ny,&val);
1164 mm_log((1,"(0x%x) <- i_transform\n",new_img));
1169 =item i_img_diff(im1, im2)
1171 Calculates the sum of the squares of the differences between
1172 correspoding channels in two images.
1174 If the images are not the same size then only the common area is
1175 compared, hence even if images are different sizes this function
1181 i_img_diff(i_img *im1,i_img *im2) {
1182 int x,y,ch,xb,yb,chb;
1186 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1188 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1189 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1190 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1192 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1195 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1196 i_gpix(im1,x,y,&val1);
1197 i_gpix(im2,x,y,&val2);
1199 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1201 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1205 /* just a tiny demo of haar wavelets */
1213 i_img *new_img,*new_img2;
1214 i_color val1,val2,dval1,dval2;
1222 /* horizontal pass */
1224 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1225 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1228 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1229 i_gpix(im,x*2,y,&val1);
1230 i_gpix(im,x*2+1,y,&val2);
1231 for(ch=0;ch<im->channels;ch++) {
1232 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1233 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1235 i_ppix(new_img,x,y,&dval1);
1236 i_ppix(new_img,x+fx,y,&dval2);
1239 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1240 i_gpix(new_img,x,y*2,&val1);
1241 i_gpix(new_img,x,y*2+1,&val2);
1242 for(ch=0;ch<im->channels;ch++) {
1243 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1244 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1246 i_ppix(new_img2,x,y,&dval1);
1247 i_ppix(new_img2,x,y+fy,&dval2);
1250 i_img_destroy(new_img);
1255 =item i_count_colors(im, maxc)
1257 returns number of colors or -1
1258 to indicate that it was more than max colors
1263 i_count_colors(i_img *im,int maxc) {
1270 mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
1277 for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
1278 i_gpix(im,x,y,&val);
1279 colorcnt+=octt_add(ct,val.rgb.r,val.rgb.g,val.rgb.b);
1280 if (colorcnt > maxc) { octt_delete(ct); return -1; }
1287 symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
1288 i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
1289 i_img_info,i_img_setmask,i_img_getmask,i_ppix,i_gpix,
1290 i_box,i_draw,i_arc,i_copyto,i_copyto_trans,i_rubthru};
1296 =head2 8-bit per sample image internal functions
1298 These are the functions installed in an 8-bit per sample image.
1302 =item i_ppix_d(im, x, y, col)
1306 This is the function kept in the i_f_ppix member of an i_img object.
1307 It does a normal store of a pixel into the image with range checking.
1309 Returns 0 if the pixel could be set, -1 otherwise.
1315 i_ppix_d(i_img *im, int x, int y, i_color *val) {
1318 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1319 for(ch=0;ch<im->channels;ch++)
1320 if (im->ch_mask&(1<<ch))
1321 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1324 return -1; /* error was clipped */
1328 =item i_gpix_d(im, x, y, &col)
1332 This is the function kept in the i_f_gpix member of an i_img object.
1333 It does normal retrieval of a pixel from the image with range checking.
1335 Returns 0 if the pixel could be set, -1 otherwise.
1341 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1343 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1344 for(ch=0;ch<im->channels;ch++)
1345 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1348 for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1349 return -1; /* error was cliped */
1353 =item i_glin_d(im, l, r, y, vals)
1355 Reads a line of data from the image, storing the pixels at vals.
1357 The line runs from (l,y) inclusive to (r,y) non-inclusive
1359 vals should point at space for (r-l) pixels.
1361 l should never be less than zero (to avoid confusion about where to
1362 put the pixels in vals).
1364 Returns the number of pixels copied (eg. if r, l or y is out of range)
1370 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1372 unsigned char *data;
1373 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1376 data = im->idata + (l+y*im->xsize) * im->channels;
1378 for (i = 0; i < count; ++i) {
1379 for (ch = 0; ch < im->channels; ++ch)
1380 vals[i].channel[ch] = *data++;
1390 =item i_plin_d(im, l, r, y, vals)
1392 Writes a line of data into the image, using the pixels at vals.
1394 The line runs from (l,y) inclusive to (r,y) non-inclusive
1396 vals should point at (r-l) pixels.
1398 l should never be less than zero (to avoid confusion about where to
1399 get the pixels in vals).
1401 Returns the number of pixels copied (eg. if r, l or y is out of range)
1407 i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
1409 unsigned char *data;
1410 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1413 data = im->idata + (l+y*im->xsize) * im->channels;
1415 for (i = 0; i < count; ++i) {
1416 for (ch = 0; ch < im->channels; ++ch) {
1417 if (im->ch_mask & (1 << ch))
1418 *data = vals[i].channel[ch];
1430 =item i_ppixf_d(im, x, y, val)
1436 i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
1439 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1440 for(ch=0;ch<im->channels;ch++)
1441 if (im->ch_mask&(1<<ch)) {
1442 im->idata[(x+y*im->xsize)*im->channels+ch] =
1443 SampleFTo8(val->channel[ch]);
1447 return -1; /* error was clipped */
1451 =item i_gpixf_d(im, x, y, val)
1457 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1459 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1460 for(ch=0;ch<im->channels;ch++) {
1462 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1466 return -1; /* error was cliped */
1470 =item i_glinf_d(im, l, r, y, vals)
1472 Reads a line of data from the image, storing the pixels at vals.
1474 The line runs from (l,y) inclusive to (r,y) non-inclusive
1476 vals should point at space for (r-l) pixels.
1478 l should never be less than zero (to avoid confusion about where to
1479 put the pixels in vals).
1481 Returns the number of pixels copied (eg. if r, l or y is out of range)
1487 i_glinf_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 vals[i].channel[ch] = Sample8ToF(*data++);
1507 =item i_plinf_d(im, l, r, y, vals)
1509 Writes a line of data into the image, using the pixels at vals.
1511 The line runs from (l,y) inclusive to (r,y) non-inclusive
1513 vals should point at (r-l) pixels.
1515 l should never be less than zero (to avoid confusion about where to
1516 get the pixels in vals).
1518 Returns the number of pixels copied (eg. if r, l or y is out of range)
1524 i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1526 unsigned char *data;
1527 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1530 data = im->idata + (l+y*im->xsize) * im->channels;
1532 for (i = 0; i < count; ++i) {
1533 for (ch = 0; ch < im->channels; ++ch) {
1534 if (im->ch_mask & (1 << ch))
1535 *data = SampleFTo8(vals[i].channel[ch]);
1547 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1549 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1550 for the channels specified by chans, an array of int with chan_count
1553 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1559 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
1560 int *chans, int chan_count) {
1561 int ch, count, i, w;
1562 unsigned char *data;
1564 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1567 data = im->idata + (l+y*im->xsize) * im->channels;
1572 /* make sure we have good channel numbers */
1573 for (ch = 0; ch < chan_count; ++ch) {
1574 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1575 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1579 for (i = 0; i < w; ++i) {
1580 for (ch = 0; ch < chan_count; ++ch) {
1581 *samps++ = data[chans[ch]];
1584 data += im->channels;
1588 for (i = 0; i < w; ++i) {
1589 for (ch = 0; ch < chan_count; ++ch) {
1590 *samps++ = data[ch];
1593 data += im->channels;
1605 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1607 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1608 for the channels specified by chan_mask, where bit 0 is the first
1611 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1617 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
1618 int *chans, int chan_count) {
1619 int ch, count, i, w;
1620 unsigned char *data;
1621 for (ch = 0; ch < chan_count; ++ch) {
1622 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1623 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1626 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1629 data = im->idata + (l+y*im->xsize) * im->channels;
1634 /* make sure we have good channel numbers */
1635 for (ch = 0; ch < chan_count; ++ch) {
1636 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1637 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1641 for (i = 0; i < w; ++i) {
1642 for (ch = 0; ch < chan_count; ++ch) {
1643 *samps++ = Sample8ToF(data[chans[ch]]);
1646 data += im->channels;
1650 for (i = 0; i < w; ++i) {
1651 for (ch = 0; ch < chan_count; ++ch) {
1652 *samps++ = Sample8ToF(data[ch]);
1655 data += im->channels;
1668 =head2 Image method wrappers
1670 These functions provide i_fsample_t functions in terms of their
1671 i_sample_t versions.
1675 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1680 int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1684 for (ch = 0; ch < im->channels; ++ch)
1685 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1687 return i_ppix(im, x, y, &temp);
1691 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1695 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1699 if (i_gpix(im, x, y, &temp)) {
1700 for (ch = 0; ch < im->channels; ++ch)
1701 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1709 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1713 int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1716 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1722 work = mymalloc(sizeof(i_color) * (r-l));
1723 for (i = 0; i < r-l; ++i) {
1724 for (ch = 0; ch < im->channels; ++ch)
1725 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1727 ret = i_plin(im, l, r, y, work);
1742 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1746 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1749 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1755 work = mymalloc(sizeof(i_color) * (r-l));
1756 ret = i_plin(im, l, r, y, work);
1757 for (i = 0; i < r-l; ++i) {
1758 for (ch = 0; ch < im->channels; ++ch)
1759 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1775 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1779 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
1780 int *chans, int chan_count) {
1783 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1789 work = mymalloc(sizeof(i_sample_t) * (r-l));
1790 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1791 for (i = 0; i < ret; ++i) {
1792 samp[i] = Sample8ToF(work[i]);
1810 =head2 Palette wrapper functions
1812 Used for virtual images, these forward palette calls to a wrapped image,
1813 assuming the wrapped image is the first pointer in the structure that
1814 im->ext_data points at.
1818 =item i_addcolors_forward(i_img *im, i_color *colors, int count)
1822 int i_addcolors_forward(i_img *im, i_color *colors, int count) {
1823 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1827 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1831 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1832 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1836 =item i_setcolors_forward(i_img *im, int i, i_color *color, int count)
1840 int i_setcolors_forward(i_img *im, int i, i_color *color, int count) {
1841 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1845 =item i_colorcount_forward(i_img *im)
1849 int i_colorcount_forward(i_img *im) {
1850 return i_colorcount(*(i_img **)im->ext_data);
1854 =item i_maxcolors_forward(i_img *im)
1858 int i_maxcolors_forward(i_img *im) {
1859 return i_maxcolors(*(i_img **)im->ext_data);
1863 =item i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry)
1867 int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry) {
1868 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1874 =head2 Stream reading and writing wrapper functions
1878 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1880 Performs general read buffering for file readers that permit reading
1881 to be done through a callback.
1883 The final callback gets two parameters, a I<need> value, and a I<want>
1884 value, where I<need> is the amount of data that the file library needs
1885 to read, and I<want> is the amount of space available in the buffer
1886 maintained by these functions.
1888 This means if you need to read from a stream that you don't know the
1889 length of, you can return I<need> bytes, taking the performance hit of
1890 possibly expensive callbacks (eg. back to perl code), or if you are
1891 reading from a stream where it doesn't matter if some data is lost, or
1892 if the total length of the stream is known, you can return I<want>
1899 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1902 if (length < gci->length - gci->cpos) {
1904 memcpy(buf, gci->buffer+gci->cpos, length);
1905 gci->cpos += length;
1910 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
1911 total += gci->length - gci->cpos;
1912 length -= gci->length - gci->cpos;
1913 buf += gci->length - gci->cpos;
1914 if (length < (int)sizeof(gci->buffer)) {
1918 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
1919 sizeof(gci->buffer))) > 0) {
1921 gci->length = did_read;
1923 copy_size = min(length, gci->length);
1924 memcpy(buf, gci->buffer, copy_size);
1925 gci->cpos += copy_size;
1928 length -= copy_size;
1932 /* just read the rest - too big for our buffer*/
1934 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1944 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1946 For use by callback file readers to initialize the reader buffer.
1948 Allocates, initializes and returns the reader buffer.
1950 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1955 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1956 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1958 self->userdata = userdata;
1966 =item free_gen_read_data(i_gen_read_data *)
1972 void free_gen_read_data(i_gen_read_data *self) {
1977 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1979 Performs write buffering for a callback based file writer.
1981 Failures are considered fatal, if a write fails then data will be
1988 i_gen_write_data *self,
1992 if (self->filledto && self->filledto+size > self->maxlength) {
1993 if (self->cb(self->userdata, self->buffer, self->filledto)) {
2001 if (self->filledto+size <= self->maxlength) {
2003 memcpy(self->buffer+self->filledto, data, size);
2004 self->filledto += size;
2007 /* doesn't fit - hand it off */
2008 return self->cb(self->userdata, data, size);
2012 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2014 Allocates and initializes the data structure used by i_gen_writer.
2016 This should be released with L<image.c/free_gen_write_data>
2020 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
2021 char *userdata, int max_length)
2023 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2025 self->userdata = userdata;
2026 self->maxlength = min(max_length, sizeof(self->buffer));
2027 if (self->maxlength < 0)
2028 self->maxlength = sizeof(self->buffer);
2035 =item free_gen_write_data(i_gen_write_data *info, int flush)
2037 Cleans up the write buffer.
2039 Will flush any left-over data if I<flush> is non-zero.
2041 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2043 Return zero only if flush is non-zero and info->cb() returns zero.
2049 int free_gen_write_data(i_gen_write_data *info, int flush)
2051 int result = !flush ||
2052 info->filledto == 0 ||
2053 info->cb(info->userdata, info->buffer, info->filledto);
2064 Arnar M. Hrafnkelsson <addi@umich.edu>
2066 Tony Cook <tony@develop-help.com>