7 image.c - implements most of the basic functions of Imager and much of the rest
13 c = i_color_new(red, green, blue, alpha);
21 image.c implements the basic functions to create and destroy image and
22 color objects for Imager.
24 =head1 FUNCTION REFERENCE
26 Some of these functions are internal.
37 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) )
39 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
40 static void fake(void) { ceil(1); }
42 static int i_ppix_d(i_img *im, int x, int y, i_color *val);
43 static int i_gpix_d(i_img *im, int x, int y, i_color *val);
44 static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
45 static int i_plin_d(i_img *im, int l, int r, int y, i_color *vals);
46 static int i_ppixf_d(i_img *im, int x, int y, i_fcolor *val);
47 static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
48 static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
49 static int i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
50 static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
51 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
52 /*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
53 static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
56 =item ICL_new_internal(r, g, b, a)
58 Return a new color object with values passed to it.
60 r - red component (range: 0 - 255)
61 g - green component (range: 0 - 255)
62 b - blue component (range: 0 - 255)
63 a - alpha component (range: 0 - 255)
69 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
72 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
74 if ( (cl=mymalloc(sizeof(i_color))) == NULL) m_fatal(2,"malloc() error\n");
79 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
85 =item ICL_set_internal(cl, r, g, b, a)
87 Overwrite a color with new values.
89 cl - pointer to color object
90 r - red component (range: 0 - 255)
91 g - green component (range: 0 - 255)
92 b - blue component (range: 0 - 255)
93 a - alpha component (range: 0 - 255)
99 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
100 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
102 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
103 m_fatal(2,"malloc() error\n");
108 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
114 =item ICL_add(dst, src, ch)
116 Add src to dst inplace - dst is modified.
118 dst - pointer to destination color object
119 src - pointer to color object that is added
120 ch - number of channels
126 ICL_add(i_color *dst,i_color *src,int ch) {
129 tmp=dst->channel[i]+src->channel[i];
130 dst->channel[i]= tmp>255 ? 255:tmp;
137 Dump color information to log - strictly for debugging.
139 cl - pointer to color object
145 ICL_info(i_color *cl) {
146 mm_log((1,"i_color_info(cl* %p)\n",cl));
147 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
153 Destroy ancillary data for Color object.
155 cl - pointer to color object
161 ICL_DESTROY(i_color *cl) {
162 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
167 =item i_fcolor_new(double r, double g, double b, double a)
171 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
174 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
176 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) m_fatal(2,"malloc() error\n");
181 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
187 =item i_fcolor_destroy(i_fcolor *cl)
191 void i_fcolor_destroy(i_fcolor *cl) {
196 =item IIM_base_8bit_direct (static)
198 A static i_img object used to initialize direct 8-bit per sample images.
202 static i_img IIM_base_8bit_direct =
204 0, /* channels set */
205 0, 0, 0, /* xsize, ysize, bytes */
208 i_direct_type, /* type */
211 { 0, 0, NULL }, /* tags */
214 i_ppix_d, /* i_f_ppix */
215 i_ppixf_d, /* i_f_ppixf */
216 i_plin_d, /* i_f_plin */
217 i_plinf_d, /* i_f_plinf */
218 i_gpix_d, /* i_f_gpix */
219 i_gpixf_d, /* i_f_gpixf */
220 i_glin_d, /* i_f_glin */
221 i_glinf_d, /* i_f_glinf */
222 i_gsamp_d, /* i_f_gsamp */
223 i_gsampf_d, /* i_f_gsampf */
227 NULL, /* i_f_addcolors */
228 NULL, /* i_f_getcolors */
229 NULL, /* i_f_colorcount */
230 NULL, /* i_f_maxcolors */
231 NULL, /* i_f_findcolor */
232 NULL, /* i_f_setcolors */
234 NULL, /* i_f_destroy */
237 /*static void set_8bit_direct(i_img *im) {
238 im->i_f_ppix = i_ppix_d;
239 im->i_f_ppixf = i_ppixf_d;
240 im->i_f_plin = i_plin_d;
241 im->i_f_plinf = i_plinf_d;
242 im->i_f_gpix = i_gpix_d;
243 im->i_f_gpixf = i_gpixf_d;
244 im->i_f_glin = i_glin_d;
245 im->i_f_glinf = i_glinf_d;
248 im->i_f_addcolor = NULL;
249 im->i_f_getcolor = NULL;
250 im->i_f_colorcount = NULL;
251 im->i_f_findcolor = NULL;
255 =item IIM_new(x, y, ch)
257 Creates a new image object I<x> pixels wide, and I<y> pixels high with I<ch> channels.
264 IIM_new(int x,int y,int ch) {
266 mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
268 im=i_img_empty_ch(NULL,x,y,ch);
270 mm_log((1,"(%p) <- IIM_new\n",im));
276 IIM_DESTROY(i_img *im) {
277 mm_log((1,"IIM_DESTROY(im* %p)\n",im));
287 Create new image reference - notice that this isn't an object yet and
288 this should be fixed asap.
298 mm_log((1,"i_img_struct()\n"));
299 if ( (im=mymalloc(sizeof(i_img))) == NULL)
300 m_fatal(2,"malloc() error\n");
302 *im = IIM_base_8bit_direct;
310 mm_log((1,"(%p) <- i_img_struct\n",im));
315 =item i_img_empty(im, x, y)
317 Re-new image reference (assumes 3 channels)
320 x - xsize of destination image
321 y - ysize of destination image
323 **FIXME** what happens if a live image is passed in here?
325 Should this just call i_img_empty_ch()?
331 i_img_empty(i_img *im,int x,int y) {
332 mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
333 return i_img_empty_ch(im, x, y, 3);
337 =item i_img_empty_ch(im, x, y, ch)
339 Re-new image reference
342 x - xsize of destination image
343 y - ysize of destination image
344 ch - number of channels
350 i_img_empty_ch(i_img *im,int x,int y,int ch) {
353 mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
355 if (x < 1 || y < 1) {
356 i_push_error(0, "Image sizes must be positive");
359 if (ch < 1 || ch > MAXCHANNELS) {
360 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
363 /* check this multiplication doesn't overflow */
365 if (bytes / y / ch != x) {
366 i_push_errorf(0, "integer overflow calculating image allocation");
371 if ( (im=mymalloc(sizeof(i_img))) == NULL)
372 m_fatal(2,"malloc() error\n");
374 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
375 i_tags_new(&im->tags);
379 im->ch_mask = MAXINT;
381 if ( (im->idata=mymalloc(im->bytes)) == NULL)
382 m_fatal(2,"malloc() error\n");
383 memset(im->idata,0,(size_t)im->bytes);
387 mm_log((1,"(%p) <- i_img_empty_ch\n",im));
392 =item i_img_exorcise(im)
402 i_img_exorcise(i_img *im) {
403 mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
404 i_tags_destroy(&im->tags);
406 (im->i_f_destroy)(im);
407 if (im->idata != NULL) { myfree(im->idata); }
413 im->i_f_ppix=i_ppix_d;
414 im->i_f_gpix=i_gpix_d;
415 im->i_f_plin=i_plin_d;
416 im->i_f_glin=i_glin_d;
421 =item i_img_destroy(im)
423 Destroy image and free data via exorcise.
431 i_img_destroy(i_img *im) {
432 mm_log((1,"i_img_destroy(im %p)\n",im));
434 if (im) { myfree(im); }
438 =item i_img_info(im, info)
440 Return image information
443 info - pointer to array to return data
445 info is an array of 4 integers with the following values:
450 info[3] - channel mask
457 i_img_info(i_img *im,int *info) {
458 mm_log((1,"i_img_info(im 0x%x)\n",im));
460 mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
461 mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
464 info[2] = im->channels;
465 info[3] = im->ch_mask;
475 =item i_img_setmask(im, ch_mask)
477 Set the image channel mask for I<im> to I<ch_mask>.
482 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
486 =item i_img_getmask(im)
488 Get the image channel mask for I<im>.
493 i_img_getmask(i_img *im) { return im->ch_mask; }
496 =item i_img_getchannels(im)
498 Get the number of channels in I<im>.
503 i_img_getchannels(i_img *im) { return im->channels; }
508 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
510 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
511 (tx,ty) specifies the upper left corner for the target image.
512 pass NULL in trans for non transparent i_colors.
518 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans) {
520 int x,y,t,ttx,tty,tt,ch;
522 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",
523 im, src, x1, y1, x2, y2, tx, ty, trans));
525 if (x2<x1) { t=x1; x1=x2; x2=t; }
526 if (y2<y1) { t=y1; y1=y2; y2=t; }
538 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
539 if (tt) i_ppix(im,ttx,tty,&pv);
540 } else i_ppix(im,ttx,tty,&pv);
548 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
550 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
551 a rectangle the same size with it's top-left corner at (tx,ty) in the
554 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
560 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
561 int x, y, t, ttx, tty;
563 if (x2<x1) { t=x1; x1=x2; x2=t; }
564 if (y2<y1) { t=y1; y1=y2; y2=t; }
566 mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
567 im, src, x1, y1, x2, y2, tx, ty));
569 if (im->bits == i_8_bits) {
572 for(y=y1; y<y2; y++) {
574 for(x=x1; x<x2; x++) {
575 i_gpix(src, x, y, &pv);
576 i_ppix(im, ttx, tty, &pv);
585 for(y=y1; y<y2; y++) {
587 for(x=x1; x<x2; x++) {
588 i_gpixf(src, x, y, &pv);
589 i_ppixf(im, ttx, tty, &pv);
598 =item i_copy(im, src)
600 Copies the contents of the image I<src> over the image I<im>.
606 i_copy(i_img *im, i_img *src) {
609 mm_log((1,"i_copy(im* %p,src %p)\n", im, src));
613 if (src->type == i_direct_type) {
614 if (src->bits == i_8_bits) {
616 i_img_empty_ch(im, x1, y1, src->channels);
617 pv = mymalloc(sizeof(i_color) * x1);
619 for (y = 0; y < y1; ++y) {
620 i_glin(src, 0, x1, y, pv);
621 i_plin(im, 0, x1, y, pv);
627 if (src->bits == i_16_bits)
628 i_img_16_new_low(im, x1, y1, src->channels);
629 else if (src->bits == i_double_bits)
630 i_img_double_new_low(im, x1, y1, src->channels);
632 fprintf(stderr, "i_copy(): Unknown image bit size %d\n", src->bits);
633 return; /* I dunno */
636 pv = mymalloc(sizeof(i_fcolor) * x1);
637 for (y = 0; y < y1; ++y) {
638 i_glinf(src, 0, x1, y, pv);
639 i_plinf(im, 0, x1, y, pv);
651 i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
652 /* copy across the palette */
653 count = i_colorcount(src);
654 for (index = 0; index < count; ++index) {
655 i_getcolors(src, index, &temp, 1);
656 i_addcolors(im, &temp, 1);
659 vals = mymalloc(sizeof(i_palidx) * x1);
660 for (y = 0; y < y1; ++y) {
661 i_gpal(src, 0, x1, y, vals);
662 i_ppal(im, 0, x1, y, vals);
670 =item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy )
672 Takes the sub image I<src[src_minx, src_maxx)[src_miny, src_maxy)> and
673 overlays it at (I<tx>,I<ty>) on the image object.
675 The alpha channel of each pixel in I<src> is used to control how much
676 the existing colour in I<im> is replaced, if it is 255 then the colour
677 is completely replaced, if it is 0 then the original colour is left
684 i_rubthru(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny,
685 int src_maxx, int src_maxy) {
692 mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d, src_minx %d, "
693 "src_miny %d, src_maxx %d, src_maxy %d)\n",
694 im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy));
697 if (im->channels == 3 && src->channels == 4) {
699 chans[0] = 0; chans[1] = 1; chans[2] = 2;
702 else if (im->channels == 3 && src->channels == 2) {
704 chans[0] = chans[1] = chans[2] = 0;
707 else if (im->channels == 1 && src->channels == 2) {
713 i_push_error(0, "rubthru can only work where (dest, src) channels are (3,4), (3,2) or (1,2)");
718 /* if you change this code, please make sure the else branch is
719 changed in a similar fashion - TC */
721 i_color pv, orig, dest;
723 for(y = src_miny; y < src_maxy; y++) {
725 for(x = src_minx; x < src_maxx; x++) {
726 i_gpix(src, x, y, &pv);
727 i_gpix(im, ttx, tty, &orig);
728 alpha = pv.channel[alphachan];
729 for (ch = 0; ch < chancount; ++ch) {
730 dest.channel[ch] = (alpha * pv.channel[chans[ch]]
731 + (255 - alpha) * orig.channel[ch])/255;
733 i_ppix(im, ttx, tty, &dest);
741 i_fcolor pv, orig, dest;
744 for(y = src_miny; y < src_maxy; y++) {
746 for(x = src_minx; x < src_maxx; x++) {
747 i_gpixf(src, x, y, &pv);
748 i_gpixf(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 + (1 - alpha) * orig.channel[ch];
754 i_ppixf(im, ttx, tty, &dest);
766 =item i_flipxy(im, axis)
768 Flips the image inplace around the axis specified.
769 Returns 0 if parameters are invalid.
772 axis - 0 = x, 1 = y, 2 = both
778 i_flipxy(i_img *im, int direction) {
779 int x, x2, y, y2, xm, ym;
783 mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
788 case XAXIS: /* Horizontal flip */
791 for(y=0; y<ym; y++) {
793 for(x=0; x<xm; x++) {
795 i_gpix(im, x, y, &val1);
796 i_gpix(im, x2, y, &val2);
797 i_ppix(im, x, y, &val2);
798 i_ppix(im, x2, y, &val1);
803 case YAXIS: /* Vertical flip */
807 for(y=0; y<ym; y++) {
808 for(x=0; x<xm; x++) {
810 i_gpix(im, x, y, &val1);
811 i_gpix(im, x, y2, &val2);
812 i_ppix(im, x, y, &val2);
813 i_ppix(im, x, y2, &val1);
818 case XYAXIS: /* Horizontal and Vertical flip */
822 for(y=0; y<ym; y++) {
824 for(x=0; x<xm; x++) {
826 i_gpix(im, x, y, &val1);
827 i_gpix(im, x2, y2, &val2);
828 i_ppix(im, x, y, &val2);
829 i_ppix(im, x2, y2, &val1);
831 i_gpix(im, x2, y, &val1);
832 i_gpix(im, x, y2, &val2);
833 i_ppix(im, x2, y, &val2);
834 i_ppix(im, x, y2, &val1);
839 if (xm*2 != xs) { /* odd number of column */
840 mm_log((1, "i_flipxy: odd number of columns\n"));
843 for(y=0; y<ym; y++) {
845 i_gpix(im, x, y, &val1);
846 i_gpix(im, x, y2, &val2);
847 i_ppix(im, x, y, &val2);
848 i_ppix(im, x, y2, &val1);
852 if (ym*2 != ys) { /* odd number of rows */
853 mm_log((1, "i_flipxy: odd number of rows\n"));
856 for(x=0; x<xm; x++) {
858 i_gpix(im, x, y, &val1);
859 i_gpix(im, x2, y, &val2);
860 i_ppix(im, x, y, &val2);
861 i_ppix(im, x2, y, &val1);
867 mm_log((1, "i_flipxy: direction is invalid\n" ));
885 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
886 else if (x == 0.0) return (1.0);
887 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
892 =item i_scaleaxis(im, value, axis)
894 Returns a new image object which is I<im> scaled by I<value> along
895 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
901 i_scaleaxis(i_img *im, float Value, int Axis) {
902 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
903 int LanczosWidthFactor;
904 float *l0, *l1, OldLocation;
907 float F, PictureValue[MAXCHANNELS];
909 i_color val,val1,val2;
912 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
916 hsize = (int)(0.5 + im->xsize * Value);
919 Value = 1.0 / im->xsize;
927 vsize = (int)(0.5 + im->ysize * Value);
931 Value = 1.0 / im->ysize;
938 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
940 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
941 LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value);
942 lMax = LanczosWidthFactor << 1;
944 l0 = mymalloc(lMax * sizeof(float));
945 l1 = mymalloc(lMax * sizeof(float));
947 for (j=0; j<jEnd; j++) {
948 OldLocation = ((float) j) / Value;
949 T = (int) (OldLocation);
950 F = OldLocation - (float) T;
952 for (l = 0; l<lMax; l++) {
953 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
954 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
957 /* Make sure filter is normalized */
959 for(l=0; l<lMax; l++) {
963 t /= (float)LanczosWidthFactor;
965 for(l=0; l<lMax; l++) {
972 for (i=0; i<iEnd; i++) {
973 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
974 for (l=0; l<lMax; l++) {
977 mx = (mx < 0) ? 0 : mx;
978 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
980 i_gpix(im, Mx, i, &val1);
981 i_gpix(im, mx, i, &val2);
983 for (k=0; k<im->channels; k++) {
984 PictureValue[k] += l1[l] * val1.channel[k];
985 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
988 for(k=0;k<im->channels;k++) {
989 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
990 val.channel[k]=minmax(0,255,psave);
992 i_ppix(new_img, j, i, &val);
997 for (i=0; i<iEnd; i++) {
998 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
999 for (l=0; l < lMax; l++) {
1000 int mx = T-lMax+l+1;
1002 mx = (mx < 0) ? 0 : mx;
1003 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
1005 i_gpix(im, i, Mx, &val1);
1006 i_gpix(im, i, mx, &val2);
1007 for (k=0; k<im->channels; k++) {
1008 PictureValue[k] += l1[l] * val1.channel[k];
1009 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
1012 for (k=0; k<im->channels; k++) {
1013 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
1014 val.channel[k] = minmax(0, 255, psave);
1016 i_ppix(new_img, i, j, &val);
1024 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
1031 =item i_scale_nn(im, scx, scy)
1033 Scale by using nearest neighbor
1034 Both axes scaled at the same time since
1035 nothing is gained by doing it in two steps
1042 i_scale_nn(i_img *im, float scx, float scy) {
1044 int nxsize,nysize,nx,ny;
1048 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1050 nxsize = (int) ((float) im->xsize * scx);
1053 scx = 1 / im->xsize;
1055 nysize = (int) ((float) im->ysize * scy);
1058 scy = 1 / im->ysize;
1061 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1063 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1064 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1065 i_ppix(new_img,nx,ny,&val);
1068 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1074 =item i_sametype(i_img *im, int xsize, int ysize)
1076 Returns an image of the same type (sample size, channels, paletted/direct).
1078 For paletted images the palette is copied from the source.
1083 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1084 if (src->type == i_direct_type) {
1085 if (src->bits == 8) {
1086 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1088 else if (src->bits == i_16_bits) {
1089 return i_img_16_new(xsize, ysize, src->channels);
1091 else if (src->bits == i_double_bits) {
1092 return i_img_double_new(xsize, ysize, src->channels);
1095 i_push_error(0, "Unknown image bits");
1103 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1104 for (i = 0; i < i_colorcount(src); ++i) {
1105 i_getcolors(src, i, &col, 1);
1106 i_addcolors(targ, &col, 1);
1114 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
1116 Returns an image of the same type (sample size).
1118 For paletted images the equivalent direct type is returned.
1123 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1124 if (src->bits == 8) {
1125 return i_img_empty_ch(NULL, xsize, ysize, channels);
1127 else if (src->bits == i_16_bits) {
1128 return i_img_16_new(xsize, ysize, channels);
1130 else if (src->bits == i_double_bits) {
1131 return i_img_double_new(xsize, ysize, channels);
1134 i_push_error(0, "Unknown image bits");
1140 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1142 Spatially transforms I<im> returning a new image.
1144 opx for a length of opxl and opy for a length of opy are arrays of
1145 operators that modify the x and y positions to retreive the pixel data from.
1147 parm and parmlen define extra parameters that the operators may use.
1149 Note that this function is largely superseded by the more flexible
1150 L<transform.c/i_transform2>.
1152 Returns the new image.
1154 The operators for this function are defined in L<stackmach.c>.
1159 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1161 int nxsize,nysize,nx,ny;
1165 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));
1168 nysize = im->ysize ;
1170 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1171 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
1172 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1173 /* parm[parmlen-2]=(double)nx;
1174 parm[parmlen-1]=(double)ny; */
1179 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
1180 rx=i_op_run(opx,opxl,parm,parmlen);
1181 ry=i_op_run(opy,opyl,parm,parmlen);
1182 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
1183 i_gpix(im,rx,ry,&val);
1184 i_ppix(new_img,nx,ny,&val);
1187 mm_log((1,"(0x%x) <- i_transform\n",new_img));
1192 =item i_img_diff(im1, im2)
1194 Calculates the sum of the squares of the differences between
1195 correspoding channels in two images.
1197 If the images are not the same size then only the common area is
1198 compared, hence even if images are different sizes this function
1204 i_img_diff(i_img *im1,i_img *im2) {
1205 int x,y,ch,xb,yb,chb;
1209 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1211 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1212 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1213 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1215 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1218 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1219 i_gpix(im1,x,y,&val1);
1220 i_gpix(im2,x,y,&val2);
1222 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1224 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1228 /* just a tiny demo of haar wavelets */
1236 i_img *new_img,*new_img2;
1237 i_color val1,val2,dval1,dval2;
1245 /* horizontal pass */
1247 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1248 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1251 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1252 i_gpix(im,x*2,y,&val1);
1253 i_gpix(im,x*2+1,y,&val2);
1254 for(ch=0;ch<im->channels;ch++) {
1255 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1256 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1258 i_ppix(new_img,x,y,&dval1);
1259 i_ppix(new_img,x+fx,y,&dval2);
1262 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1263 i_gpix(new_img,x,y*2,&val1);
1264 i_gpix(new_img,x,y*2+1,&val2);
1265 for(ch=0;ch<im->channels;ch++) {
1266 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1267 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1269 i_ppix(new_img2,x,y,&dval1);
1270 i_ppix(new_img2,x,y+fy,&dval2);
1273 i_img_destroy(new_img);
1278 =item i_count_colors(im, maxc)
1280 returns number of colors or -1
1281 to indicate that it was more than max colors
1286 i_count_colors(i_img *im,int maxc) {
1293 mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
1300 for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
1301 i_gpix(im,x,y,&val);
1302 colorcnt+=octt_add(ct,val.rgb.r,val.rgb.g,val.rgb.b);
1303 if (colorcnt > maxc) { octt_delete(ct); return -1; }
1312 =head2 8-bit per sample image internal functions
1314 These are the functions installed in an 8-bit per sample image.
1318 =item i_ppix_d(im, x, y, col)
1322 This is the function kept in the i_f_ppix member of an i_img object.
1323 It does a normal store of a pixel into the image with range checking.
1325 Returns 0 if the pixel could be set, -1 otherwise.
1331 i_ppix_d(i_img *im, int x, int y, i_color *val) {
1334 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1335 for(ch=0;ch<im->channels;ch++)
1336 if (im->ch_mask&(1<<ch))
1337 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1340 return -1; /* error was clipped */
1344 =item i_gpix_d(im, x, y, &col)
1348 This is the function kept in the i_f_gpix member of an i_img object.
1349 It does normal retrieval of a pixel from the image with range checking.
1351 Returns 0 if the pixel could be set, -1 otherwise.
1357 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1359 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1360 for(ch=0;ch<im->channels;ch++)
1361 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1364 for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1365 return -1; /* error was cliped */
1369 =item i_glin_d(im, l, r, y, vals)
1371 Reads a line of data from the image, storing the pixels at vals.
1373 The line runs from (l,y) inclusive to (r,y) non-inclusive
1375 vals should point at space for (r-l) pixels.
1377 l should never be less than zero (to avoid confusion about where to
1378 put the pixels in vals).
1380 Returns the number of pixels copied (eg. if r, l or y is out of range)
1386 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1388 unsigned char *data;
1389 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1392 data = im->idata + (l+y*im->xsize) * im->channels;
1394 for (i = 0; i < count; ++i) {
1395 for (ch = 0; ch < im->channels; ++ch)
1396 vals[i].channel[ch] = *data++;
1406 =item i_plin_d(im, l, r, y, vals)
1408 Writes a line of data into the image, using the pixels at vals.
1410 The line runs from (l,y) inclusive to (r,y) non-inclusive
1412 vals should point at (r-l) pixels.
1414 l should never be less than zero (to avoid confusion about where to
1415 get the pixels in vals).
1417 Returns the number of pixels copied (eg. if r, l or y is out of range)
1423 i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
1425 unsigned char *data;
1426 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1429 data = im->idata + (l+y*im->xsize) * im->channels;
1431 for (i = 0; i < count; ++i) {
1432 for (ch = 0; ch < im->channels; ++ch) {
1433 if (im->ch_mask & (1 << ch))
1434 *data = vals[i].channel[ch];
1446 =item i_ppixf_d(im, x, y, val)
1452 i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
1455 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1456 for(ch=0;ch<im->channels;ch++)
1457 if (im->ch_mask&(1<<ch)) {
1458 im->idata[(x+y*im->xsize)*im->channels+ch] =
1459 SampleFTo8(val->channel[ch]);
1463 return -1; /* error was clipped */
1467 =item i_gpixf_d(im, x, y, val)
1473 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1475 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1476 for(ch=0;ch<im->channels;ch++) {
1478 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1482 return -1; /* error was cliped */
1486 =item i_glinf_d(im, l, r, y, vals)
1488 Reads a line of data from the image, storing the pixels at vals.
1490 The line runs from (l,y) inclusive to (r,y) non-inclusive
1492 vals should point at space for (r-l) pixels.
1494 l should never be less than zero (to avoid confusion about where to
1495 put the pixels in vals).
1497 Returns the number of pixels copied (eg. if r, l or y is out of range)
1503 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1505 unsigned char *data;
1506 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1509 data = im->idata + (l+y*im->xsize) * im->channels;
1511 for (i = 0; i < count; ++i) {
1512 for (ch = 0; ch < im->channels; ++ch)
1513 vals[i].channel[ch] = Sample8ToF(*data++);
1523 =item i_plinf_d(im, l, r, y, vals)
1525 Writes a line of data into the image, using the pixels at vals.
1527 The line runs from (l,y) inclusive to (r,y) non-inclusive
1529 vals should point at (r-l) pixels.
1531 l should never be less than zero (to avoid confusion about where to
1532 get the pixels in vals).
1534 Returns the number of pixels copied (eg. if r, l or y is out of range)
1540 i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1542 unsigned char *data;
1543 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1546 data = im->idata + (l+y*im->xsize) * im->channels;
1548 for (i = 0; i < count; ++i) {
1549 for (ch = 0; ch < im->channels; ++ch) {
1550 if (im->ch_mask & (1 << ch))
1551 *data = SampleFTo8(vals[i].channel[ch]);
1563 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1565 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1566 for the channels specified by chans, an array of int with chan_count
1569 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1575 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
1576 const int *chans, int chan_count) {
1577 int ch, count, i, w;
1578 unsigned char *data;
1580 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1583 data = im->idata + (l+y*im->xsize) * im->channels;
1588 /* make sure we have good channel numbers */
1589 for (ch = 0; ch < chan_count; ++ch) {
1590 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1591 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1595 for (i = 0; i < w; ++i) {
1596 for (ch = 0; ch < chan_count; ++ch) {
1597 *samps++ = data[chans[ch]];
1600 data += im->channels;
1604 for (i = 0; i < w; ++i) {
1605 for (ch = 0; ch < chan_count; ++ch) {
1606 *samps++ = data[ch];
1609 data += im->channels;
1621 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1623 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1624 for the channels specified by chan_mask, where bit 0 is the first
1627 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1633 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
1634 const int *chans, int chan_count) {
1635 int ch, count, i, w;
1636 unsigned char *data;
1637 for (ch = 0; ch < chan_count; ++ch) {
1638 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1639 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1642 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1645 data = im->idata + (l+y*im->xsize) * im->channels;
1650 /* make sure we have good channel numbers */
1651 for (ch = 0; ch < chan_count; ++ch) {
1652 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1653 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1657 for (i = 0; i < w; ++i) {
1658 for (ch = 0; ch < chan_count; ++ch) {
1659 *samps++ = Sample8ToF(data[chans[ch]]);
1662 data += im->channels;
1666 for (i = 0; i < w; ++i) {
1667 for (ch = 0; ch < chan_count; ++ch) {
1668 *samps++ = Sample8ToF(data[ch]);
1671 data += im->channels;
1684 =head2 Image method wrappers
1686 These functions provide i_fsample_t functions in terms of their
1687 i_sample_t versions.
1691 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1696 int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1700 for (ch = 0; ch < im->channels; ++ch)
1701 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1703 return i_ppix(im, x, y, &temp);
1707 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1711 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1715 if (i_gpix(im, x, y, &temp)) {
1716 for (ch = 0; ch < im->channels; ++ch)
1717 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1725 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1729 int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1732 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1738 work = mymalloc(sizeof(i_color) * (r-l));
1739 for (i = 0; i < r-l; ++i) {
1740 for (ch = 0; ch < im->channels; ++ch)
1741 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1743 ret = i_plin(im, l, r, y, work);
1758 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1762 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1765 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1771 work = mymalloc(sizeof(i_color) * (r-l));
1772 ret = i_plin(im, l, r, y, work);
1773 for (i = 0; i < r-l; ++i) {
1774 for (ch = 0; ch < im->channels; ++ch)
1775 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1791 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1795 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
1796 int const *chans, int chan_count) {
1799 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1805 work = mymalloc(sizeof(i_sample_t) * (r-l));
1806 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1807 for (i = 0; i < ret; ++i) {
1808 samp[i] = Sample8ToF(work[i]);
1826 =head2 Palette wrapper functions
1828 Used for virtual images, these forward palette calls to a wrapped image,
1829 assuming the wrapped image is the first pointer in the structure that
1830 im->ext_data points at.
1834 =item i_addcolors_forward(i_img *im, i_color *colors, int count)
1838 int i_addcolors_forward(i_img *im, i_color *colors, int count) {
1839 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1843 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1847 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1848 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1852 =item i_setcolors_forward(i_img *im, int i, i_color *color, int count)
1856 int i_setcolors_forward(i_img *im, int i, i_color *color, int count) {
1857 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1861 =item i_colorcount_forward(i_img *im)
1865 int i_colorcount_forward(i_img *im) {
1866 return i_colorcount(*(i_img **)im->ext_data);
1870 =item i_maxcolors_forward(i_img *im)
1874 int i_maxcolors_forward(i_img *im) {
1875 return i_maxcolors(*(i_img **)im->ext_data);
1879 =item i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry)
1883 int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry) {
1884 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1890 =head2 Stream reading and writing wrapper functions
1894 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1896 Performs general read buffering for file readers that permit reading
1897 to be done through a callback.
1899 The final callback gets two parameters, a I<need> value, and a I<want>
1900 value, where I<need> is the amount of data that the file library needs
1901 to read, and I<want> is the amount of space available in the buffer
1902 maintained by these functions.
1904 This means if you need to read from a stream that you don't know the
1905 length of, you can return I<need> bytes, taking the performance hit of
1906 possibly expensive callbacks (eg. back to perl code), or if you are
1907 reading from a stream where it doesn't matter if some data is lost, or
1908 if the total length of the stream is known, you can return I<want>
1915 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1918 if (length < gci->length - gci->cpos) {
1920 memcpy(buf, gci->buffer+gci->cpos, length);
1921 gci->cpos += length;
1926 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
1927 total += gci->length - gci->cpos;
1928 length -= gci->length - gci->cpos;
1929 buf += gci->length - gci->cpos;
1930 if (length < (int)sizeof(gci->buffer)) {
1934 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
1935 sizeof(gci->buffer))) > 0) {
1937 gci->length = did_read;
1939 copy_size = i_min(length, gci->length);
1940 memcpy(buf, gci->buffer, copy_size);
1941 gci->cpos += copy_size;
1944 length -= copy_size;
1948 /* just read the rest - too big for our buffer*/
1950 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1960 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1962 For use by callback file readers to initialize the reader buffer.
1964 Allocates, initializes and returns the reader buffer.
1966 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1971 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1972 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1974 self->userdata = userdata;
1982 =item i_free_gen_read_data(i_gen_read_data *)
1988 void i_free_gen_read_data(i_gen_read_data *self) {
1993 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1995 Performs write buffering for a callback based file writer.
1997 Failures are considered fatal, if a write fails then data will be
2004 i_gen_write_data *self,
2008 if (self->filledto && self->filledto+size > self->maxlength) {
2009 if (self->cb(self->userdata, self->buffer, self->filledto)) {
2017 if (self->filledto+size <= self->maxlength) {
2019 memcpy(self->buffer+self->filledto, data, size);
2020 self->filledto += size;
2023 /* doesn't fit - hand it off */
2024 return self->cb(self->userdata, data, size);
2028 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2030 Allocates and initializes the data structure used by i_gen_writer.
2032 This should be released with L<image.c/i_free_gen_write_data>
2036 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
2037 char *userdata, int max_length)
2039 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2041 self->userdata = userdata;
2042 self->maxlength = i_min(max_length, sizeof(self->buffer));
2043 if (self->maxlength < 0)
2044 self->maxlength = sizeof(self->buffer);
2051 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2053 Cleans up the write buffer.
2055 Will flush any left-over data if I<flush> is non-zero.
2057 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2059 Return zero only if flush is non-zero and info->cb() returns zero.
2065 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2067 int result = !flush ||
2068 info->filledto == 0 ||
2069 info->cb(info->userdata, info->buffer, info->filledto);
2078 =item i_test_format_probe(io_glue *data, int length)
2080 Check the beginning of the supplied file for a 'magic number'
2087 i_test_format_probe(io_glue *data, int length) {
2093 {"\xFF\xD8", "jpeg"},
2099 {"\x89PNG\x0d\x0a\x1a\x0a", "png"},
2112 io_glue_commit_types(data);
2113 rc = data->readcb(data, head, 18);
2114 if (rc == -1) return NULL;
2115 data->seekcb(data, -rc, SEEK_CUR);
2117 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
2119 ssize_t len = strlen(formats[i].magic);
2120 if (rc<len) continue;
2121 c = !strncmp(formats[i].magic, head, len);
2123 match = formats[i].name;
2129 if (match && !strcmp(match, "jpeg")) {
2130 unsigned int x0, x1;
2131 rc = data->readcb(data, head, 18);
2132 if (rc == -1) return NULL;
2133 x0 = (unsigned char)head[0];
2134 x1 = (unsigned char)head[1];
2135 data->seekcb(data, -rc, SEEK_CUR);
2136 printf("Jpeg reread: %x %x\n", x0, x1);
2142 tga_header_verify(head)) return "tga";
2154 Arnar M. Hrafnkelsson <addi@umich.edu>
2156 Tony Cook <tony@develop-help.com>