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 static 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, const int *chans, int chan_count);
52 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
53 /*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
54 static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
57 =item ICL_new_internal(r, g, b, a)
59 Return a new color object with values passed to it.
61 r - red component (range: 0 - 255)
62 g - green component (range: 0 - 255)
63 b - blue component (range: 0 - 255)
64 a - alpha component (range: 0 - 255)
70 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
73 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
75 if ( (cl=mymalloc(sizeof(i_color))) == NULL) m_fatal(2,"malloc() error\n");
80 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
86 =item ICL_set_internal(cl, r, g, b, a)
88 Overwrite a color with new values.
90 cl - pointer to color object
91 r - red component (range: 0 - 255)
92 g - green component (range: 0 - 255)
93 b - blue component (range: 0 - 255)
94 a - alpha component (range: 0 - 255)
100 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
101 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
103 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
104 m_fatal(2,"malloc() error\n");
109 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
115 =item ICL_add(dst, src, ch)
117 Add src to dst inplace - dst is modified.
119 dst - pointer to destination color object
120 src - pointer to color object that is added
121 ch - number of channels
127 ICL_add(i_color *dst,i_color *src,int ch) {
130 tmp=dst->channel[i]+src->channel[i];
131 dst->channel[i]= tmp>255 ? 255:tmp;
138 Dump color information to log - strictly for debugging.
140 cl - pointer to color object
146 ICL_info(i_color *cl) {
147 mm_log((1,"i_color_info(cl* %p)\n",cl));
148 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
154 Destroy ancillary data for Color object.
156 cl - pointer to color object
162 ICL_DESTROY(i_color *cl) {
163 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
168 =item i_fcolor_new(double r, double g, double b, double a)
172 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
175 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
177 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) m_fatal(2,"malloc() error\n");
182 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
188 =item i_fcolor_destroy(i_fcolor *cl)
192 void i_fcolor_destroy(i_fcolor *cl) {
197 =item IIM_base_8bit_direct (static)
199 A static i_img object used to initialize direct 8-bit per sample images.
203 static i_img IIM_base_8bit_direct =
205 0, /* channels set */
206 0, 0, 0, /* xsize, ysize, bytes */
209 i_direct_type, /* type */
212 { 0, 0, NULL }, /* tags */
215 i_ppix_d, /* i_f_ppix */
216 i_ppixf_d, /* i_f_ppixf */
217 i_plin_d, /* i_f_plin */
218 i_plinf_d, /* i_f_plinf */
219 i_gpix_d, /* i_f_gpix */
220 i_gpixf_d, /* i_f_gpixf */
221 i_glin_d, /* i_f_glin */
222 i_glinf_d, /* i_f_glinf */
223 i_gsamp_d, /* i_f_gsamp */
224 i_gsampf_d, /* i_f_gsampf */
228 NULL, /* i_f_addcolors */
229 NULL, /* i_f_getcolors */
230 NULL, /* i_f_colorcount */
231 NULL, /* i_f_maxcolors */
232 NULL, /* i_f_findcolor */
233 NULL, /* i_f_setcolors */
235 NULL, /* i_f_destroy */
238 /*static void set_8bit_direct(i_img *im) {
239 im->i_f_ppix = i_ppix_d;
240 im->i_f_ppixf = i_ppixf_d;
241 im->i_f_plin = i_plin_d;
242 im->i_f_plinf = i_plinf_d;
243 im->i_f_gpix = i_gpix_d;
244 im->i_f_gpixf = i_gpixf_d;
245 im->i_f_glin = i_glin_d;
246 im->i_f_glinf = i_glinf_d;
249 im->i_f_addcolor = NULL;
250 im->i_f_getcolor = NULL;
251 im->i_f_colorcount = NULL;
252 im->i_f_findcolor = NULL;
256 =item IIM_new(x, y, ch)
258 Creates a new image object I<x> pixels wide, and I<y> pixels high with I<ch> channels.
265 IIM_new(int x,int y,int ch) {
267 mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
269 im=i_img_empty_ch(NULL,x,y,ch);
271 mm_log((1,"(%p) <- IIM_new\n",im));
277 IIM_DESTROY(i_img *im) {
278 mm_log((1,"IIM_DESTROY(im* %p)\n",im));
288 Create new image reference - notice that this isn't an object yet and
289 this should be fixed asap.
299 mm_log((1,"i_img_struct()\n"));
300 if ( (im=mymalloc(sizeof(i_img))) == NULL)
301 m_fatal(2,"malloc() error\n");
303 *im = IIM_base_8bit_direct;
311 mm_log((1,"(%p) <- i_img_struct\n",im));
316 =item i_img_empty(im, x, y)
318 Re-new image reference (assumes 3 channels)
321 x - xsize of destination image
322 y - ysize of destination image
324 **FIXME** what happens if a live image is passed in here?
326 Should this just call i_img_empty_ch()?
332 i_img_empty(i_img *im,int x,int y) {
333 mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
334 return i_img_empty_ch(im, x, y, 3);
338 =item i_img_empty_ch(im, x, y, ch)
340 Re-new image reference
343 x - xsize of destination image
344 y - ysize of destination image
345 ch - number of channels
351 i_img_empty_ch(i_img *im,int x,int y,int ch) {
352 mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
354 if (x < 1 || y < 1) {
355 i_push_error(0, "Image sizes must be positive");
358 if (ch < 1 || ch > MAXCHANNELS) {
359 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
364 if ( (im=mymalloc(sizeof(i_img))) == NULL)
365 m_fatal(2,"malloc() error\n");
367 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
368 i_tags_new(&im->tags);
372 im->ch_mask = MAXINT;
373 im->bytes=x*y*im->channels;
374 if ( (im->idata=mymalloc(im->bytes)) == NULL) m_fatal(2,"malloc() error\n");
375 memset(im->idata,0,(size_t)im->bytes);
379 mm_log((1,"(%p) <- i_img_empty_ch\n",im));
384 =item i_img_exorcise(im)
394 i_img_exorcise(i_img *im) {
395 mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
396 i_tags_destroy(&im->tags);
398 (im->i_f_destroy)(im);
399 if (im->idata != NULL) { myfree(im->idata); }
405 im->i_f_ppix=i_ppix_d;
406 im->i_f_gpix=i_gpix_d;
407 im->i_f_plin=i_plin_d;
408 im->i_f_glin=i_glin_d;
413 =item i_img_destroy(im)
415 Destroy image and free data via exorcise.
423 i_img_destroy(i_img *im) {
424 mm_log((1,"i_img_destroy(im %p)\n",im));
426 if (im) { myfree(im); }
430 =item i_img_info(im, info)
432 Return image information
435 info - pointer to array to return data
437 info is an array of 4 integers with the following values:
442 info[3] - channel mask
449 i_img_info(i_img *im,int *info) {
450 mm_log((1,"i_img_info(im 0x%x)\n",im));
452 mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
453 mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
456 info[2] = im->channels;
457 info[3] = im->ch_mask;
467 =item i_img_setmask(im, ch_mask)
469 Set the image channel mask for I<im> to I<ch_mask>.
474 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
478 =item i_img_getmask(im)
480 Get the image channel mask for I<im>.
485 i_img_getmask(i_img *im) { return im->ch_mask; }
488 =item i_img_getchannels(im)
490 Get the number of channels in I<im>.
495 i_img_getchannels(i_img *im) { return im->channels; }
500 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
502 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
503 (tx,ty) specifies the upper left corner for the target image.
504 pass NULL in trans for non transparent i_colors.
510 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans) {
512 int x,y,t,ttx,tty,tt,ch;
514 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",
515 im, src, x1, y1, x2, y2, tx, ty, trans));
517 if (x2<x1) { t=x1; x1=x2; x2=t; }
518 if (y2<y1) { t=y1; y1=y2; y2=t; }
530 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
531 if (tt) i_ppix(im,ttx,tty,&pv);
532 } else i_ppix(im,ttx,tty,&pv);
540 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
542 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
543 a rectangle the same size with it's top-left corner at (tx,ty) in the
546 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
552 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
553 int x, y, t, ttx, tty;
555 if (x2<x1) { t=x1; x1=x2; x2=t; }
556 if (y2<y1) { t=y1; y1=y2; y2=t; }
558 mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
559 im, src, x1, y1, x2, y2, tx, ty));
561 if (im->bits == i_8_bits) {
564 for(y=y1; y<y2; y++) {
566 for(x=x1; x<x2; x++) {
567 i_gpix(src, x, y, &pv);
568 i_ppix(im, ttx, tty, &pv);
577 for(y=y1; y<y2; y++) {
579 for(x=x1; x<x2; x++) {
580 i_gpixf(src, x, y, &pv);
581 i_ppixf(im, ttx, tty, &pv);
590 =item i_copy(im, src)
592 Copies the contents of the image I<src> over the image I<im>.
598 i_copy(i_img *im, i_img *src) {
601 mm_log((1,"i_copy(im* %p,src %p)\n", im, src));
605 if (src->type == i_direct_type) {
606 if (src->bits == i_8_bits) {
608 i_img_empty_ch(im, x1, y1, src->channels);
609 pv = mymalloc(sizeof(i_color) * x1);
611 for (y = 0; y < y1; ++y) {
612 i_glin(src, 0, x1, y, pv);
613 i_plin(im, 0, x1, y, pv);
619 if (src->bits == i_16_bits)
620 i_img_16_new_low(im, x1, y1, src->channels);
621 else if (src->bits == i_double_bits)
622 i_img_double_new_low(im, x1, y1, src->channels);
624 fprintf(stderr, "i_copy(): Unknown image bit size %d\n", src->bits);
625 return; /* I dunno */
628 pv = mymalloc(sizeof(i_fcolor) * x1);
629 for (y = 0; y < y1; ++y) {
630 i_glinf(src, 0, x1, y, pv);
631 i_plinf(im, 0, x1, y, pv);
643 i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
644 /* copy across the palette */
645 count = i_colorcount(src);
646 for (index = 0; index < count; ++index) {
647 i_getcolors(src, index, &temp, 1);
648 i_addcolors(im, &temp, 1);
651 vals = mymalloc(sizeof(i_palidx) * x1);
652 for (y = 0; y < y1; ++y) {
653 i_gpal(src, 0, x1, y, vals);
654 i_ppal(im, 0, x1, y, vals);
662 =item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy )
664 Takes the sub image I<src[src_minx, src_maxx)[src_miny, src_maxy)> and
665 overlays it at (I<tx>,I<ty>) on the image object.
667 The alpha channel of each pixel in I<src> is used to control how much
668 the existing colour in I<im> is replaced, if it is 255 then the colour
669 is completely replaced, if it is 0 then the original colour is left
676 i_rubthru(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny,
677 int src_maxx, int src_maxy) {
684 mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d, src_minx %d, "
685 "src_miny %d, src_maxx %d, src_maxy %d)\n",
686 im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy));
689 if (im->channels == 3 && src->channels == 4) {
691 chans[0] = 0; chans[1] = 1; chans[2] = 2;
694 else if (im->channels == 3 && src->channels == 2) {
696 chans[0] = chans[1] = chans[2] = 0;
699 else if (im->channels == 1 && src->channels == 2) {
705 i_push_error(0, "rubthru can only work where (dest, src) channels are (3,4), (3,2) or (1,2)");
710 /* if you change this code, please make sure the else branch is
711 changed in a similar fashion - TC */
713 i_color pv, orig, dest;
715 for(y = src_miny; y < src_maxy; y++) {
717 for(x = src_minx; x < src_maxx; x++) {
718 i_gpix(src, x, y, &pv);
719 i_gpix(im, ttx, tty, &orig);
720 alpha = pv.channel[alphachan];
721 for (ch = 0; ch < chancount; ++ch) {
722 dest.channel[ch] = (alpha * pv.channel[chans[ch]]
723 + (255 - alpha) * orig.channel[ch])/255;
725 i_ppix(im, ttx, tty, &dest);
733 i_fcolor pv, orig, dest;
736 for(y = src_miny; y < src_maxy; y++) {
738 for(x = src_minx; x < src_maxx; x++) {
739 i_gpixf(src, x, y, &pv);
740 i_gpixf(im, ttx, tty, &orig);
741 alpha = pv.channel[alphachan];
742 for (ch = 0; ch < chancount; ++ch) {
743 dest.channel[ch] = alpha * pv.channel[chans[ch]]
744 + (1 - alpha) * orig.channel[ch];
746 i_ppixf(im, ttx, tty, &dest);
758 =item i_flipxy(im, axis)
760 Flips the image inplace around the axis specified.
761 Returns 0 if parameters are invalid.
764 axis - 0 = x, 1 = y, 2 = both
770 i_flipxy(i_img *im, int direction) {
771 int x, x2, y, y2, xm, ym;
775 mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
780 case XAXIS: /* Horizontal flip */
783 for(y=0; y<ym; y++) {
785 for(x=0; x<xm; x++) {
787 i_gpix(im, x, y, &val1);
788 i_gpix(im, x2, y, &val2);
789 i_ppix(im, x, y, &val2);
790 i_ppix(im, x2, y, &val1);
795 case YAXIS: /* Vertical flip */
799 for(y=0; y<ym; y++) {
800 for(x=0; x<xm; x++) {
802 i_gpix(im, x, y, &val1);
803 i_gpix(im, x, y2, &val2);
804 i_ppix(im, x, y, &val2);
805 i_ppix(im, x, y2, &val1);
810 case XYAXIS: /* Horizontal and Vertical flip */
814 for(y=0; y<ym; y++) {
816 for(x=0; x<xm; x++) {
818 i_gpix(im, x, y, &val1);
819 i_gpix(im, x2, y2, &val2);
820 i_ppix(im, x, y, &val2);
821 i_ppix(im, x2, y2, &val1);
823 i_gpix(im, x2, y, &val1);
824 i_gpix(im, x, y2, &val2);
825 i_ppix(im, x2, y, &val2);
826 i_ppix(im, x, y2, &val1);
831 if (xm*2 != xs) { /* odd number of column */
832 mm_log((1, "i_flipxy: odd number of columns\n"));
835 for(y=0; y<ym; y++) {
837 i_gpix(im, x, y, &val1);
838 i_gpix(im, x, y2, &val2);
839 i_ppix(im, x, y, &val2);
840 i_ppix(im, x, y2, &val1);
844 if (ym*2 != ys) { /* odd number of rows */
845 mm_log((1, "i_flipxy: odd number of rows\n"));
848 for(x=0; x<xm; x++) {
850 i_gpix(im, x, y, &val1);
851 i_gpix(im, x2, y, &val2);
852 i_ppix(im, x, y, &val2);
853 i_ppix(im, x2, y, &val1);
859 mm_log((1, "i_flipxy: direction is invalid\n" ));
877 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
878 else if (x == 0.0) return (1.0);
879 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
884 =item i_scaleaxis(im, value, axis)
886 Returns a new image object which is I<im> scaled by I<value> along
887 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
893 i_scaleaxis(i_img *im, float Value, int Axis) {
894 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
895 int LanczosWidthFactor;
896 float *l0, *l1, OldLocation;
899 float F, PictureValue[MAXCHANNELS];
901 i_color val,val1,val2;
904 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
908 hsize = (int)(0.5 + im->xsize * Value);
911 Value = 1 / im->xsize;
919 vsize = (int)(0.5 + im->ysize * Value);
923 Value = 1 / im->ysize;
930 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
932 /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
933 LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value);
934 lMax = LanczosWidthFactor << 1;
936 l0 = mymalloc(lMax * sizeof(float));
937 l1 = mymalloc(lMax * sizeof(float));
939 for (j=0; j<jEnd; j++) {
940 OldLocation = ((float) j) / Value;
941 T = (int) (OldLocation);
942 F = OldLocation - (float) T;
944 for (l = 0; l<lMax; l++) {
945 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
946 l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
949 /* Make sure filter is normalized */
951 for(l=0; l<lMax; l++) {
955 t /= (float)LanczosWidthFactor;
957 for(l=0; l<lMax; l++) {
964 for (i=0; i<iEnd; i++) {
965 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
966 for (l=0; l<lMax; l++) {
969 mx = (mx < 0) ? 0 : mx;
970 Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
972 i_gpix(im, Mx, i, &val1);
973 i_gpix(im, mx, i, &val2);
975 for (k=0; k<im->channels; k++) {
976 PictureValue[k] += l1[l] * val1.channel[k];
977 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
980 for(k=0;k<im->channels;k++) {
981 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
982 val.channel[k]=minmax(0,255,psave);
984 i_ppix(new_img, j, i, &val);
989 for (i=0; i<iEnd; i++) {
990 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
991 for (l=0; l < lMax; l++) {
994 mx = (mx < 0) ? 0 : mx;
995 Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
997 i_gpix(im, i, Mx, &val1);
998 i_gpix(im, i, mx, &val2);
999 for (k=0; k<im->channels; k++) {
1000 PictureValue[k] += l1[l] * val1.channel[k];
1001 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
1004 for (k=0; k<im->channels; k++) {
1005 psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
1006 val.channel[k] = minmax(0, 255, psave);
1008 i_ppix(new_img, i, j, &val);
1016 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
1023 =item i_scale_nn(im, scx, scy)
1025 Scale by using nearest neighbor
1026 Both axes scaled at the same time since
1027 nothing is gained by doing it in two steps
1034 i_scale_nn(i_img *im, float scx, float scy) {
1036 int nxsize,nysize,nx,ny;
1040 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1042 nxsize = (int) ((float) im->xsize * scx);
1045 scx = 1 / im->xsize;
1047 nysize = (int) ((float) im->ysize * scy);
1050 scy = 1 / im->ysize;
1053 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1055 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1056 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1057 i_ppix(new_img,nx,ny,&val);
1060 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1066 =item i_sametype(i_img *im, int xsize, int ysize)
1068 Returns an image of the same type (sample size, channels, paletted/direct).
1070 For paletted images the palette is copied from the source.
1075 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1076 if (src->type == i_direct_type) {
1077 if (src->bits == 8) {
1078 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1080 else if (src->bits == i_16_bits) {
1081 return i_img_16_new(xsize, ysize, src->channels);
1083 else if (src->bits == i_double_bits) {
1084 return i_img_double_new(xsize, ysize, src->channels);
1087 i_push_error(0, "Unknown image bits");
1095 i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1096 for (i = 0; i < i_colorcount(src); ++i) {
1097 i_getcolors(src, i, &col, 1);
1098 i_addcolors(targ, &col, 1);
1106 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
1108 Returns an image of the same type (sample size).
1110 For paletted images the equivalent direct type is returned.
1115 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1116 if (src->bits == 8) {
1117 return i_img_empty_ch(NULL, xsize, ysize, channels);
1119 else if (src->bits == i_16_bits) {
1120 return i_img_16_new(xsize, ysize, channels);
1122 else if (src->bits == i_double_bits) {
1123 return i_img_double_new(xsize, ysize, channels);
1126 i_push_error(0, "Unknown image bits");
1132 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1134 Spatially transforms I<im> returning a new image.
1136 opx for a length of opxl and opy for a length of opy are arrays of
1137 operators that modify the x and y positions to retreive the pixel data from.
1139 parm and parmlen define extra parameters that the operators may use.
1141 Note that this function is largely superseded by the more flexible
1142 L<transform.c/i_transform2>.
1144 Returns the new image.
1146 The operators for this function are defined in L<stackmach.c>.
1151 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1153 int nxsize,nysize,nx,ny;
1157 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));
1160 nysize = im->ysize ;
1162 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1163 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
1164 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1165 /* parm[parmlen-2]=(double)nx;
1166 parm[parmlen-1]=(double)ny; */
1171 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
1172 rx=i_op_run(opx,opxl,parm,parmlen);
1173 ry=i_op_run(opy,opyl,parm,parmlen);
1174 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
1175 i_gpix(im,rx,ry,&val);
1176 i_ppix(new_img,nx,ny,&val);
1179 mm_log((1,"(0x%x) <- i_transform\n",new_img));
1184 =item i_img_diff(im1, im2)
1186 Calculates the sum of the squares of the differences between
1187 correspoding channels in two images.
1189 If the images are not the same size then only the common area is
1190 compared, hence even if images are different sizes this function
1196 i_img_diff(i_img *im1,i_img *im2) {
1197 int x,y,ch,xb,yb,chb;
1201 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1203 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1204 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1205 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1207 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1210 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1211 i_gpix(im1,x,y,&val1);
1212 i_gpix(im2,x,y,&val2);
1214 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1216 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1220 /* just a tiny demo of haar wavelets */
1228 i_img *new_img,*new_img2;
1229 i_color val1,val2,dval1,dval2;
1237 /* horizontal pass */
1239 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1240 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1243 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1244 i_gpix(im,x*2,y,&val1);
1245 i_gpix(im,x*2+1,y,&val2);
1246 for(ch=0;ch<im->channels;ch++) {
1247 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1248 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1250 i_ppix(new_img,x,y,&dval1);
1251 i_ppix(new_img,x+fx,y,&dval2);
1254 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1255 i_gpix(new_img,x,y*2,&val1);
1256 i_gpix(new_img,x,y*2+1,&val2);
1257 for(ch=0;ch<im->channels;ch++) {
1258 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1259 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1261 i_ppix(new_img2,x,y,&dval1);
1262 i_ppix(new_img2,x,y+fy,&dval2);
1265 i_img_destroy(new_img);
1270 =item i_count_colors(im, maxc)
1272 returns number of colors or -1
1273 to indicate that it was more than max colors
1278 i_count_colors(i_img *im,int maxc) {
1285 mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
1292 for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
1293 i_gpix(im,x,y,&val);
1294 colorcnt+=octt_add(ct,val.rgb.r,val.rgb.g,val.rgb.b);
1295 if (colorcnt > maxc) { octt_delete(ct); return -1; }
1304 =head2 8-bit per sample image internal functions
1306 These are the functions installed in an 8-bit per sample image.
1310 =item i_ppix_d(im, x, y, col)
1314 This is the function kept in the i_f_ppix member of an i_img object.
1315 It does a normal store of a pixel into the image with range checking.
1317 Returns 0 if the pixel could be set, -1 otherwise.
1323 i_ppix_d(i_img *im, int x, int y, i_color *val) {
1326 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1327 for(ch=0;ch<im->channels;ch++)
1328 if (im->ch_mask&(1<<ch))
1329 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1332 return -1; /* error was clipped */
1336 =item i_gpix_d(im, x, y, &col)
1340 This is the function kept in the i_f_gpix member of an i_img object.
1341 It does normal retrieval of a pixel from the image with range checking.
1343 Returns 0 if the pixel could be set, -1 otherwise.
1349 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1351 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1352 for(ch=0;ch<im->channels;ch++)
1353 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1356 for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1357 return -1; /* error was cliped */
1361 =item i_glin_d(im, l, r, y, vals)
1363 Reads a line of data from the image, storing the pixels at vals.
1365 The line runs from (l,y) inclusive to (r,y) non-inclusive
1367 vals should point at space for (r-l) pixels.
1369 l should never be less than zero (to avoid confusion about where to
1370 put the pixels in vals).
1372 Returns the number of pixels copied (eg. if r, l or y is out of range)
1378 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1380 unsigned char *data;
1381 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1384 data = im->idata + (l+y*im->xsize) * im->channels;
1386 for (i = 0; i < count; ++i) {
1387 for (ch = 0; ch < im->channels; ++ch)
1388 vals[i].channel[ch] = *data++;
1398 =item i_plin_d(im, l, r, y, vals)
1400 Writes a line of data into the image, using the pixels at vals.
1402 The line runs from (l,y) inclusive to (r,y) non-inclusive
1404 vals should point at (r-l) pixels.
1406 l should never be less than zero (to avoid confusion about where to
1407 get the pixels in vals).
1409 Returns the number of pixels copied (eg. if r, l or y is out of range)
1415 i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
1417 unsigned char *data;
1418 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1421 data = im->idata + (l+y*im->xsize) * im->channels;
1423 for (i = 0; i < count; ++i) {
1424 for (ch = 0; ch < im->channels; ++ch) {
1425 if (im->ch_mask & (1 << ch))
1426 *data = vals[i].channel[ch];
1438 =item i_ppixf_d(im, x, y, val)
1444 i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
1447 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1448 for(ch=0;ch<im->channels;ch++)
1449 if (im->ch_mask&(1<<ch)) {
1450 im->idata[(x+y*im->xsize)*im->channels+ch] =
1451 SampleFTo8(val->channel[ch]);
1455 return -1; /* error was clipped */
1459 =item i_gpixf_d(im, x, y, val)
1465 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1467 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1468 for(ch=0;ch<im->channels;ch++) {
1470 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1474 return -1; /* error was cliped */
1478 =item i_glinf_d(im, l, r, y, vals)
1480 Reads a line of data from the image, storing the pixels at vals.
1482 The line runs from (l,y) inclusive to (r,y) non-inclusive
1484 vals should point at space for (r-l) pixels.
1486 l should never be less than zero (to avoid confusion about where to
1487 put the pixels in vals).
1489 Returns the number of pixels copied (eg. if r, l or y is out of range)
1495 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1497 unsigned char *data;
1498 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1501 data = im->idata + (l+y*im->xsize) * im->channels;
1503 for (i = 0; i < count; ++i) {
1504 for (ch = 0; ch < im->channels; ++ch)
1505 vals[i].channel[ch] = Sample8ToF(*data++);
1515 =item i_plinf_d(im, l, r, y, vals)
1517 Writes a line of data into the image, using the pixels at vals.
1519 The line runs from (l,y) inclusive to (r,y) non-inclusive
1521 vals should point at (r-l) pixels.
1523 l should never be less than zero (to avoid confusion about where to
1524 get the pixels in vals).
1526 Returns the number of pixels copied (eg. if r, l or y is out of range)
1532 i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1534 unsigned char *data;
1535 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1538 data = im->idata + (l+y*im->xsize) * im->channels;
1540 for (i = 0; i < count; ++i) {
1541 for (ch = 0; ch < im->channels; ++ch) {
1542 if (im->ch_mask & (1 << ch))
1543 *data = SampleFTo8(vals[i].channel[ch]);
1555 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1557 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1558 for the channels specified by chans, an array of int with chan_count
1561 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1567 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
1568 const int *chans, int chan_count) {
1569 int ch, count, i, w;
1570 unsigned char *data;
1572 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1575 data = im->idata + (l+y*im->xsize) * im->channels;
1580 /* make sure we have good channel numbers */
1581 for (ch = 0; ch < chan_count; ++ch) {
1582 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1583 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1587 for (i = 0; i < w; ++i) {
1588 for (ch = 0; ch < chan_count; ++ch) {
1589 *samps++ = data[chans[ch]];
1592 data += im->channels;
1596 for (i = 0; i < w; ++i) {
1597 for (ch = 0; ch < chan_count; ++ch) {
1598 *samps++ = data[ch];
1601 data += im->channels;
1613 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1615 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1616 for the channels specified by chan_mask, where bit 0 is the first
1619 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1625 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
1626 const int *chans, int chan_count) {
1627 int ch, count, i, w;
1628 unsigned char *data;
1629 for (ch = 0; ch < chan_count; ++ch) {
1630 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1631 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1634 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1637 data = im->idata + (l+y*im->xsize) * im->channels;
1642 /* make sure we have good channel numbers */
1643 for (ch = 0; ch < chan_count; ++ch) {
1644 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1645 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1649 for (i = 0; i < w; ++i) {
1650 for (ch = 0; ch < chan_count; ++ch) {
1651 *samps++ = Sample8ToF(data[chans[ch]]);
1654 data += im->channels;
1658 for (i = 0; i < w; ++i) {
1659 for (ch = 0; ch < chan_count; ++ch) {
1660 *samps++ = Sample8ToF(data[ch]);
1663 data += im->channels;
1676 =head2 Image method wrappers
1678 These functions provide i_fsample_t functions in terms of their
1679 i_sample_t versions.
1683 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1688 int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1692 for (ch = 0; ch < im->channels; ++ch)
1693 temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1695 return i_ppix(im, x, y, &temp);
1699 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1703 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1707 if (i_gpix(im, x, y, &temp)) {
1708 for (ch = 0; ch < im->channels; ++ch)
1709 pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1717 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1721 int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1724 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1730 work = mymalloc(sizeof(i_color) * (r-l));
1731 for (i = 0; i < r-l; ++i) {
1732 for (ch = 0; ch < im->channels; ++ch)
1733 work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1735 ret = i_plin(im, l, r, y, work);
1750 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1754 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1757 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1763 work = mymalloc(sizeof(i_color) * (r-l));
1764 ret = i_plin(im, l, r, y, work);
1765 for (i = 0; i < r-l; ++i) {
1766 for (ch = 0; ch < im->channels; ++ch)
1767 pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1783 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1787 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
1788 int const *chans, int chan_count) {
1791 if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1797 work = mymalloc(sizeof(i_sample_t) * (r-l));
1798 ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1799 for (i = 0; i < ret; ++i) {
1800 samp[i] = Sample8ToF(work[i]);
1818 =head2 Palette wrapper functions
1820 Used for virtual images, these forward palette calls to a wrapped image,
1821 assuming the wrapped image is the first pointer in the structure that
1822 im->ext_data points at.
1826 =item i_addcolors_forward(i_img *im, i_color *colors, int count)
1830 int i_addcolors_forward(i_img *im, i_color *colors, int count) {
1831 return i_addcolors(*(i_img **)im->ext_data, colors, count);
1835 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1839 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1840 return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1844 =item i_setcolors_forward(i_img *im, int i, i_color *color, int count)
1848 int i_setcolors_forward(i_img *im, int i, i_color *color, int count) {
1849 return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1853 =item i_colorcount_forward(i_img *im)
1857 int i_colorcount_forward(i_img *im) {
1858 return i_colorcount(*(i_img **)im->ext_data);
1862 =item i_maxcolors_forward(i_img *im)
1866 int i_maxcolors_forward(i_img *im) {
1867 return i_maxcolors(*(i_img **)im->ext_data);
1871 =item i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry)
1875 int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry) {
1876 return i_findcolor(*(i_img **)im->ext_data, color, entry);
1882 =head2 Stream reading and writing wrapper functions
1886 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1888 Performs general read buffering for file readers that permit reading
1889 to be done through a callback.
1891 The final callback gets two parameters, a I<need> value, and a I<want>
1892 value, where I<need> is the amount of data that the file library needs
1893 to read, and I<want> is the amount of space available in the buffer
1894 maintained by these functions.
1896 This means if you need to read from a stream that you don't know the
1897 length of, you can return I<need> bytes, taking the performance hit of
1898 possibly expensive callbacks (eg. back to perl code), or if you are
1899 reading from a stream where it doesn't matter if some data is lost, or
1900 if the total length of the stream is known, you can return I<want>
1907 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1910 if (length < gci->length - gci->cpos) {
1912 memcpy(buf, gci->buffer+gci->cpos, length);
1913 gci->cpos += length;
1918 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
1919 total += gci->length - gci->cpos;
1920 length -= gci->length - gci->cpos;
1921 buf += gci->length - gci->cpos;
1922 if (length < (int)sizeof(gci->buffer)) {
1926 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
1927 sizeof(gci->buffer))) > 0) {
1929 gci->length = did_read;
1931 copy_size = i_min(length, gci->length);
1932 memcpy(buf, gci->buffer, copy_size);
1933 gci->cpos += copy_size;
1936 length -= copy_size;
1940 /* just read the rest - too big for our buffer*/
1942 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1952 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1954 For use by callback file readers to initialize the reader buffer.
1956 Allocates, initializes and returns the reader buffer.
1958 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1963 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1964 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1966 self->userdata = userdata;
1974 =item i_free_gen_read_data(i_gen_read_data *)
1980 void i_free_gen_read_data(i_gen_read_data *self) {
1985 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1987 Performs write buffering for a callback based file writer.
1989 Failures are considered fatal, if a write fails then data will be
1996 i_gen_write_data *self,
2000 if (self->filledto && self->filledto+size > self->maxlength) {
2001 if (self->cb(self->userdata, self->buffer, self->filledto)) {
2009 if (self->filledto+size <= self->maxlength) {
2011 memcpy(self->buffer+self->filledto, data, size);
2012 self->filledto += size;
2015 /* doesn't fit - hand it off */
2016 return self->cb(self->userdata, data, size);
2020 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2022 Allocates and initializes the data structure used by i_gen_writer.
2024 This should be released with L<image.c/i_free_gen_write_data>
2028 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
2029 char *userdata, int max_length)
2031 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2033 self->userdata = userdata;
2034 self->maxlength = i_min(max_length, sizeof(self->buffer));
2035 if (self->maxlength < 0)
2036 self->maxlength = sizeof(self->buffer);
2043 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2045 Cleans up the write buffer.
2047 Will flush any left-over data if I<flush> is non-zero.
2049 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2051 Return zero only if flush is non-zero and info->cb() returns zero.
2057 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2059 int result = !flush ||
2060 info->filledto == 0 ||
2061 info->cb(info->userdata, info->buffer, info->filledto);
2070 =item i_test_format_probe(io_glue *data, int length)
2072 Check the beginning of the supplied file for a 'magic number'
2079 i_test_format_probe(io_glue *data, int length) {
2085 {"\xFF\xD8", "jpeg"},
2091 {"\x89PNG\x0d\x0a\x1a\x0a", "png"},
2104 io_glue_commit_types(data);
2105 rc = data->readcb(data, head, 18);
2106 if (rc == -1) return NULL;
2107 data->seekcb(data, -rc, SEEK_CUR);
2109 for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
2111 ssize_t len = strlen(formats[i].magic);
2112 if (rc<len) continue;
2113 c = !strncmp(formats[i].magic, head, len);
2115 match = formats[i].name;
2121 if (match && !strcmp(match, "jpeg")) {
2122 unsigned int x0, x1;
2123 rc = data->readcb(data, head, 18);
2124 if (rc == -1) return NULL;
2125 x0 = (unsigned char)head[0];
2126 x1 = (unsigned char)head[1];
2127 data->seekcb(data, -rc, SEEK_CUR);
2128 printf("Jpeg reread: %x %x\n", x0, x1);
2134 tga_header_verify(head)) return "tga";
2146 Arnar M. Hrafnkelsson <addi@umich.edu>
2148 Tony Cook <tony@develop-help.com>