]> git.imager.perl.org - imager.git/blob - image.c
avoid warning about gccversion being non-numeric
[imager.git] / image.c
1 #include "imager.h"
2 #include "imageri.h"
3
4 /*
5 =head1 NAME
6
7 image.c - implements most of the basic functions of Imager and much of the rest
8
9 =head1 SYNOPSIS
10
11   i_img *i;
12   i_color *c;
13   c = i_color_new(red, green, blue, alpha);
14   ICL_DESTROY(c);
15   i = i_img_new();
16   i_img_destroy(i);
17   // and much more
18
19 =head1 DESCRIPTION
20
21 image.c implements the basic functions to create and destroy image and
22 color objects for Imager.
23
24 =head1 FUNCTION REFERENCE
25
26 Some of these functions are internal.
27
28 =over
29
30 =cut
31 */
32
33 #define XAXIS 0
34 #define YAXIS 1
35 #define XYAXIS 2
36
37 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i   )) )
38
39 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
40 void i_linker_bug_fake(void) { ceil(1); }
41
42 /*
43 =item i_img_alloc()
44 =category Image Implementation
45
46 Allocates a new i_img structure.
47
48 When implementing a new image type perform the following steps in your
49 image object creation function:
50
51 =over
52
53 =item 1.
54
55 allocate the image with i_img_alloc().
56
57 =item 2.
58
59 initialize any function pointers or other data as needed, you can
60 overwrite the whole block if you need to.
61
62 =item 3.
63
64 initialize Imager's internal data by calling i_img_init() on the image
65 object.
66
67 =back
68
69 =cut
70 */
71
72 i_img *
73 i_img_alloc(void) {
74   return mymalloc(sizeof(i_img));
75 }
76
77 /*
78 =item i_img_init(C<img>)
79 =category Image Implementation
80
81 Imager internal initialization of images.
82
83 Currently this does very little, in the future it may be used to
84 support threads, or color profiles.
85
86 =cut
87 */
88
89 void
90 i_img_init(i_img *img) {
91   img->im_data = NULL;
92 }
93
94 /* 
95 =item ICL_new_internal(r, g, b, a)
96
97 Return a new color object with values passed to it.
98
99    r - red   component (range: 0 - 255)
100    g - green component (range: 0 - 255)
101    b - blue  component (range: 0 - 255)
102    a - alpha component (range: 0 - 255)
103
104 =cut
105 */
106
107 i_color *
108 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
109   i_color *cl = NULL;
110
111   mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
112
113   if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
114   cl->rgba.r = r;
115   cl->rgba.g = g;
116   cl->rgba.b = b;
117   cl->rgba.a = a;
118   mm_log((1,"(%p) <- ICL_new_internal\n",cl));
119   return cl;
120 }
121
122
123 /*
124 =item ICL_set_internal(cl, r, g, b, a)
125
126  Overwrite a color with new values.
127
128    cl - pointer to color object
129    r - red   component (range: 0 - 255)
130    g - green component (range: 0 - 255)
131    b - blue  component (range: 0 - 255)
132    a - alpha component (range: 0 - 255)
133
134 =cut
135 */
136
137 i_color *
138 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
139   mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
140   if (cl == NULL)
141     if ( (cl=mymalloc(sizeof(i_color))) == NULL)
142       i_fatal(2,"malloc() error\n");
143   cl->rgba.r=r;
144   cl->rgba.g=g;
145   cl->rgba.b=b;
146   cl->rgba.a=a;
147   mm_log((1,"(%p) <- ICL_set_internal\n",cl));
148   return cl;
149 }
150
151
152 /* 
153 =item ICL_add(dst, src, ch)
154
155 Add src to dst inplace - dst is modified.
156
157    dst - pointer to destination color object
158    src - pointer to color object that is added
159    ch - number of channels
160
161 =cut
162 */
163
164 void
165 ICL_add(i_color *dst,i_color *src,int ch) {
166   int tmp,i;
167   for(i=0;i<ch;i++) {
168     tmp=dst->channel[i]+src->channel[i];
169     dst->channel[i]= tmp>255 ? 255:tmp;
170   }
171 }
172
173 /* 
174 =item ICL_info(cl)
175
176 Dump color information to log - strictly for debugging.
177
178    cl - pointer to color object
179
180 =cut
181 */
182
183 void
184 ICL_info(i_color const *cl) {
185   mm_log((1,"i_color_info(cl* %p)\n",cl));
186   mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
187 }
188
189 /* 
190 =item ICL_DESTROY
191
192 Destroy ancillary data for Color object.
193
194    cl - pointer to color object
195
196 =cut
197 */
198
199 void
200 ICL_DESTROY(i_color *cl) {
201   mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
202   myfree(cl);
203 }
204
205 /*
206 =item i_fcolor_new(double r, double g, double b, double a)
207
208 =cut
209 */
210 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
211   i_fcolor *cl = NULL;
212
213   mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
214
215   if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
216   cl->rgba.r = r;
217   cl->rgba.g = g;
218   cl->rgba.b = b;
219   cl->rgba.a = a;
220   mm_log((1,"(%p) <- i_fcolor_new\n",cl));
221
222   return cl;
223 }
224
225 /*
226 =item i_fcolor_destroy(i_fcolor *cl) 
227
228 =cut
229 */
230 void i_fcolor_destroy(i_fcolor *cl) {
231   myfree(cl);
232 }
233
234 /* 
235 =item i_img_exorcise(im)
236
237 Free image data.
238
239    im - Image pointer
240
241 =cut
242 */
243
244 void
245 i_img_exorcise(i_img *im) {
246   mm_log((1,"i_img_exorcise(im* %p)\n",im));
247   i_tags_destroy(&im->tags);
248   if (im->i_f_destroy)
249     (im->i_f_destroy)(im);
250   if (im->idata != NULL) { myfree(im->idata); }
251   im->idata    = NULL;
252   im->xsize    = 0;
253   im->ysize    = 0;
254   im->channels = 0;
255
256   im->ext_data=NULL;
257 }
258
259 /* 
260 =item i_img_destroy(C<img>)
261 =order 90
262 =category Image creation/destruction
263 =synopsis i_img_destroy(img)
264
265 Destroy an image object
266
267 =cut
268 */
269
270 void
271 i_img_destroy(i_img *im) {
272   mm_log((1,"i_img_destroy(im %p)\n",im));
273   i_img_exorcise(im);
274   if (im) { myfree(im); }
275 }
276
277 /* 
278 =item i_img_info(im, info)
279
280 =category Image
281
282 Return image information
283
284    im - Image pointer
285    info - pointer to array to return data
286
287 info is an array of 4 integers with the following values:
288
289  info[0] - width
290  info[1] - height
291  info[2] - channels
292  info[3] - channel mask
293
294 =cut
295 */
296
297
298 void
299 i_img_info(i_img *im, i_img_dim *info) {
300   mm_log((1,"i_img_info(im %p)\n",im));
301   if (im != NULL) {
302     mm_log((1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
303             "mask=%ud\n",
304             i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
305     mm_log((1,"i_img_info: idata=%p\n",im->idata));
306     info[0] = im->xsize;
307     info[1] = im->ysize;
308     info[2] = im->channels;
309     info[3] = im->ch_mask;
310   } else {
311     info[0] = 0;
312     info[1] = 0;
313     info[2] = 0;
314     info[3] = 0;
315   }
316 }
317
318 /*
319 =item i_img_setmask(C<im>, C<ch_mask>)
320 =category Image Information
321 =synopsis // only channel 0 writeable 
322 =synopsis i_img_setmask(img, 0x01);
323
324 Set the image channel mask for C<im> to C<ch_mask>.
325
326 The image channel mask gives some control over which channels can be
327 written to in the image.
328
329 =cut
330 */
331 void
332 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
333
334
335 /*
336 =item i_img_getmask(C<im>)
337 =category Image Information
338 =synopsis int mask = i_img_getmask(img);
339
340 Get the image channel mask for C<im>.
341
342 =cut
343 */
344 int
345 i_img_getmask(i_img *im) { return im->ch_mask; }
346
347 /*
348 =item i_img_getchannels(C<im>)
349 =category Image Information
350 =synopsis int channels = i_img_getchannels(img);
351
352 Get the number of channels in C<im>.
353
354 =cut
355 */
356 int
357 i_img_getchannels(i_img *im) { return im->channels; }
358
359 /*
360 =item i_img_get_width(C<im>)
361 =category Image Information
362 =synopsis i_img_dim width = i_img_get_width(im);
363
364 Returns the width in pixels of the image.
365
366 =cut
367 */
368 i_img_dim
369 i_img_get_width(i_img *im) {
370   return im->xsize;
371 }
372
373 /*
374 =item i_img_get_height(C<im>)
375 =category Image Information
376 =synopsis i_img_dim height = i_img_get_height(im);
377
378 Returns the height in pixels of the image.
379
380 =cut
381 */
382 i_img_dim
383 i_img_get_height(i_img *im) {
384   return im->ysize;
385 }
386
387 /*
388 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
389
390 =category Image
391
392 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
393 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
394 the target image.  pass NULL in C<trans> for non transparent i_colors.
395
396 =cut
397 */
398
399 void
400 i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans) {
401   i_color pv;
402   i_img_dim x,y,t,ttx,tty,tt;
403   int ch;
404
405   mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
406           "to(" i_DFp "), trans* %p)\n",
407           im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
408   
409   if (x2<x1) { t=x1; x1=x2; x2=t; }
410   if (y2<y1) { t=y1; y1=y2; y2=t; }
411
412   ttx=tx;
413   for(x=x1;x<x2;x++)
414     {
415       tty=ty;
416       for(y=y1;y<y2;y++)
417         {
418           i_gpix(src,x,y,&pv);
419           if ( trans != NULL)
420           {
421             tt=0;
422             for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
423             if (tt) i_ppix(im,ttx,tty,&pv);
424           } else i_ppix(im,ttx,tty,&pv);
425           tty++;
426         }
427       ttx++;
428     }
429 }
430
431 /*
432 =item i_copy(source)
433
434 =category Image
435
436 Creates a new image that is a copy of the image C<source>.
437
438 Tags are not copied, only the image data.
439
440 Returns: i_img *
441
442 =cut
443 */
444
445 i_img *
446 i_copy(i_img *src) {
447   i_img_dim y, y1, x1;
448   i_img *im = i_sametype(src, src->xsize, src->ysize);
449
450   mm_log((1,"i_copy(src %p)\n", src));
451
452   if (!im)
453     return NULL;
454
455   x1 = src->xsize;
456   y1 = src->ysize;
457   if (src->type == i_direct_type) {
458     if (src->bits == i_8_bits) {
459       i_color *pv;
460       pv = mymalloc(sizeof(i_color) * x1);
461       
462       for (y = 0; y < y1; ++y) {
463         i_glin(src, 0, x1, y, pv);
464         i_plin(im, 0, x1, y, pv);
465       }
466       myfree(pv);
467     }
468     else {
469       i_fcolor *pv;
470
471       pv = mymalloc(sizeof(i_fcolor) * x1);
472       for (y = 0; y < y1; ++y) {
473         i_glinf(src, 0, x1, y, pv);
474         i_plinf(im, 0, x1, y, pv);
475       }
476       myfree(pv);
477     }
478   }
479   else {
480     i_palidx *vals;
481
482     vals = mymalloc(sizeof(i_palidx) * x1);
483     for (y = 0; y < y1; ++y) {
484       i_gpal(src, 0, x1, y, vals);
485       i_ppal(im, 0, x1, y, vals);
486     }
487     myfree(vals);
488   }
489
490   return im;
491 }
492
493 /*
494
495 http://en.wikipedia.org/wiki/Lanczos_resampling
496
497 */
498
499 static
500 float
501 Lanczos(float x) {
502   float PIx, PIx2;
503   
504   PIx = PI * x;
505   PIx2 = PIx / 2.0;
506   
507   if ((x >= 2.0) || (x <= -2.0)) return (0.0);
508   else if (x == 0.0) return (1.0);
509   else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
510 }
511
512
513 /*
514 =item i_scaleaxis(im, value, axis)
515
516 Returns a new image object which is I<im> scaled by I<value> along
517 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
518
519 =cut
520 */
521
522 i_img*
523 i_scaleaxis(i_img *im, double Value, int Axis) {
524   i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
525   i_img_dim LanczosWidthFactor;
526   float *l0, *l1;
527   double OldLocation;
528   i_img_dim T; 
529   double t;
530   float F, PictureValue[MAXCHANNELS];
531   short psave;
532   i_color val,val1,val2;
533   i_img *new_img;
534   int has_alpha = i_img_has_alpha(im);
535   int color_chans = i_img_color_channels(im);
536
537   i_clear_error();
538   mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
539
540   if (Axis == XAXIS) {
541     hsize = (i_img_dim)(0.5 + im->xsize * Value);
542     if (hsize < 1) {
543       hsize = 1;
544       Value = 1.0 / im->xsize;
545     }
546     vsize = im->ysize;
547     
548     jEnd = hsize;
549     iEnd = vsize;
550   } else {
551     hsize = im->xsize;
552     vsize = (i_img_dim)(0.5 + im->ysize * Value);
553
554     if (vsize < 1) {
555       vsize = 1;
556       Value = 1.0 / im->ysize;
557     }
558
559     jEnd = vsize;
560     iEnd = hsize;
561   }
562   
563   new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
564   if (!new_img) {
565     i_push_error(0, "cannot create output image");
566     return NULL;
567   }
568   
569   /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
570   LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value); 
571   lMax = LanczosWidthFactor << 1;
572   
573   l0 = mymalloc(lMax * sizeof(float));
574   l1 = mymalloc(lMax * sizeof(float));
575   
576   for (j=0; j<jEnd; j++) {
577     OldLocation = ((double) j) / Value;
578     T = (i_img_dim) (OldLocation);
579     F = OldLocation - T;
580     
581     for (l = 0; l<lMax; l++) {
582       l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
583       l1[l]        = Lanczos(((float) (l+1)      - F) / (float) LanczosWidthFactor);
584     }
585     
586     /* Make sure filter is normalized */
587     t = 0.0;
588     for(l=0; l<lMax; l++) {
589       t+=l0[l];
590       t+=l1[l];
591     }
592     t /= (double)LanczosWidthFactor;
593     
594     for(l=0; l<lMax; l++) {
595       l0[l] /= t;
596       l1[l] /= t;
597     }
598
599     if (Axis == XAXIS) {
600       
601       for (i=0; i<iEnd; i++) {
602         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
603         for (l=0; l<lMax; l++) {
604           i_img_dim mx = T-lMax+l+1;
605           i_img_dim Mx = T+l+1;
606           mx = (mx < 0) ? 0 : mx;
607           Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
608           
609           i_gpix(im, Mx, i, &val1);
610           i_gpix(im, mx, i, &val2);
611
612           if (has_alpha) {
613             i_sample_t alpha1 = val1.channel[color_chans];
614             i_sample_t alpha2 = val2.channel[color_chans];
615             for (k=0; k < color_chans; k++) {
616               PictureValue[k] += l1[l]        * val1.channel[k] * alpha1 / 255;
617               PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
618             }
619             PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
620             PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
621           }
622           else {
623             for (k=0; k<im->channels; k++) {
624               PictureValue[k] += l1[l]        * val1.channel[k];
625               PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
626             }
627           }
628         }
629
630         if (has_alpha) {
631           float fa = PictureValue[color_chans] / LanczosWidthFactor;
632           int alpha = minmax(0, 255, fa+0.5);
633           if (alpha) {
634             for (k = 0; k < color_chans; ++k) {
635               psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
636               val.channel[k]=minmax(0,255,psave);
637             }
638             val.channel[color_chans] = alpha;
639           }
640           else {
641             /* zero alpha, so the pixel has no color */
642             for (k = 0; k < im->channels; ++k)
643               val.channel[k] = 0;
644           }
645         }
646         else {
647           for(k=0;k<im->channels;k++) {
648             psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
649             val.channel[k]=minmax(0,255,psave);
650           }
651         }
652         i_ppix(new_img, j, i, &val);
653       }
654       
655     } else {
656       
657       for (i=0; i<iEnd; i++) {
658         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
659         for (l=0; l < lMax; l++) {
660           i_img_dim mx = T-lMax+l+1;
661           i_img_dim Mx = T+l+1;
662           mx = (mx < 0) ? 0 : mx;
663           Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
664
665           i_gpix(im, i, Mx, &val1);
666           i_gpix(im, i, mx, &val2);
667           if (has_alpha) {
668             i_sample_t alpha1 = val1.channel[color_chans];
669             i_sample_t alpha2 = val2.channel[color_chans];
670             for (k=0; k < color_chans; k++) {
671               PictureValue[k] += l1[l]        * val1.channel[k] * alpha1 / 255;
672               PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
673             }
674             PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
675             PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
676           }
677           else {
678             for (k=0; k<im->channels; k++) {
679               PictureValue[k] += l1[l]        * val1.channel[k];
680               PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
681             }
682           }
683         }
684         if (has_alpha) {
685           float fa = PictureValue[color_chans] / LanczosWidthFactor;
686           int alpha = minmax(0, 255, fa+0.5);
687           if (alpha) {
688             for (k = 0; k < color_chans; ++k) {
689               psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
690               val.channel[k]=minmax(0,255,psave);
691             }
692             val.channel[color_chans] = alpha;
693           }
694           else {
695             for (k = 0; k < im->channels; ++k)
696               val.channel[k] = 0;
697           }
698         }
699         else {
700           for(k=0;k<im->channels;k++) {
701             psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
702             val.channel[k]=minmax(0,255,psave);
703           }
704         }
705         i_ppix(new_img, i, j, &val);
706       }
707       
708     }
709   }
710   myfree(l0);
711   myfree(l1);
712
713   mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
714
715   return new_img;
716 }
717
718
719 /* 
720 =item i_scale_nn(im, scx, scy)
721
722 Scale by using nearest neighbor 
723 Both axes scaled at the same time since 
724 nothing is gained by doing it in two steps 
725
726 =cut
727 */
728
729
730 i_img*
731 i_scale_nn(i_img *im, double scx, double scy) {
732
733   i_img_dim nxsize,nysize,nx,ny;
734   i_img *new_img;
735   i_color val;
736
737   mm_log((1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
738
739   nxsize = (i_img_dim) ((double) im->xsize * scx);
740   if (nxsize < 1) {
741     nxsize = 1;
742     scx = 1.0 / im->xsize;
743   }
744   nysize = (i_img_dim) ((double) im->ysize * scy);
745   if (nysize < 1) {
746     nysize = 1;
747     scy = 1.0 / im->ysize;
748   }
749   im_assert(scx != 0 && scy != 0);
750     
751   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
752   
753   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
754     i_gpix(im,((double)nx)/scx,((double)ny)/scy,&val);
755     i_ppix(new_img,nx,ny,&val);
756   }
757
758   mm_log((1,"(%p) <- i_scale_nn\n",new_img));
759
760   return new_img;
761 }
762
763 /*
764 =item i_sametype(C<im>, C<xsize>, C<ysize>)
765
766 =category Image creation/destruction
767 =synopsis i_img *img = i_sametype(src, width, height);
768
769 Returns an image of the same type (sample size, channels, paletted/direct).
770
771 For paletted images the palette is copied from the source.
772
773 =cut
774 */
775
776 i_img *i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
777   if (src->type == i_direct_type) {
778     if (src->bits == 8) {
779       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
780     }
781     else if (src->bits == i_16_bits) {
782       return i_img_16_new(xsize, ysize, src->channels);
783     }
784     else if (src->bits == i_double_bits) {
785       return i_img_double_new(xsize, ysize, src->channels);
786     }
787     else {
788       i_push_error(0, "Unknown image bits");
789       return NULL;
790     }
791   }
792   else {
793     i_color col;
794     int i;
795
796     i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
797     for (i = 0; i < i_colorcount(src); ++i) {
798       i_getcolors(src, i, &col, 1);
799       i_addcolors(targ, &col, 1);
800     }
801
802     return targ;
803   }
804 }
805
806 /*
807 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
808
809 =category Image creation/destruction
810 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
811
812 Returns an image of the same type (sample size).
813
814 For paletted images the equivalent direct type is returned.
815
816 =cut
817 */
818
819 i_img *i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
820   if (src->bits == 8) {
821     return i_img_empty_ch(NULL, xsize, ysize, channels);
822   }
823   else if (src->bits == i_16_bits) {
824     return i_img_16_new(xsize, ysize, channels);
825   }
826   else if (src->bits == i_double_bits) {
827     return i_img_double_new(xsize, ysize, channels);
828   }
829   else {
830     i_push_error(0, "Unknown image bits");
831     return NULL;
832   }
833 }
834
835 /*
836 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
837
838 Spatially transforms I<im> returning a new image.
839
840 opx for a length of opxl and opy for a length of opy are arrays of
841 operators that modify the x and y positions to retreive the pixel data from.
842
843 parm and parmlen define extra parameters that the operators may use.
844
845 Note that this function is largely superseded by the more flexible
846 L<transform.c/i_transform2>.
847
848 Returns the new image.
849
850 The operators for this function are defined in L<stackmach.c>.
851
852 =cut
853 */
854 i_img*
855 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
856   double rx,ry;
857   i_img_dim nxsize,nysize,nx,ny;
858   i_img *new_img;
859   i_color val;
860   
861   mm_log((1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
862
863   nxsize = im->xsize;
864   nysize = im->ysize ;
865   
866   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
867   /*   fprintf(stderr,"parm[2]=%f\n",parm[2]);   */
868   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
869     /*     parm[parmlen-2]=(double)nx;
870            parm[parmlen-1]=(double)ny; */
871
872     parm[0]=(double)nx;
873     parm[1]=(double)ny;
874
875     /*     fprintf(stderr,"(%d,%d) ->",nx,ny);  */
876     rx=i_op_run(opx,opxl,parm,parmlen);
877     ry=i_op_run(opy,opyl,parm,parmlen);
878     /*    fprintf(stderr,"(%f,%f)\n",rx,ry); */
879     i_gpix(im,rx,ry,&val);
880     i_ppix(new_img,nx,ny,&val);
881   }
882
883   mm_log((1,"(%p) <- i_transform\n",new_img));
884   return new_img;
885 }
886
887 /*
888 =item i_img_diff(im1, im2)
889
890 Calculates the sum of the squares of the differences between
891 correspoding channels in two images.
892
893 If the images are not the same size then only the common area is 
894 compared, hence even if images are different sizes this function 
895 can return zero.
896
897 =cut
898 */
899
900 float
901 i_img_diff(i_img *im1,i_img *im2) {
902   i_img_dim x, y, xb, yb;
903   int ch, chb;
904   float tdiff;
905   i_color val1,val2;
906
907   mm_log((1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
908
909   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
910   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
911   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
912
913   mm_log((1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
914           i_DFcp(xb,yb), chb));
915
916   tdiff=0;
917   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
918     i_gpix(im1,x,y,&val1);
919     i_gpix(im2,x,y,&val2);
920
921     for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
922   }
923   mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
924   return tdiff;
925 }
926
927 /*
928 =item i_img_diffd(im1, im2)
929
930 Calculates the sum of the squares of the differences between
931 correspoding channels in two images.
932
933 If the images are not the same size then only the common area is 
934 compared, hence even if images are different sizes this function 
935 can return zero.
936
937 This is like i_img_diff() but looks at floating point samples instead.
938
939 =cut
940 */
941
942 double
943 i_img_diffd(i_img *im1,i_img *im2) {
944   i_img_dim x, y, xb, yb;
945   int ch, chb;
946   double tdiff;
947   i_fcolor val1,val2;
948
949   mm_log((1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
950
951   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
952   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
953   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
954
955   mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
956           i_DFcp(xb, yb), chb));
957
958   tdiff=0;
959   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
960     i_gpixf(im1,x,y,&val1);
961     i_gpixf(im2,x,y,&val2);
962
963     for(ch=0;ch<chb;ch++) {
964       double sdiff = val1.channel[ch]-val2.channel[ch];
965       tdiff += sdiff * sdiff;
966     }
967   }
968   mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
969
970   return tdiff;
971 }
972
973 int
974 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
975   i_img_dim x,y,xb,yb;
976   int ch, chb;
977   i_fcolor val1,val2;
978
979   if (what == NULL)
980     what = "(null)";
981
982   mm_log((1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
983
984   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
985   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
986   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
987
988   mm_log((1,"i_img_samef: b(" i_DFp ") chb=%d\n",
989           i_DFcp(xb, yb), chb));
990
991   for(y = 0; y < yb; y++) {
992     for(x = 0; x < xb; x++) {
993       i_gpixf(im1, x, y, &val1);
994       i_gpixf(im2, x, y, &val2);
995       
996       for(ch = 0; ch < chb; ch++) {
997         double sdiff = val1.channel[ch] - val2.channel[ch];
998         if (fabs(sdiff) > epsilon) {
999           mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n",
1000                   sdiff, i_DFcp(x, y)));
1001           return 0;
1002         }
1003       }
1004     }
1005   }
1006   mm_log((1,"i_img_samef <- same\n"));
1007
1008   return 1;
1009 }
1010
1011 /* just a tiny demo of haar wavelets */
1012
1013 i_img*
1014 i_haar(i_img *im) {
1015   i_img_dim mx,my;
1016   i_img_dim fx,fy;
1017   i_img_dim x,y;
1018   int ch,c;
1019   i_img *new_img,*new_img2;
1020   i_color val1,val2,dval1,dval2;
1021   
1022   mx=im->xsize;
1023   my=im->ysize;
1024   fx=(mx+1)/2;
1025   fy=(my+1)/2;
1026
1027
1028   /* horizontal pass */
1029   
1030   new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1031   new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1032
1033   c=0; 
1034   for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1035     i_gpix(im,x*2,y,&val1);
1036     i_gpix(im,x*2+1,y,&val2);
1037     for(ch=0;ch<im->channels;ch++) {
1038       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1039       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1040     }
1041     i_ppix(new_img,x,y,&dval1);
1042     i_ppix(new_img,x+fx,y,&dval2);
1043   }
1044
1045   for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1046     i_gpix(new_img,x,y*2,&val1);
1047     i_gpix(new_img,x,y*2+1,&val2);
1048     for(ch=0;ch<im->channels;ch++) {
1049       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1050       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1051     }
1052     i_ppix(new_img2,x,y,&dval1);
1053     i_ppix(new_img2,x,y+fy,&dval2);
1054   }
1055
1056   i_img_destroy(new_img);
1057   return new_img2;
1058 }
1059
1060 /* 
1061 =item i_count_colors(im, maxc)
1062
1063 returns number of colors or -1 
1064 to indicate that it was more than max colors
1065
1066 =cut
1067 */
1068 /* This function has been changed and is now faster. It's using
1069  * i_gsamp instead of i_gpix */
1070 int
1071 i_count_colors(i_img *im,int maxc) {
1072   struct octt *ct;
1073   i_img_dim x,y;
1074   int colorcnt;
1075   int channels[3];
1076   int *samp_chans;
1077   i_sample_t * samp;
1078   i_img_dim xsize = im->xsize; 
1079   i_img_dim ysize = im->ysize;
1080   int samp_cnt = 3 * xsize;
1081
1082   if (im->channels >= 3) {
1083     samp_chans = NULL;
1084   }
1085   else {
1086     channels[0] = channels[1] = channels[2] = 0;
1087     samp_chans = channels;
1088   }
1089
1090   ct = octt_new();
1091
1092   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1093
1094   colorcnt = 0;
1095   for(y = 0; y < ysize; ) {
1096       i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1097       for(x = 0; x < samp_cnt; ) {
1098           colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1099           x += 3;
1100           if (colorcnt > maxc) { 
1101               octt_delete(ct); 
1102               return -1; 
1103           }
1104       }
1105   }
1106   myfree(samp);
1107   octt_delete(ct);
1108   return colorcnt;
1109 }
1110
1111 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm 
1112  * (adapted from the Numerical Recipes)
1113  */
1114 /* Needed by get_anonymous_color_histo */
1115 static void
1116 hpsort(unsigned int n, unsigned *ra) {
1117     unsigned int i,
1118                  ir,
1119                  j,
1120                  l, 
1121                  rra;
1122
1123     if (n < 2) return;
1124     l = n >> 1;
1125     ir = n - 1;
1126     for(;;) {
1127         if (l > 0) {
1128             rra = ra[--l];
1129         }
1130         else {
1131             rra = ra[ir];
1132             ra[ir] = ra[0];
1133             if (--ir == 0) {
1134                 ra[0] = rra;
1135                 break;
1136             }
1137         }
1138         i = l;
1139         j = 2 * l + 1;
1140         while (j <= ir) {
1141             if (j < ir && ra[j] < ra[j+1]) j++;
1142             if (rra < ra[j]) {
1143                 ra[i] = ra[j];
1144                 i = j;
1145                 j++; j <<= 1; j--;
1146             }
1147             else break;
1148         }
1149         ra[i] = rra;
1150     }
1151 }
1152
1153 /* This function constructs an ordered list which represents how much the
1154  * different colors are used. So for instance (100, 100, 500) means that one
1155  * color is used for 500 pixels, another for 100 pixels and another for 100
1156  * pixels. It's tuned for performance. You might not like the way I've hardcoded
1157  * the maxc ;-) and you might want to change the name... */
1158 /* Uses octt_histo */
1159 int
1160 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1161   struct octt *ct;
1162   i_img_dim x,y;
1163   int colorcnt;
1164   unsigned int *col_usage_it;
1165   i_sample_t * samp;
1166   int channels[3];
1167   int *samp_chans;
1168   
1169   i_img_dim xsize = im->xsize; 
1170   i_img_dim ysize = im->ysize;
1171   int samp_cnt = 3 * xsize;
1172   ct = octt_new();
1173   
1174   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1175   
1176   if (im->channels >= 3) {
1177     samp_chans = NULL;
1178   }
1179   else {
1180     channels[0] = channels[1] = channels[2] = 0;
1181     samp_chans = channels;
1182   }
1183
1184   colorcnt = 0;
1185   for(y = 0; y < ysize; ) {
1186     i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1187     for(x = 0; x < samp_cnt; ) {
1188       colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1189       x += 3;
1190       if (colorcnt > maxc) { 
1191         octt_delete(ct); 
1192         return -1; 
1193       }
1194     }
1195   }
1196   myfree(samp);
1197   /* Now that we know the number of colours... */
1198   col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1199   octt_histo(ct, &col_usage_it);
1200   hpsort(colorcnt, *col_usage);
1201   octt_delete(ct);
1202   return colorcnt;
1203 }
1204
1205 /*
1206 =back
1207
1208 =head2 Image method wrappers
1209
1210 These functions provide i_fsample_t functions in terms of their
1211 i_sample_t versions.
1212
1213 =over
1214
1215 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1216
1217 =cut
1218 */
1219
1220 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1221   i_color temp;
1222   int ch;
1223
1224   for (ch = 0; ch < im->channels; ++ch)
1225     temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1226   
1227   return i_ppix(im, x, y, &temp);
1228 }
1229
1230 /*
1231 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1232
1233 =cut
1234 */
1235 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1236   i_color temp;
1237   int ch;
1238
1239   if (i_gpix(im, x, y, &temp)) {
1240     for (ch = 0; ch < im->channels; ++ch)
1241       pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1242     return 0;
1243   }
1244   else 
1245     return -1;
1246 }
1247
1248 /*
1249 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1250
1251 =cut
1252 */
1253 i_img_dim
1254 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1255   i_color *work;
1256
1257   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1258     if (r > im->xsize)
1259       r = im->xsize;
1260     if (r > l) {
1261       i_img_dim ret;
1262       i_img_dim i;
1263       int ch;
1264       work = mymalloc(sizeof(i_color) * (r-l));
1265       for (i = 0; i < r-l; ++i) {
1266         for (ch = 0; ch < im->channels; ++ch) 
1267           work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1268       }
1269       ret = i_plin(im, l, r, y, work);
1270       myfree(work);
1271
1272       return ret;
1273     }
1274     else {
1275       return 0;
1276     }
1277   }
1278   else {
1279     return 0;
1280   }
1281 }
1282
1283 /*
1284 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1285
1286 =cut
1287 */
1288 i_img_dim
1289 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1290   i_color *work;
1291
1292   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1293     if (r > im->xsize)
1294       r = im->xsize;
1295     if (r > l) {
1296       i_img_dim ret;
1297       i_img_dim i;
1298       int ch;
1299       work = mymalloc(sizeof(i_color) * (r-l));
1300       ret = i_plin(im, l, r, y, work);
1301       for (i = 0; i < r-l; ++i) {
1302         for (ch = 0; ch < im->channels; ++ch) 
1303           pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1304       }
1305       myfree(work);
1306
1307       return ret;
1308     }
1309     else {
1310       return 0;
1311     }
1312   }
1313   else {
1314     return 0;
1315   }
1316 }
1317
1318 /*
1319 =item i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int *chans, int chan_count)
1320
1321 =cut
1322 */
1323
1324 i_img_dim
1325 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, 
1326                 int const *chans, int chan_count) {
1327   i_sample_t *work;
1328
1329   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1330     if (r > im->xsize)
1331       r = im->xsize;
1332     if (r > l) {
1333       i_img_dim ret;
1334       i_img_dim i;
1335       work = mymalloc(sizeof(i_sample_t) * (r-l));
1336       ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1337       for (i = 0; i < ret; ++i) {
1338           samp[i] = Sample8ToF(work[i]);
1339       }
1340       myfree(work);
1341
1342       return ret;
1343     }
1344     else {
1345       return 0;
1346     }
1347   }
1348   else {
1349     return 0;
1350   }
1351 }
1352
1353 /*
1354 =back
1355
1356 =head2 Palette wrapper functions
1357
1358 Used for virtual images, these forward palette calls to a wrapped image, 
1359 assuming the wrapped image is the first pointer in the structure that 
1360 im->ext_data points at.
1361
1362 =over
1363
1364 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1365
1366 =cut
1367 */
1368 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1369   return i_addcolors(*(i_img **)im->ext_data, colors, count);
1370 }
1371
1372 /*
1373 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1374
1375 =cut
1376 */
1377 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1378   return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1379 }
1380
1381 /*
1382 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1383
1384 =cut
1385 */
1386 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1387   return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1388 }
1389
1390 /*
1391 =item i_colorcount_forward(i_img *im)
1392
1393 =cut
1394 */
1395 int i_colorcount_forward(i_img *im) {
1396   return i_colorcount(*(i_img **)im->ext_data);
1397 }
1398
1399 /*
1400 =item i_maxcolors_forward(i_img *im)
1401
1402 =cut
1403 */
1404 int i_maxcolors_forward(i_img *im) {
1405   return i_maxcolors(*(i_img **)im->ext_data);
1406 }
1407
1408 /*
1409 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1410
1411 =cut
1412 */
1413 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1414   return i_findcolor(*(i_img **)im->ext_data, color, entry);
1415 }
1416
1417 /*
1418 =back
1419
1420 =head2 Fallback handler
1421
1422 =over
1423
1424 =item i_gsamp_bits_fb
1425
1426 =cut
1427 */
1428
1429 i_img_dim
1430 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, 
1431                 const int *chans, int chan_count, int bits) {
1432   if (bits < 1 || bits > 32) {
1433     i_push_error(0, "Invalid bits, must be 1..32");
1434     return -1;
1435   }
1436
1437   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1438     double scale;
1439     int ch;
1440     i_img_dim count, i, w;
1441     
1442     if (bits == 32)
1443       scale = 4294967295.0;
1444     else
1445       scale = (double)(1 << bits) - 1;
1446
1447     if (r > im->xsize)
1448       r = im->xsize;
1449     w = r - l;
1450     count = 0;
1451
1452     if (chans) {
1453       /* make sure we have good channel numbers */
1454       for (ch = 0; ch < chan_count; ++ch) {
1455         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1456           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1457           return -1;
1458         }
1459       }
1460       for (i = 0; i < w; ++i) {
1461         i_fcolor c;
1462         i_gpixf(im, l+i, y, &c);
1463         for (ch = 0; ch < chan_count; ++ch) {
1464           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1465           ++count;
1466         }
1467       }
1468     }
1469     else {
1470       if (chan_count <= 0 || chan_count > im->channels) {
1471         i_push_error(0, "Invalid channel count");
1472         return -1;
1473       }
1474       for (i = 0; i < w; ++i) {
1475         i_fcolor c;
1476         i_gpixf(im, l+i, y, &c);
1477         for (ch = 0; ch < chan_count; ++ch) {
1478           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1479           ++count;
1480         }
1481       }
1482     }
1483
1484     return count;
1485   }
1486   else {
1487     i_push_error(0, "Image position outside of image");
1488     return -1;
1489   }
1490 }
1491
1492 /*
1493 =back
1494
1495 =head2 Stream reading and writing wrapper functions
1496
1497 =over
1498
1499 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1500
1501 Performs general read buffering for file readers that permit reading
1502 to be done through a callback.
1503
1504 The final callback gets two parameters, a I<need> value, and a I<want>
1505 value, where I<need> is the amount of data that the file library needs
1506 to read, and I<want> is the amount of space available in the buffer
1507 maintained by these functions.
1508
1509 This means if you need to read from a stream that you don't know the
1510 length of, you can return I<need> bytes, taking the performance hit of
1511 possibly expensive callbacks (eg. back to perl code), or if you are
1512 reading from a stream where it doesn't matter if some data is lost, or
1513 if the total length of the stream is known, you can return I<want>
1514 bytes.
1515
1516 =cut 
1517 */
1518
1519 int
1520 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1521   int total;
1522
1523   if (length < gci->length - gci->cpos) {
1524     /* simplest case */
1525     memcpy(buf, gci->buffer+gci->cpos, length);
1526     gci->cpos += length;
1527     return length;
1528   }
1529   
1530   total = 0;
1531   memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
1532   total  += gci->length - gci->cpos;
1533   length -= gci->length - gci->cpos;
1534   buf    += gci->length - gci->cpos;
1535   if (length < (int)sizeof(gci->buffer)) {
1536     int did_read;
1537     int copy_size;
1538     while (length
1539            && (did_read = (gci->cb)(gci->userdata, gci->buffer, length, 
1540                                     sizeof(gci->buffer))) > 0) {
1541       gci->cpos = 0;
1542       gci->length = did_read;
1543
1544       copy_size = i_min(length, gci->length);
1545       memcpy(buf, gci->buffer, copy_size);
1546       gci->cpos += copy_size;
1547       buf += copy_size;
1548       total += copy_size;
1549       length -= copy_size;
1550     }
1551   }
1552   else {
1553     /* just read the rest - too big for our buffer*/
1554     int did_read;
1555     while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1556       length -= did_read;
1557       total += did_read;
1558       buf += did_read;
1559     }
1560   }
1561   return total;
1562 }
1563
1564 /*
1565 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1566
1567 For use by callback file readers to initialize the reader buffer.
1568
1569 Allocates, initializes and returns the reader buffer.
1570
1571 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1572
1573 =cut
1574 */
1575 i_gen_read_data *
1576 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1577   i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1578   self->cb = cb;
1579   self->userdata = userdata;
1580   self->length = 0;
1581   self->cpos = 0;
1582
1583   return self;
1584 }
1585
1586 /*
1587 =item i_free_gen_read_data(i_gen_read_data *)
1588
1589 Cleans up.
1590
1591 =cut
1592 */
1593 void i_free_gen_read_data(i_gen_read_data *self) {
1594   myfree(self);
1595 }
1596
1597 /*
1598 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1599
1600 Performs write buffering for a callback based file writer.
1601
1602 Failures are considered fatal, if a write fails then data will be
1603 dropped.
1604
1605 =cut
1606 */
1607 int 
1608 i_gen_writer(
1609 i_gen_write_data *self, 
1610 char const *data, 
1611 int size)
1612 {
1613   if (self->filledto && self->filledto+size > self->maxlength) {
1614     if (self->cb(self->userdata, self->buffer, self->filledto)) {
1615       self->filledto = 0;
1616     }
1617     else {
1618       self->filledto = 0;
1619       return 0;
1620     }
1621   }
1622   if (self->filledto+size <= self->maxlength) {
1623     /* just save it */
1624     memcpy(self->buffer+self->filledto, data, size);
1625     self->filledto += size;
1626     return 1;
1627   }
1628   /* doesn't fit - hand it off */
1629   return self->cb(self->userdata, data, size);
1630 }
1631
1632 /*
1633 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
1634
1635 Allocates and initializes the data structure used by i_gen_writer.
1636
1637 This should be released with L<image.c/i_free_gen_write_data>
1638
1639 =cut
1640 */
1641 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, 
1642                                        char *userdata, int max_length)
1643 {
1644   i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
1645   self->cb = cb;
1646   self->userdata = userdata;
1647   self->maxlength = i_min(max_length, sizeof(self->buffer));
1648   if (self->maxlength < 0)
1649     self->maxlength = sizeof(self->buffer);
1650   self->filledto = 0;
1651
1652   return self;
1653 }
1654
1655 /*
1656 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
1657
1658 Cleans up the write buffer.
1659
1660 Will flush any left-over data if I<flush> is non-zero.
1661
1662 Returns non-zero if flush is zero or if info->cb() returns non-zero.
1663
1664 Return zero only if flush is non-zero and info->cb() returns zero.
1665 ie. if it fails.
1666
1667 =cut
1668 */
1669
1670 int i_free_gen_write_data(i_gen_write_data *info, int flush)
1671 {
1672   int result = !flush || 
1673     info->filledto == 0 ||
1674     info->cb(info->userdata, info->buffer, info->filledto);
1675   myfree(info);
1676
1677   return result;
1678 }
1679
1680 struct magic_entry {
1681   unsigned char *magic;
1682   size_t magic_size;
1683   char *name;
1684   unsigned char *mask;  
1685 };
1686
1687 static int
1688 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
1689   if (length < magic->magic_size)
1690     return 0;
1691   if (magic->mask) {
1692     int i;
1693     unsigned char *bufp = buffer, 
1694       *maskp = magic->mask, 
1695       *magicp = magic->magic;
1696
1697     for (i = 0; i < magic->magic_size; ++i) {
1698       int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1699       ++maskp;
1700
1701       if ((*bufp++ & mask) != (*magicp++ & mask)) 
1702         return 0;
1703     }
1704
1705     return 1;
1706   }
1707   else {
1708     return !memcmp(magic->magic, buffer, magic->magic_size);
1709   }
1710 }
1711
1712 /*
1713 =item i_test_format_probe(io_glue *data, int length)
1714
1715 Check the beginning of the supplied file for a 'magic number'
1716
1717 =cut
1718 */
1719
1720 #define FORMAT_ENTRY(magic, type) \
1721   { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1722 #define FORMAT_ENTRY2(magic, type, mask) \
1723   { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1724
1725 const char *
1726 i_test_format_probe(io_glue *data, int length) {
1727   static const struct magic_entry formats[] = {
1728     FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1729     FORMAT_ENTRY("GIF87a", "gif"),
1730     FORMAT_ENTRY("GIF89a", "gif"),
1731     FORMAT_ENTRY("MM\0*", "tiff"),
1732     FORMAT_ENTRY("II*\0", "tiff"),
1733     FORMAT_ENTRY("BM", "bmp"),
1734     FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1735     FORMAT_ENTRY("P1", "pnm"),
1736     FORMAT_ENTRY("P2", "pnm"),
1737     FORMAT_ENTRY("P3", "pnm"),
1738     FORMAT_ENTRY("P4", "pnm"),
1739     FORMAT_ENTRY("P5", "pnm"),
1740     FORMAT_ENTRY("P6", "pnm"),
1741     FORMAT_ENTRY("/* XPM", "xpm"),
1742     FORMAT_ENTRY("\x8aMNG", "mng"),
1743     FORMAT_ENTRY("\x8aJNG", "jng"),
1744     /* SGI RGB - with various possible parameters to avoid false positives
1745        on similar files 
1746        values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1747     */
1748     FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1749     FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1750     FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1751     FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1752     
1753     FORMAT_ENTRY2("FORM    ILBM", "ilbm", "xxxx    xxxx"),
1754
1755     /* different versions of PCX format 
1756        http://www.fileformat.info/format/pcx/
1757     */
1758     FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1759     FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1760     FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1761     FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1762     FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1763
1764     /* FITS - http://fits.gsfc.nasa.gov/ */
1765     FORMAT_ENTRY("SIMPLE  =", "fits"),
1766
1767     /* PSD - Photoshop */
1768     FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1769     
1770     /* EPS - Encapsulated Postscript */
1771     /* only reading 18 chars, so we don't include the F in EPSF */
1772     FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1773
1774     /* Utah RLE */
1775     FORMAT_ENTRY("\x52\xCC", "utah"),
1776
1777     /* GZIP compressed, only matching deflate for now */
1778     FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1779
1780     /* bzip2 compressed */
1781     FORMAT_ENTRY("BZh", "bzip2"),
1782
1783     /* WEBP
1784        http://code.google.com/speed/webp/docs/riff_container.html */
1785     FORMAT_ENTRY2("RIFF    WEBP", "webp", "xxxx    xxxx"),
1786
1787     /* JPEG 2000 
1788        This might match a little loosely */
1789     FORMAT_ENTRY("\x00\x00\x00\x0CjP  \x0D\x0A\x87\x0A", "jp2"),
1790   };
1791   static const struct magic_entry more_formats[] = {
1792     /* these were originally both listed as ico, but cur files can
1793        include hotspot information */
1794     FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1795     FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1796     FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07", 
1797                   "xwd", "    xxxx"), /* X Windows Dump */
1798   };
1799
1800   unsigned int i;
1801   unsigned char head[18];
1802   ssize_t rc;
1803
1804   io_glue_commit_types(data);
1805   rc = data->readcb(data, head, 18);
1806   if (rc == -1) return NULL;
1807   data->seekcb(data, -rc, SEEK_CUR);
1808
1809   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
1810     struct magic_entry const *entry = formats + i;
1811
1812     if (test_magic(head, rc, entry)) 
1813       return entry->name;
1814   }
1815
1816   if ((rc == 18) &&
1817       tga_header_verify(head))
1818     return "tga";
1819
1820   for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) { 
1821     struct magic_entry const *entry = more_formats + i;
1822
1823     if (test_magic(head, rc, entry)) 
1824       return entry->name;
1825   }
1826
1827   return NULL;
1828 }
1829
1830 /*
1831 =item i_img_is_monochrome(img, &zero_is_white)
1832
1833 =category Image Information
1834
1835 Tests an image to check it meets our monochrome tests.
1836
1837 The idea is that a file writer can use this to test where it should
1838 write the image in whatever bi-level format it uses, eg. C<pbm> for
1839 C<pnm>.
1840
1841 For performance of encoders we require monochrome images:
1842
1843 =over
1844
1845 =item *
1846
1847 be paletted
1848
1849 =item *
1850
1851 have a palette of two colors, containing only C<(0,0,0)> and
1852 C<(255,255,255)> in either order.
1853
1854 =back
1855
1856 C<zero_is_white> is set to non-zero if the first palette entry is white.
1857
1858 =cut
1859 */
1860
1861 int
1862 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1863   if (im->type == i_palette_type
1864       && i_colorcount(im) == 2) {
1865     i_color colors[2];
1866     i_getcolors(im, 0, colors, 2);
1867     if (im->channels == 3) {
1868       if (colors[0].rgb.r == 255 && 
1869           colors[0].rgb.g == 255 &&
1870           colors[0].rgb.b == 255 &&
1871           colors[1].rgb.r == 0 &&
1872           colors[1].rgb.g == 0 &&
1873           colors[1].rgb.b == 0) {
1874         *zero_is_white = 1;
1875         return 1;
1876       }
1877       else if (colors[0].rgb.r == 0 && 
1878                colors[0].rgb.g == 0 &&
1879                colors[0].rgb.b == 0 &&
1880                colors[1].rgb.r == 255 &&
1881                colors[1].rgb.g == 255 &&
1882                colors[1].rgb.b == 255) {
1883         *zero_is_white = 0;
1884         return 1;
1885       }
1886     }
1887     else if (im->channels == 1) {
1888       if (colors[0].channel[0] == 255 &&
1889           colors[1].channel[0] == 0) {
1890         *zero_is_white = 1;
1891         return 1;
1892       }
1893       else if (colors[0].channel[0] == 0 &&
1894                colors[1].channel[0] == 255) {
1895         *zero_is_white = 0;
1896         return 1;         
1897       }
1898     }
1899   }
1900
1901   *zero_is_white = 0;
1902   return 0;
1903 }
1904
1905 /*
1906 =item i_get_file_background(im, &bg)
1907
1908 =category Files
1909
1910 Retrieve the file write background color tag from the image.
1911
1912 If not present, returns black.
1913
1914 =cut
1915 */
1916
1917 void
1918 i_get_file_background(i_img *im, i_color *bg) {
1919   if (!i_tags_get_color(&im->tags, "i_background", 0, bg)) {
1920     /* black default */
1921     bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1922   }
1923   /* always full alpha */
1924   bg->channel[3] = 255;
1925 }
1926
1927 /*
1928 =item i_get_file_backgroundf(im, &bg)
1929
1930 =category Files
1931
1932 Retrieve the file write background color tag from the image as a
1933 floating point color.
1934
1935 Implemented in terms of i_get_file_background().
1936
1937 If not present, returns black.
1938
1939 =cut
1940 */
1941
1942 void
1943 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1944   i_color bg;
1945
1946   i_get_file_background(im, &bg);
1947   fbg->rgba.r = Sample8ToF(bg.rgba.r);
1948   fbg->rgba.g = Sample8ToF(bg.rgba.g);
1949   fbg->rgba.b = Sample8ToF(bg.rgba.b);
1950   fbg->rgba.a = 1.0;
1951 }
1952
1953 /*
1954 =back
1955
1956 =head1 AUTHOR
1957
1958 Arnar M. Hrafnkelsson <addi@umich.edu>
1959
1960 Tony Cook <tonyc@cpan.org>
1961
1962 =head1 SEE ALSO
1963
1964 L<Imager>, L<gif.c>
1965
1966 =cut
1967 */