Gabriel Vasseur's patch, corrected just enough for it to compile.
[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 static void fake(void) { ceil(1); }
41
42 static int i_ppix_d(i_img *im, int x, int y, const i_color *val);
43 static int i_gpix_d(i_img *im, int x, int y, i_color *val);
44 static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
45 static int i_plin_d(i_img *im, int l, int r, int y, const i_color *vals);
46 static int i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val);
47 static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
48 static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
49 static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals);
50 static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
51 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
52 /*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
53   static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
54
55 /* 
56 =item ICL_new_internal(r, g, b, a)
57
58 Return a new color object with values passed to it.
59
60    r - red   component (range: 0 - 255)
61    g - green component (range: 0 - 255)
62    b - blue  component (range: 0 - 255)
63    a - alpha component (range: 0 - 255)
64
65 =cut
66 */
67
68 i_color *
69 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
70   i_color *cl = NULL;
71
72   mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
73
74   if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
75   cl->rgba.r = r;
76   cl->rgba.g = g;
77   cl->rgba.b = b;
78   cl->rgba.a = a;
79   mm_log((1,"(%p) <- ICL_new_internal\n",cl));
80   return cl;
81 }
82
83
84 /*
85 =item ICL_set_internal(cl, r, g, b, a)
86
87  Overwrite a color with new values.
88
89    cl - pointer to color object
90    r - red   component (range: 0 - 255)
91    g - green component (range: 0 - 255)
92    b - blue  component (range: 0 - 255)
93    a - alpha component (range: 0 - 255)
94
95 =cut
96 */
97
98 i_color *
99 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
100   mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
101   if (cl == NULL)
102     if ( (cl=mymalloc(sizeof(i_color))) == NULL)
103       i_fatal(2,"malloc() error\n");
104   cl->rgba.r=r;
105   cl->rgba.g=g;
106   cl->rgba.b=b;
107   cl->rgba.a=a;
108   mm_log((1,"(%p) <- ICL_set_internal\n",cl));
109   return cl;
110 }
111
112
113 /* 
114 =item ICL_add(dst, src, ch)
115
116 Add src to dst inplace - dst is modified.
117
118    dst - pointer to destination color object
119    src - pointer to color object that is added
120    ch - number of channels
121
122 =cut
123 */
124
125 void
126 ICL_add(i_color *dst,i_color *src,int ch) {
127   int tmp,i;
128   for(i=0;i<ch;i++) {
129     tmp=dst->channel[i]+src->channel[i];
130     dst->channel[i]= tmp>255 ? 255:tmp;
131   }
132 }
133
134 /* 
135 =item ICL_info(cl)
136
137 Dump color information to log - strictly for debugging.
138
139    cl - pointer to color object
140
141 =cut
142 */
143
144 void
145 ICL_info(i_color const *cl) {
146   mm_log((1,"i_color_info(cl* %p)\n",cl));
147   mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
148 }
149
150 /* 
151 =item ICL_DESTROY
152
153 Destroy ancillary data for Color object.
154
155    cl - pointer to color object
156
157 =cut
158 */
159
160 void
161 ICL_DESTROY(i_color *cl) {
162   mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
163   myfree(cl);
164 }
165
166 /*
167 =item i_fcolor_new(double r, double g, double b, double a)
168
169 =cut
170 */
171 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
172   i_fcolor *cl = NULL;
173
174   mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
175
176   if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
177   cl->rgba.r = r;
178   cl->rgba.g = g;
179   cl->rgba.b = b;
180   cl->rgba.a = a;
181   mm_log((1,"(%p) <- i_fcolor_new\n",cl));
182
183   return cl;
184 }
185
186 /*
187 =item i_fcolor_destroy(i_fcolor *cl) 
188
189 =cut
190 */
191 void i_fcolor_destroy(i_fcolor *cl) {
192   myfree(cl);
193 }
194
195 /*
196 =item IIM_base_8bit_direct (static)
197
198 A static i_img object used to initialize direct 8-bit per sample images.
199
200 =cut
201 */
202 static i_img IIM_base_8bit_direct =
203 {
204   0, /* channels set */
205   0, 0, 0, /* xsize, ysize, bytes */
206   ~0U, /* ch_mask */
207   i_8_bits, /* bits */
208   i_direct_type, /* type */
209   0, /* virtual */
210   NULL, /* idata */
211   { 0, 0, NULL }, /* tags */
212   NULL, /* ext_data */
213
214   i_ppix_d, /* i_f_ppix */
215   i_ppixf_d, /* i_f_ppixf */
216   i_plin_d, /* i_f_plin */
217   i_plinf_d, /* i_f_plinf */
218   i_gpix_d, /* i_f_gpix */
219   i_gpixf_d, /* i_f_gpixf */
220   i_glin_d, /* i_f_glin */
221   i_glinf_d, /* i_f_glinf */
222   i_gsamp_d, /* i_f_gsamp */
223   i_gsampf_d, /* i_f_gsampf */
224
225   NULL, /* i_f_gpal */
226   NULL, /* i_f_ppal */
227   NULL, /* i_f_addcolors */
228   NULL, /* i_f_getcolors */
229   NULL, /* i_f_colorcount */
230   NULL, /* i_f_maxcolors */
231   NULL, /* i_f_findcolor */
232   NULL, /* i_f_setcolors */
233
234   NULL, /* i_f_destroy */
235 };
236
237 /*static void set_8bit_direct(i_img *im) {
238   im->i_f_ppix = i_ppix_d;
239   im->i_f_ppixf = i_ppixf_d;
240   im->i_f_plin = i_plin_d;
241   im->i_f_plinf = i_plinf_d;
242   im->i_f_gpix = i_gpix_d;
243   im->i_f_gpixf = i_gpixf_d;
244   im->i_f_glin = i_glin_d;
245   im->i_f_glinf = i_glinf_d;
246   im->i_f_gpal = NULL;
247   im->i_f_ppal = NULL;
248   im->i_f_addcolor = NULL;
249   im->i_f_getcolor = NULL;
250   im->i_f_colorcount = NULL;
251   im->i_f_findcolor = NULL;
252   }*/
253
254 /*
255 =item IIM_new(x, y, ch)
256
257 =item i_img_8_new(x, y, ch)
258
259 =category Image creation
260
261 Creates a new image object I<x> pixels wide, and I<y> pixels high with
262 I<ch> channels.
263
264 =cut
265 */
266
267
268 i_img *
269 IIM_new(int x,int y,int ch) {
270   i_img *im;
271   mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
272
273   im=i_img_empty_ch(NULL,x,y,ch);
274   
275   mm_log((1,"(%p) <- IIM_new\n",im));
276   return im;
277 }
278
279
280 void
281 IIM_DESTROY(i_img *im) {
282   mm_log((1,"IIM_DESTROY(im* %p)\n",im));
283   i_img_destroy(im);
284   /*   myfree(cl); */
285 }
286
287 /* 
288 =item i_img_new()
289
290 Create new image reference - notice that this isn't an object yet and
291 this should be fixed asap.
292
293 =cut
294 */
295
296
297 i_img *
298 i_img_new() {
299   i_img *im;
300   
301   mm_log((1,"i_img_struct()\n"));
302   if ( (im=mymalloc(sizeof(i_img))) == NULL)
303     i_fatal(2,"malloc() error\n");
304   
305   *im = IIM_base_8bit_direct;
306   im->xsize=0;
307   im->ysize=0;
308   im->channels=3;
309   im->ch_mask=MAXINT;
310   im->bytes=0;
311   im->idata=NULL;
312   
313   mm_log((1,"(%p) <- i_img_struct\n",im));
314   return im;
315 }
316
317 /* 
318 =item i_img_empty(im, x, y)
319
320 Re-new image reference (assumes 3 channels)
321
322    im - Image pointer
323    x - xsize of destination image
324    y - ysize of destination image
325
326 **FIXME** what happens if a live image is passed in here?
327
328 Should this just call i_img_empty_ch()?
329
330 =cut
331 */
332
333 i_img *
334 i_img_empty(i_img *im,int x,int y) {
335   mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
336   return i_img_empty_ch(im, x, y, 3);
337 }
338
339 /* 
340 =item i_img_empty_ch(im, x, y, ch)
341
342 Re-new image reference 
343
344    im - Image pointer
345    x  - xsize of destination image
346    y  - ysize of destination image
347    ch - number of channels
348
349 =cut
350 */
351
352 i_img *
353 i_img_empty_ch(i_img *im,int x,int y,int ch) {
354   int bytes;
355
356   mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
357
358   if (x < 1 || y < 1) {
359     i_push_error(0, "Image sizes must be positive");
360     return NULL;
361   }
362   if (ch < 1 || ch > MAXCHANNELS) {
363     i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
364     return NULL;
365   }
366   /* check this multiplication doesn't overflow */
367   bytes = x*y*ch;
368   if (bytes / y / ch != x) {
369     i_push_errorf(0, "integer overflow calculating image allocation");
370     return NULL;
371   }
372
373   if (im == NULL)
374     if ( (im=mymalloc(sizeof(i_img))) == NULL)
375       i_fatal(2,"malloc() error\n");
376
377   memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
378   i_tags_new(&im->tags);
379   im->xsize    = x;
380   im->ysize    = y;
381   im->channels = ch;
382   im->ch_mask  = MAXINT;
383   im->bytes=bytes;
384   if ( (im->idata=mymalloc(im->bytes)) == NULL) 
385     i_fatal(2,"malloc() error\n"); 
386   memset(im->idata,0,(size_t)im->bytes);
387   
388   im->ext_data = NULL;
389   
390   mm_log((1,"(%p) <- i_img_empty_ch\n",im));
391   return im;
392 }
393
394 /* 
395 =item i_img_exorcise(im)
396
397 Free image data.
398
399    im - Image pointer
400
401 =cut
402 */
403
404 void
405 i_img_exorcise(i_img *im) {
406   mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
407   i_tags_destroy(&im->tags);
408   if (im->i_f_destroy)
409     (im->i_f_destroy)(im);
410   if (im->idata != NULL) { myfree(im->idata); }
411   im->idata    = NULL;
412   im->xsize    = 0;
413   im->ysize    = 0;
414   im->channels = 0;
415
416   im->i_f_ppix=i_ppix_d;
417   im->i_f_gpix=i_gpix_d;
418   im->i_f_plin=i_plin_d;
419   im->i_f_glin=i_glin_d;
420   im->ext_data=NULL;
421 }
422
423 /* 
424 =item i_img_destroy(im)
425
426 =category Image
427
428 Destroy image and free data via exorcise.
429
430    im - Image pointer
431
432 =cut
433 */
434
435 void
436 i_img_destroy(i_img *im) {
437   mm_log((1,"i_img_destroy(im %p)\n",im));
438   i_img_exorcise(im);
439   if (im) { myfree(im); }
440 }
441
442 /* 
443 =item i_img_info(im, info)
444
445 =category Image
446
447 Return image information
448
449    im - Image pointer
450    info - pointer to array to return data
451
452 info is an array of 4 integers with the following values:
453
454  info[0] - width
455  info[1] - height
456  info[2] - channels
457  info[3] - channel mask
458
459 =cut
460 */
461
462
463 void
464 i_img_info(i_img *im,int *info) {
465   mm_log((1,"i_img_info(im 0x%x)\n",im));
466   if (im != NULL) {
467     mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
468     mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
469     info[0] = im->xsize;
470     info[1] = im->ysize;
471     info[2] = im->channels;
472     info[3] = im->ch_mask;
473   } else {
474     info[0] = 0;
475     info[1] = 0;
476     info[2] = 0;
477     info[3] = 0;
478   }
479 }
480
481 /*
482 =item i_img_setmask(im, ch_mask)
483
484 =synopsis // only channel 0 writeable 
485 =synopsis i_img_setmask(img, 0x01);
486
487 Set the image channel mask for I<im> to I<ch_mask>.
488
489 =cut
490 */
491 void
492 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
493
494
495 /*
496 =item i_img_getmask(im)
497
498 =synopsis mask = i_img_getmask(img);
499
500 Get the image channel mask for I<im>.
501
502 =cut
503 */
504 int
505 i_img_getmask(i_img *im) { return im->ch_mask; }
506
507 /*
508 =item i_img_getchannels(im)
509
510 =synopsis channels = i_img_getchannels(img);
511
512 Get the number of channels in I<im>.
513
514 =cut
515 */
516 int
517 i_img_getchannels(i_img *im) { return im->channels; }
518
519 /*
520 =item i_img_get_width(im)
521
522 =synopsis width = i_img_get_width(im);
523
524 Returns the width in pixels of the image.
525
526 =cut
527 */
528 i_img_dim
529 i_img_get_width(i_img *im) {
530   return im->xsize;
531 }
532
533 /*
534 =item i_img_get_height(im)
535
536 =synopsis height = i_img_get_height(im);
537
538 Returns the height in pixels of the image.
539
540 =cut
541 */
542 i_img_dim
543 i_img_get_height(i_img *im) {
544   return im->ysize;
545 }
546
547 /*
548 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
549
550 =category Image
551
552 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
553 (tx,ty) specifies the upper left corner for the target image.
554 pass NULL in trans for non transparent i_colors.
555
556 =cut
557 */
558
559 void
560 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,const i_color *trans) {
561   i_color pv;
562   int x,y,t,ttx,tty,tt,ch;
563
564   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",
565           im, src, x1, y1, x2, y2, tx, ty, trans));
566   
567   if (x2<x1) { t=x1; x1=x2; x2=t; }
568   if (y2<y1) { t=y1; y1=y2; y2=t; }
569
570   ttx=tx;
571   for(x=x1;x<x2;x++)
572     {
573       tty=ty;
574       for(y=y1;y<y2;y++)
575         {
576           i_gpix(src,x,y,&pv);
577           if ( trans != NULL)
578           {
579             tt=0;
580             for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
581             if (tt) i_ppix(im,ttx,tty,&pv);
582           } else i_ppix(im,ttx,tty,&pv);
583           tty++;
584         }
585       ttx++;
586     }
587 }
588
589 /*
590 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
591
592 =category Image
593
594 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
595 a rectangle the same size with it's top-left corner at (tx,ty) in the
596 destination image.
597
598 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
599
600 =cut
601 */
602
603 void
604 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
605   int x, y, t, ttx, tty;
606   
607   if (x2<x1) { t=x1; x1=x2; x2=t; }
608   if (y2<y1) { t=y1; y1=y2; y2=t; }
609   if (tx < 0) {
610     /* adjust everything equally */
611     x1 += -tx;
612     x2 += -tx;
613     tx = 0;
614   }
615   if (ty < 0) {
616     y1 += -ty;
617     y2 += -ty;
618     ty = 0;
619   }
620   if (x1 >= src->xsize || y1 >= src->ysize)
621     return; /* nothing to do */
622   if (x2 > src->xsize)
623     x2 = src->xsize;
624   if (y2 > src->ysize)
625     y2 = src->ysize;
626   if (x1 == x2 || y1 == y2)
627     return; /* nothing to do */
628
629   mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
630           im, src, x1, y1, x2, y2, tx, ty));
631   
632   if (im->bits == i_8_bits) {
633     i_color *row = mymalloc(sizeof(i_color) * (x2-x1));
634     tty = ty;
635     for(y=y1; y<y2; y++) {
636       ttx = tx;
637       i_glin(src, x1, x2, y, row);
638       i_plin(im, tx, tx+x2-x1, tty, row);
639       tty++;
640     }
641     myfree(row);
642   }
643   else {
644     i_fcolor pv;
645     tty = ty;
646     for(y=y1; y<y2; y++) {
647       ttx = tx;
648       for(x=x1; x<x2; x++) {
649         i_gpixf(src, x,   y,   &pv);
650         i_ppixf(im,  ttx, tty, &pv);
651         ttx++;
652       }
653       tty++;
654     }
655   }
656 }
657
658 /*
659 =item i_copy(src)
660
661 =category Image
662
663 Creates a new image that is a copy of src.
664
665 Tags are not copied, only the image data.
666
667 Returns: i_img *
668
669 =cut
670 */
671
672 i_img *
673 i_copy(i_img *src) {
674   int y, y1, x1;
675   i_img *im = i_sametype(src, src->xsize, src->ysize);
676
677   mm_log((1,"i_copy(src %p)\n", src));
678
679   if (!im)
680     return NULL;
681
682   x1 = src->xsize;
683   y1 = src->ysize;
684   if (src->type == i_direct_type) {
685     if (src->bits == i_8_bits) {
686       i_color *pv;
687       pv = mymalloc(sizeof(i_color) * x1);
688       
689       for (y = 0; y < y1; ++y) {
690         i_glin(src, 0, x1, y, pv);
691         i_plin(im, 0, x1, y, pv);
692       }
693       myfree(pv);
694     }
695     else {
696       i_fcolor *pv;
697
698       pv = mymalloc(sizeof(i_fcolor) * x1);
699       for (y = 0; y < y1; ++y) {
700         i_glinf(src, 0, x1, y, pv);
701         i_plinf(im, 0, x1, y, pv);
702       }
703       myfree(pv);
704     }
705   }
706   else {
707     i_color temp;
708     int index;
709     int count;
710     i_palidx *vals;
711
712     /* paletted image */
713     i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
714     /* copy across the palette */
715     count = i_colorcount(src);
716     for (index = 0; index < count; ++index) {
717       i_getcolors(src, index, &temp, 1);
718       i_addcolors(im, &temp, 1);
719     }
720
721     vals = mymalloc(sizeof(i_palidx) * x1);
722     for (y = 0; y < y1; ++y) {
723       i_gpal(src, 0, x1, y, vals);
724       i_ppal(im, 0, x1, y, vals);
725     }
726     myfree(vals);
727   }
728
729   return im;
730 }
731
732
733 /*
734 =item i_flipxy(im, axis)
735
736 Flips the image inplace around the axis specified.
737 Returns 0 if parameters are invalid.
738
739    im   - Image pointer
740    axis - 0 = x, 1 = y, 2 = both
741
742 =cut
743 */
744
745 undef_int
746 i_flipxy(i_img *im, int direction) {
747   int x, x2, y, y2, xm, ym;
748   int xs = im->xsize;
749   int ys = im->ysize;
750   
751   mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
752
753   if (!im) return 0;
754
755   switch (direction) {
756   case XAXIS: /* Horizontal flip */
757     xm = xs/2;
758     ym = ys;
759     for(y=0; y<ym; y++) {
760       x2 = xs-1;
761       for(x=0; x<xm; x++) {
762         i_color val1, val2;
763         i_gpix(im, x,  y,  &val1);
764         i_gpix(im, x2, y,  &val2);
765         i_ppix(im, x,  y,  &val2);
766         i_ppix(im, x2, y,  &val1);
767         x2--;
768       }
769     }
770     break;
771   case YAXIS: /* Vertical flip */
772     xm = xs;
773     ym = ys/2;
774     y2 = ys-1;
775     for(y=0; y<ym; y++) {
776       for(x=0; x<xm; x++) {
777         i_color val1, val2;
778         i_gpix(im, x,  y,  &val1);
779         i_gpix(im, x,  y2, &val2);
780         i_ppix(im, x,  y,  &val2);
781         i_ppix(im, x,  y2, &val1);
782       }
783       y2--;
784     }
785     break;
786   case XYAXIS: /* Horizontal and Vertical flip */
787     xm = xs/2;
788     ym = ys/2;
789     y2 = ys-1;
790     for(y=0; y<ym; y++) {
791       x2 = xs-1;
792       for(x=0; x<xm; x++) {
793         i_color val1, val2;
794         i_gpix(im, x,  y,  &val1);
795         i_gpix(im, x2, y2, &val2);
796         i_ppix(im, x,  y,  &val2);
797         i_ppix(im, x2, y2, &val1);
798
799         i_gpix(im, x2, y,  &val1);
800         i_gpix(im, x,  y2, &val2);
801         i_ppix(im, x2, y,  &val2);
802         i_ppix(im, x,  y2, &val1);
803         x2--;
804       }
805       y2--;
806     }
807     if (xm*2 != xs) { /* odd number of column */
808       mm_log((1, "i_flipxy: odd number of columns\n"));
809       x = xm;
810       y2 = ys-1;
811       for(y=0; y<ym; y++) {
812         i_color val1, val2;
813         i_gpix(im, x,  y,  &val1);
814         i_gpix(im, x,  y2, &val2);
815         i_ppix(im, x,  y,  &val2);
816         i_ppix(im, x,  y2, &val1);
817         y2--;
818       }
819     }
820     if (ym*2 != ys) { /* odd number of rows */
821       mm_log((1, "i_flipxy: odd number of rows\n"));
822       y = ym;
823       x2 = xs-1;
824       for(x=0; x<xm; x++) {
825         i_color val1, val2;
826         i_gpix(im, x,  y,  &val1);
827         i_gpix(im, x2, y,  &val2);
828         i_ppix(im, x,  y,  &val2);
829         i_ppix(im, x2, y,  &val1);
830         x2--;
831       }
832     }
833     break;
834   default:
835     mm_log((1, "i_flipxy: direction is invalid\n" ));
836     return 0;
837   }
838   return 1;
839 }
840
841
842
843
844
845 static
846 float
847 Lanczos(float x) {
848   float PIx, PIx2;
849   
850   PIx = PI * x;
851   PIx2 = PIx / 2.0;
852   
853   if ((x >= 2.0) || (x <= -2.0)) return (0.0);
854   else if (x == 0.0) return (1.0);
855   else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
856 }
857
858
859 /*
860 =item i_scaleaxis(im, value, axis)
861
862 Returns a new image object which is I<im> scaled by I<value> along
863 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
864
865 =cut
866 */
867
868 i_img*
869 i_scaleaxis(i_img *im, float Value, int Axis) {
870   int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
871   int LanczosWidthFactor;
872   float *l0, *l1, OldLocation;
873   int T; 
874   float t;
875   float F, PictureValue[MAXCHANNELS];
876   short psave;
877   i_color val,val1,val2;
878   i_img *new_img;
879
880   mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
881
882
883   if (Axis == XAXIS) {
884     hsize = (int)(0.5 + im->xsize * Value);
885     if (hsize < 1) {
886       hsize = 1;
887       Value = 1.0 / im->xsize;
888     }
889     vsize = im->ysize;
890     
891     jEnd = hsize;
892     iEnd = vsize;
893   } else {
894     hsize = im->xsize;
895     vsize = (int)(0.5 + im->ysize * Value);
896
897     if (vsize < 1) {
898       vsize = 1;
899       Value = 1.0 / im->ysize;
900     }
901
902     jEnd = vsize;
903     iEnd = hsize;
904   }
905   
906   new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
907   
908   /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
909   LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value); 
910   lMax = LanczosWidthFactor << 1;
911   
912   l0 = mymalloc(lMax * sizeof(float));
913   l1 = mymalloc(lMax * sizeof(float));
914   
915   for (j=0; j<jEnd; j++) {
916     OldLocation = ((float) j) / Value;
917     T = (int) (OldLocation);
918     F = OldLocation - (float) T;
919     
920     for (l = 0; l<lMax; l++) {
921       l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
922       l1[l]        = Lanczos(((float) (l+1)      - F) / (float) LanczosWidthFactor);
923     }
924     
925     /* Make sure filter is normalized */
926     t = 0.0;
927     for(l=0; l<lMax; l++) {
928       t+=l0[l];
929       t+=l1[l];
930     }
931     t /= (float)LanczosWidthFactor;
932     
933     for(l=0; l<lMax; l++) {
934       l0[l] /= t;
935       l1[l] /= t;
936     }
937
938     if (Axis == XAXIS) {
939       
940       for (i=0; i<iEnd; i++) {
941         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
942         for (l=0; l<lMax; l++) {
943           int mx = T-lMax+l+1;
944           int Mx = T+l+1;
945           mx = (mx < 0) ? 0 : mx;
946           Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
947           
948           i_gpix(im, Mx, i, &val1);
949           i_gpix(im, mx, i, &val2);
950           
951           for (k=0; k<im->channels; k++) {
952             PictureValue[k] += l1[l]        * val1.channel[k];
953             PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
954           }
955         }
956         for(k=0;k<im->channels;k++) {
957           psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
958           val.channel[k]=minmax(0,255,psave);
959         }
960         i_ppix(new_img, j, i, &val);
961       }
962       
963     } else {
964       
965       for (i=0; i<iEnd; i++) {
966         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
967         for (l=0; l < lMax; l++) {
968           int mx = T-lMax+l+1;
969           int Mx = T+l+1;
970           mx = (mx < 0) ? 0 : mx;
971           Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
972
973           i_gpix(im, i, Mx, &val1);
974           i_gpix(im, i, mx, &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]; 
978           }
979         }
980         for (k=0; k<im->channels; k++) {
981           psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
982           val.channel[k] = minmax(0, 255, psave);
983         }
984         i_ppix(new_img, i, j, &val);
985       }
986       
987     }
988   }
989   myfree(l0);
990   myfree(l1);
991
992   mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
993
994   return new_img;
995 }
996
997
998 /* 
999 =item i_scale_nn(im, scx, scy)
1000
1001 Scale by using nearest neighbor 
1002 Both axes scaled at the same time since 
1003 nothing is gained by doing it in two steps 
1004
1005 =cut
1006 */
1007
1008
1009 i_img*
1010 i_scale_nn(i_img *im, float scx, float scy) {
1011
1012   int nxsize,nysize,nx,ny;
1013   i_img *new_img;
1014   i_color val;
1015
1016   mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1017
1018   nxsize = (int) ((float) im->xsize * scx);
1019   if (nxsize < 1) {
1020     nxsize = 1;
1021     scx = 1 / im->xsize;
1022   }
1023   nysize = (int) ((float) im->ysize * scy);
1024   if (nysize < 1) {
1025     nysize = 1;
1026     scy = 1 / im->ysize;
1027   }
1028     
1029   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1030   
1031   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1032     i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1033     i_ppix(new_img,nx,ny,&val);
1034   }
1035
1036   mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1037
1038   return new_img;
1039 }
1040
1041 /*
1042 =item i_sametype(i_img *im, int xsize, int ysize)
1043
1044 =category Image creation
1045
1046 Returns an image of the same type (sample size, channels, paletted/direct).
1047
1048 For paletted images the palette is copied from the source.
1049
1050 =cut
1051 */
1052
1053 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1054   if (src->type == i_direct_type) {
1055     if (src->bits == 8) {
1056       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1057     }
1058     else if (src->bits == i_16_bits) {
1059       return i_img_16_new(xsize, ysize, src->channels);
1060     }
1061     else if (src->bits == i_double_bits) {
1062       return i_img_double_new(xsize, ysize, src->channels);
1063     }
1064     else {
1065       i_push_error(0, "Unknown image bits");
1066       return NULL;
1067     }
1068   }
1069   else {
1070     i_color col;
1071     int i;
1072
1073     i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1074     for (i = 0; i < i_colorcount(src); ++i) {
1075       i_getcolors(src, i, &col, 1);
1076       i_addcolors(targ, &col, 1);
1077     }
1078
1079     return targ;
1080   }
1081 }
1082
1083 /*
1084 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
1085
1086 =category Image creation
1087
1088 Returns an image of the same type (sample size).
1089
1090 For paletted images the equivalent direct type is returned.
1091
1092 =cut
1093 */
1094
1095 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1096   if (src->bits == 8) {
1097     return i_img_empty_ch(NULL, xsize, ysize, channels);
1098   }
1099   else if (src->bits == i_16_bits) {
1100     return i_img_16_new(xsize, ysize, channels);
1101   }
1102   else if (src->bits == i_double_bits) {
1103     return i_img_double_new(xsize, ysize, channels);
1104   }
1105   else {
1106     i_push_error(0, "Unknown image bits");
1107     return NULL;
1108   }
1109 }
1110
1111 /*
1112 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1113
1114 Spatially transforms I<im> returning a new image.
1115
1116 opx for a length of opxl and opy for a length of opy are arrays of
1117 operators that modify the x and y positions to retreive the pixel data from.
1118
1119 parm and parmlen define extra parameters that the operators may use.
1120
1121 Note that this function is largely superseded by the more flexible
1122 L<transform.c/i_transform2>.
1123
1124 Returns the new image.
1125
1126 The operators for this function are defined in L<stackmach.c>.
1127
1128 =cut
1129 */
1130 i_img*
1131 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1132   double rx,ry;
1133   int nxsize,nysize,nx,ny;
1134   i_img *new_img;
1135   i_color val;
1136   
1137   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));
1138
1139   nxsize = im->xsize;
1140   nysize = im->ysize ;
1141   
1142   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1143   /*   fprintf(stderr,"parm[2]=%f\n",parm[2]);   */
1144   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1145     /*     parm[parmlen-2]=(double)nx;
1146            parm[parmlen-1]=(double)ny; */
1147
1148     parm[0]=(double)nx;
1149     parm[1]=(double)ny;
1150
1151     /*     fprintf(stderr,"(%d,%d) ->",nx,ny);  */
1152     rx=i_op_run(opx,opxl,parm,parmlen);
1153     ry=i_op_run(opy,opyl,parm,parmlen);
1154     /*    fprintf(stderr,"(%f,%f)\n",rx,ry); */
1155     i_gpix(im,rx,ry,&val);
1156     i_ppix(new_img,nx,ny,&val);
1157   }
1158
1159   mm_log((1,"(0x%x) <- i_transform\n",new_img));
1160   return new_img;
1161 }
1162
1163 /*
1164 =item i_img_diff(im1, im2)
1165
1166 Calculates the sum of the squares of the differences between
1167 correspoding channels in two images.
1168
1169 If the images are not the same size then only the common area is 
1170 compared, hence even if images are different sizes this function 
1171 can return zero.
1172
1173 =cut
1174 */
1175 float
1176 i_img_diff(i_img *im1,i_img *im2) {
1177   int x,y,ch,xb,yb,chb;
1178   float tdiff;
1179   i_color val1,val2;
1180
1181   mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1182
1183   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1184   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1185   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1186
1187   mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1188
1189   tdiff=0;
1190   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1191     i_gpix(im1,x,y,&val1);
1192     i_gpix(im2,x,y,&val2);
1193
1194     for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1195   }
1196   mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1197   return tdiff;
1198 }
1199
1200 /* just a tiny demo of haar wavelets */
1201
1202 i_img*
1203 i_haar(i_img *im) {
1204   int mx,my;
1205   int fx,fy;
1206   int x,y;
1207   int ch,c;
1208   i_img *new_img,*new_img2;
1209   i_color val1,val2,dval1,dval2;
1210   
1211   mx=im->xsize;
1212   my=im->ysize;
1213   fx=(mx+1)/2;
1214   fy=(my+1)/2;
1215
1216
1217   /* horizontal pass */
1218   
1219   new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1220   new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1221
1222   c=0; 
1223   for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1224     i_gpix(im,x*2,y,&val1);
1225     i_gpix(im,x*2+1,y,&val2);
1226     for(ch=0;ch<im->channels;ch++) {
1227       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1228       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1229     }
1230     i_ppix(new_img,x,y,&dval1);
1231     i_ppix(new_img,x+fx,y,&dval2);
1232   }
1233
1234   for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1235     i_gpix(new_img,x,y*2,&val1);
1236     i_gpix(new_img,x,y*2+1,&val2);
1237     for(ch=0;ch<im->channels;ch++) {
1238       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1239       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1240     }
1241     i_ppix(new_img2,x,y,&dval1);
1242     i_ppix(new_img2,x,y+fy,&dval2);
1243   }
1244
1245   i_img_destroy(new_img);
1246   return new_img2;
1247 }
1248
1249 /* 
1250 =item i_count_colors(im, maxc)
1251
1252 returns number of colors or -1 
1253 to indicate that it was more than max colors
1254
1255 =cut
1256 */
1257 /* This function has been changed and is now faster. It's using
1258  * i_gsamp instead of i_gpix */
1259 int
1260 i_count_colors(i_img *im,int maxc) {
1261   struct octt *ct;
1262   int x,y;
1263   int colorcnt;
1264   int channels[3];
1265   int *samp_chans;
1266   i_sample_t * samp;
1267
1268   int xsize = im->xsize; 
1269   int ysize = im->ysize;
1270   if (im->channels >= 3) {
1271     samp_chans = NULL;
1272   }
1273   else {
1274     channels[0] = channels[1] = channels[2] = 0;
1275     samp_chans = channels;
1276   }
1277   int samp_cnt = 3 * xsize;
1278   ct = octt_new();
1279
1280   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1281
1282   colorcnt = 0;
1283   for(y = 0; y < ysize; ) {
1284       i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1285       for(x = 0; x < samp_cnt; ) {
1286           colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1287           x += 3;
1288           if (colorcnt > maxc) { 
1289               octt_delete(ct); 
1290               return -1; 
1291           }
1292       }
1293   }
1294   myfree(samp);
1295   octt_delete(ct);
1296   return colorcnt;
1297 }
1298
1299 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm 
1300  * (adapted from the Numerical Recipes)
1301  */
1302 /* Needed by get_anonymous_color_histo */
1303 void hpsort(unsigned int n, int *ra) {
1304     unsigned int i,
1305                  ir,
1306                  j,
1307                  l, 
1308                  rra;
1309
1310     if (n < 2) return;
1311     l = n >> 1;
1312     ir = n - 1;
1313     for(;;) {
1314         if (l > 0) {
1315             rra = ra[--l];
1316         }
1317         else {
1318             rra = ra[ir];
1319             ra[ir] = ra[0];
1320             if (--ir == 0) {
1321                 ra[0] = rra;
1322                 break;
1323             }
1324         }
1325         i = l;
1326         j = 2 * l + 1;
1327         while (j <= ir) {
1328             if (j < ir && ra[j] < ra[j+1]) j++;
1329             if (rra < ra[j]) {
1330                 ra[i] = ra[j];
1331                 i = j;
1332                 j++; j <<= 1; j--;
1333             }
1334             else break;
1335         }
1336         ra[i] = rra;
1337     }
1338 }
1339
1340 /* This function constructs an ordered list which represents how much the
1341  * different colors are used. So for instance (100, 100, 500) means that one
1342  * color is used for 500 pixels, another for 100 pixels and another for 100
1343  * pixels. It's tuned for performance. You might not like the way I've hardcoded
1344  * the maxc ;-) and you might want to change the name... */
1345 /* Uses octt_histo */
1346 int
1347 get_anonymous_color_histo(i_img *im, unsigned int **col_usage) {
1348     struct octt *ct;
1349     int x,y,i;
1350     int colorcnt;
1351     int maxc = 10000000;
1352     unsigned int *col_usage_it;
1353     i_sample_t * samp;
1354
1355     int xsize = im->xsize; 
1356     int ysize = im->ysize;
1357     int samp_cnt = 3 * xsize;
1358     ct = octt_new();
1359
1360     samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1361
1362     colorcnt = 0;
1363     for(y = 0; y < ysize; ) {
1364         i_gsamp(im, 0, xsize, y++, samp, NULL, 3);
1365         for(x = 0; x < samp_cnt; ) {
1366             colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1367             x += 3;
1368             if (colorcnt > maxc) { 
1369                 octt_delete(ct); 
1370                 return -1; 
1371             }
1372         }
1373     }
1374     myfree(samp);
1375     /* Now that we know the number of colours... */
1376     col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * 2 * sizeof(unsigned int));
1377     octt_histo(ct, &col_usage_it);
1378     hpsort(colorcnt, *col_usage);
1379     octt_delete(ct);
1380     return colorcnt;
1381 }
1382
1383
1384
1385 /*
1386 =back
1387
1388 =head2 8-bit per sample image internal functions
1389
1390 These are the functions installed in an 8-bit per sample image.
1391
1392 =over
1393
1394 =item i_ppix_d(im, x, y, col)
1395
1396 Internal function.
1397
1398 This is the function kept in the i_f_ppix member of an i_img object.
1399 It does a normal store of a pixel into the image with range checking.
1400
1401 Returns 0 if the pixel could be set, -1 otherwise.
1402
1403 =cut
1404 */
1405 static
1406 int
1407 i_ppix_d(i_img *im, int x, int y, const i_color *val) {
1408   int ch;
1409   
1410   if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1411     for(ch=0;ch<im->channels;ch++)
1412       if (im->ch_mask&(1<<ch)) 
1413         im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1414     return 0;
1415   }
1416   return -1; /* error was clipped */
1417 }
1418
1419 /*
1420 =item i_gpix_d(im, x, y, &col)
1421
1422 Internal function.
1423
1424 This is the function kept in the i_f_gpix member of an i_img object.
1425 It does normal retrieval of a pixel from the image with range checking.
1426
1427 Returns 0 if the pixel could be set, -1 otherwise.
1428
1429 =cut
1430 */
1431 static
1432 int 
1433 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1434   int ch;
1435   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1436     for(ch=0;ch<im->channels;ch++) 
1437       val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1438     return 0;
1439   }
1440   for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1441   return -1; /* error was cliped */
1442 }
1443
1444 /*
1445 =item i_glin_d(im, l, r, y, vals)
1446
1447 Reads a line of data from the image, storing the pixels at vals.
1448
1449 The line runs from (l,y) inclusive to (r,y) non-inclusive
1450
1451 vals should point at space for (r-l) pixels.
1452
1453 l should never be less than zero (to avoid confusion about where to
1454 put the pixels in vals).
1455
1456 Returns the number of pixels copied (eg. if r, l or y is out of range)
1457
1458 =cut
1459 */
1460 static
1461 int
1462 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1463   int ch, count, i;
1464   unsigned char *data;
1465   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1466     if (r > im->xsize)
1467       r = im->xsize;
1468     data = im->idata + (l+y*im->xsize) * im->channels;
1469     count = r - l;
1470     for (i = 0; i < count; ++i) {
1471       for (ch = 0; ch < im->channels; ++ch)
1472         vals[i].channel[ch] = *data++;
1473     }
1474     return count;
1475   }
1476   else {
1477     return 0;
1478   }
1479 }
1480
1481 /*
1482 =item i_plin_d(im, l, r, y, vals)
1483
1484 Writes a line of data into the image, using the pixels at vals.
1485
1486 The line runs from (l,y) inclusive to (r,y) non-inclusive
1487
1488 vals should point at (r-l) pixels.
1489
1490 l should never be less than zero (to avoid confusion about where to
1491 get the pixels in vals).
1492
1493 Returns the number of pixels copied (eg. if r, l or y is out of range)
1494
1495 =cut
1496 */
1497 static
1498 int
1499 i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) {
1500   int ch, count, i;
1501   unsigned char *data;
1502   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1503     if (r > im->xsize)
1504       r = im->xsize;
1505     data = im->idata + (l+y*im->xsize) * im->channels;
1506     count = r - l;
1507     for (i = 0; i < count; ++i) {
1508       for (ch = 0; ch < im->channels; ++ch) {
1509         if (im->ch_mask & (1 << ch)) 
1510           *data = vals[i].channel[ch];
1511         ++data;
1512       }
1513     }
1514     return count;
1515   }
1516   else {
1517     return 0;
1518   }
1519 }
1520
1521 /*
1522 =item i_ppixf_d(im, x, y, val)
1523
1524 =cut
1525 */
1526 static
1527 int
1528 i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) {
1529   int ch;
1530   
1531   if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1532     for(ch=0;ch<im->channels;ch++)
1533       if (im->ch_mask&(1<<ch)) {
1534         im->idata[(x+y*im->xsize)*im->channels+ch] = 
1535           SampleFTo8(val->channel[ch]);
1536       }
1537     return 0;
1538   }
1539   return -1; /* error was clipped */
1540 }
1541
1542 /*
1543 =item i_gpixf_d(im, x, y, val)
1544
1545 =cut
1546 */
1547 static
1548 int
1549 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1550   int ch;
1551   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1552     for(ch=0;ch<im->channels;ch++) {
1553       val->channel[ch] = 
1554         Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1555     }
1556     return 0;
1557   }
1558   return -1; /* error was cliped */
1559 }
1560
1561 /*
1562 =item i_glinf_d(im, l, r, y, vals)
1563
1564 Reads a line of data from the image, storing the pixels at vals.
1565
1566 The line runs from (l,y) inclusive to (r,y) non-inclusive
1567
1568 vals should point at space for (r-l) pixels.
1569
1570 l should never be less than zero (to avoid confusion about where to
1571 put the pixels in vals).
1572
1573 Returns the number of pixels copied (eg. if r, l or y is out of range)
1574
1575 =cut
1576 */
1577 static
1578 int
1579 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1580   int ch, count, i;
1581   unsigned char *data;
1582   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1583     if (r > im->xsize)
1584       r = im->xsize;
1585     data = im->idata + (l+y*im->xsize) * im->channels;
1586     count = r - l;
1587     for (i = 0; i < count; ++i) {
1588       for (ch = 0; ch < im->channels; ++ch)
1589         vals[i].channel[ch] = Sample8ToF(*data++);
1590     }
1591     return count;
1592   }
1593   else {
1594     return 0;
1595   }
1596 }
1597
1598 /*
1599 =item i_plinf_d(im, l, r, y, vals)
1600
1601 Writes a line of data into the image, using the pixels at vals.
1602
1603 The line runs from (l,y) inclusive to (r,y) non-inclusive
1604
1605 vals should point at (r-l) pixels.
1606
1607 l should never be less than zero (to avoid confusion about where to
1608 get the pixels in vals).
1609
1610 Returns the number of pixels copied (eg. if r, l or y is out of range)
1611
1612 =cut
1613 */
1614 static
1615 int
1616 i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) {
1617   int ch, count, i;
1618   unsigned char *data;
1619   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1620     if (r > im->xsize)
1621       r = im->xsize;
1622     data = im->idata + (l+y*im->xsize) * im->channels;
1623     count = r - l;
1624     for (i = 0; i < count; ++i) {
1625       for (ch = 0; ch < im->channels; ++ch) {
1626         if (im->ch_mask & (1 << ch)) 
1627           *data = SampleFTo8(vals[i].channel[ch]);
1628         ++data;
1629       }
1630     }
1631     return count;
1632   }
1633   else {
1634     return 0;
1635   }
1636 }
1637
1638 /*
1639 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1640
1641 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1642 for the channels specified by chans, an array of int with chan_count
1643 elements.
1644
1645 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1646
1647 =cut
1648 */
1649 static
1650 int
1651 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, 
1652               const int *chans, int chan_count) {
1653   int ch, count, i, w;
1654   unsigned char *data;
1655
1656   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1657     if (r > im->xsize)
1658       r = im->xsize;
1659     data = im->idata + (l+y*im->xsize) * im->channels;
1660     w = r - l;
1661     count = 0;
1662
1663     if (chans) {
1664       /* make sure we have good channel numbers */
1665       for (ch = 0; ch < chan_count; ++ch) {
1666         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1667           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1668           return 0;
1669         }
1670       }
1671       for (i = 0; i < w; ++i) {
1672         for (ch = 0; ch < chan_count; ++ch) {
1673           *samps++ = data[chans[ch]];
1674           ++count;
1675         }
1676         data += im->channels;
1677       }
1678     }
1679     else {
1680       for (i = 0; i < w; ++i) {
1681         for (ch = 0; ch < chan_count; ++ch) {
1682           *samps++ = data[ch];
1683           ++count;
1684         }
1685         data += im->channels;
1686       }
1687     }
1688
1689     return count;
1690   }
1691   else {
1692     return 0;
1693   }
1694 }
1695
1696 /*
1697 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1698
1699 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1700 for the channels specified by chan_mask, where bit 0 is the first
1701 channel.
1702
1703 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1704
1705 =cut
1706 */
1707 static
1708 int
1709 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, 
1710            const int *chans, int chan_count) {
1711   int ch, count, i, w;
1712   unsigned char *data;
1713   for (ch = 0; ch < chan_count; ++ch) {
1714     if (chans[ch] < 0 || chans[ch] >= im->channels) {
1715       i_push_errorf(0, "No channel %d in this image", chans[ch]);
1716     }
1717   }
1718   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1719     if (r > im->xsize)
1720       r = im->xsize;
1721     data = im->idata + (l+y*im->xsize) * im->channels;
1722     w = r - l;
1723     count = 0;
1724
1725     if (chans) {
1726       /* make sure we have good channel numbers */
1727       for (ch = 0; ch < chan_count; ++ch) {
1728         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1729           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1730           return 0;
1731         }
1732       }
1733       for (i = 0; i < w; ++i) {
1734         for (ch = 0; ch < chan_count; ++ch) {
1735           *samps++ = Sample8ToF(data[chans[ch]]);
1736           ++count;
1737         }
1738         data += im->channels;
1739       }
1740     }
1741     else {
1742       for (i = 0; i < w; ++i) {
1743         for (ch = 0; ch < chan_count; ++ch) {
1744           *samps++ = Sample8ToF(data[ch]);
1745           ++count;
1746         }
1747         data += im->channels;
1748       }
1749     }
1750     return count;
1751   }
1752   else {
1753     return 0;
1754   }
1755 }
1756
1757 /*
1758 =back
1759
1760 =head2 Image method wrappers
1761
1762 These functions provide i_fsample_t functions in terms of their
1763 i_sample_t versions.
1764
1765 =over
1766
1767 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1768
1769 =cut
1770 */
1771
1772 int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) {
1773   i_color temp;
1774   int ch;
1775
1776   for (ch = 0; ch < im->channels; ++ch)
1777     temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1778   
1779   return i_ppix(im, x, y, &temp);
1780 }
1781
1782 /*
1783 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1784
1785 =cut
1786 */
1787 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1788   i_color temp;
1789   int ch;
1790
1791   if (i_gpix(im, x, y, &temp)) {
1792     for (ch = 0; ch < im->channels; ++ch)
1793       pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1794     return 0;
1795   }
1796   else 
1797     return -1;
1798 }
1799
1800 /*
1801 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1802
1803 =cut
1804 */
1805 int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) {
1806   i_color *work;
1807
1808   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1809     if (r > im->xsize)
1810       r = im->xsize;
1811     if (r > l) {
1812       int ret;
1813       int i, ch;
1814       work = mymalloc(sizeof(i_color) * (r-l));
1815       for (i = 0; i < r-l; ++i) {
1816         for (ch = 0; ch < im->channels; ++ch) 
1817           work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1818       }
1819       ret = i_plin(im, l, r, y, work);
1820       myfree(work);
1821
1822       return ret;
1823     }
1824     else {
1825       return 0;
1826     }
1827   }
1828   else {
1829     return 0;
1830   }
1831 }
1832
1833 /*
1834 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1835
1836 =cut
1837 */
1838 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1839   i_color *work;
1840
1841   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1842     if (r > im->xsize)
1843       r = im->xsize;
1844     if (r > l) {
1845       int ret;
1846       int i, ch;
1847       work = mymalloc(sizeof(i_color) * (r-l));
1848       ret = i_plin(im, l, r, y, work);
1849       for (i = 0; i < r-l; ++i) {
1850         for (ch = 0; ch < im->channels; ++ch) 
1851           pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1852       }
1853       myfree(work);
1854
1855       return ret;
1856     }
1857     else {
1858       return 0;
1859     }
1860   }
1861   else {
1862     return 0;
1863   }
1864 }
1865
1866 /*
1867 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1868
1869 =cut
1870 */
1871 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, 
1872                 int const *chans, int chan_count) {
1873   i_sample_t *work;
1874
1875   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1876     if (r > im->xsize)
1877       r = im->xsize;
1878     if (r > l) {
1879       int ret;
1880       int i;
1881       work = mymalloc(sizeof(i_sample_t) * (r-l));
1882       ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1883       for (i = 0; i < ret; ++i) {
1884           samp[i] = Sample8ToF(work[i]);
1885       }
1886       myfree(work);
1887
1888       return ret;
1889     }
1890     else {
1891       return 0;
1892     }
1893   }
1894   else {
1895     return 0;
1896   }
1897 }
1898
1899 /*
1900 =back
1901
1902 =head2 Palette wrapper functions
1903
1904 Used for virtual images, these forward palette calls to a wrapped image, 
1905 assuming the wrapped image is the first pointer in the structure that 
1906 im->ext_data points at.
1907
1908 =over
1909
1910 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1911
1912 =cut
1913 */
1914 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1915   return i_addcolors(*(i_img **)im->ext_data, colors, count);
1916 }
1917
1918 /*
1919 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1920
1921 =cut
1922 */
1923 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1924   return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1925 }
1926
1927 /*
1928 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1929
1930 =cut
1931 */
1932 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1933   return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1934 }
1935
1936 /*
1937 =item i_colorcount_forward(i_img *im)
1938
1939 =cut
1940 */
1941 int i_colorcount_forward(i_img *im) {
1942   return i_colorcount(*(i_img **)im->ext_data);
1943 }
1944
1945 /*
1946 =item i_maxcolors_forward(i_img *im)
1947
1948 =cut
1949 */
1950 int i_maxcolors_forward(i_img *im) {
1951   return i_maxcolors(*(i_img **)im->ext_data);
1952 }
1953
1954 /*
1955 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1956
1957 =cut
1958 */
1959 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1960   return i_findcolor(*(i_img **)im->ext_data, color, entry);
1961 }
1962
1963 /*
1964 =back
1965
1966 =head2 Stream reading and writing wrapper functions
1967
1968 =over
1969
1970 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1971
1972 Performs general read buffering for file readers that permit reading
1973 to be done through a callback.
1974
1975 The final callback gets two parameters, a I<need> value, and a I<want>
1976 value, where I<need> is the amount of data that the file library needs
1977 to read, and I<want> is the amount of space available in the buffer
1978 maintained by these functions.
1979
1980 This means if you need to read from a stream that you don't know the
1981 length of, you can return I<need> bytes, taking the performance hit of
1982 possibly expensive callbacks (eg. back to perl code), or if you are
1983 reading from a stream where it doesn't matter if some data is lost, or
1984 if the total length of the stream is known, you can return I<want>
1985 bytes.
1986
1987 =cut 
1988 */
1989
1990 int
1991 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1992   int total;
1993
1994   if (length < gci->length - gci->cpos) {
1995     /* simplest case */
1996     memcpy(buf, gci->buffer+gci->cpos, length);
1997     gci->cpos += length;
1998     return length;
1999   }
2000   
2001   total = 0;
2002   memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
2003   total  += gci->length - gci->cpos;
2004   length -= gci->length - gci->cpos;
2005   buf    += gci->length - gci->cpos;
2006   if (length < (int)sizeof(gci->buffer)) {
2007     int did_read;
2008     int copy_size;
2009     while (length
2010            && (did_read = (gci->cb)(gci->userdata, gci->buffer, length, 
2011                                     sizeof(gci->buffer))) > 0) {
2012       gci->cpos = 0;
2013       gci->length = did_read;
2014
2015       copy_size = i_min(length, gci->length);
2016       memcpy(buf, gci->buffer, copy_size);
2017       gci->cpos += copy_size;
2018       buf += copy_size;
2019       total += copy_size;
2020       length -= copy_size;
2021     }
2022   }
2023   else {
2024     /* just read the rest - too big for our buffer*/
2025     int did_read;
2026     while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
2027       length -= did_read;
2028       total += did_read;
2029       buf += did_read;
2030     }
2031   }
2032   return total;
2033 }
2034
2035 /*
2036 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
2037
2038 For use by callback file readers to initialize the reader buffer.
2039
2040 Allocates, initializes and returns the reader buffer.
2041
2042 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
2043
2044 =cut
2045 */
2046 i_gen_read_data *
2047 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
2048   i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
2049   self->cb = cb;
2050   self->userdata = userdata;
2051   self->length = 0;
2052   self->cpos = 0;
2053
2054   return self;
2055 }
2056
2057 /*
2058 =item i_free_gen_read_data(i_gen_read_data *)
2059
2060 Cleans up.
2061
2062 =cut
2063 */
2064 void i_free_gen_read_data(i_gen_read_data *self) {
2065   myfree(self);
2066 }
2067
2068 /*
2069 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
2070
2071 Performs write buffering for a callback based file writer.
2072
2073 Failures are considered fatal, if a write fails then data will be
2074 dropped.
2075
2076 =cut
2077 */
2078 int 
2079 i_gen_writer(
2080 i_gen_write_data *self, 
2081 char const *data, 
2082 int size)
2083 {
2084   if (self->filledto && self->filledto+size > self->maxlength) {
2085     if (self->cb(self->userdata, self->buffer, self->filledto)) {
2086       self->filledto = 0;
2087     }
2088     else {
2089       self->filledto = 0;
2090       return 0;
2091     }
2092   }
2093   if (self->filledto+size <= self->maxlength) {
2094     /* just save it */
2095     memcpy(self->buffer+self->filledto, data, size);
2096     self->filledto += size;
2097     return 1;
2098   }
2099   /* doesn't fit - hand it off */
2100   return self->cb(self->userdata, data, size);
2101 }
2102
2103 /*
2104 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2105
2106 Allocates and initializes the data structure used by i_gen_writer.
2107
2108 This should be released with L<image.c/i_free_gen_write_data>
2109
2110 =cut
2111 */
2112 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, 
2113                                        char *userdata, int max_length)
2114 {
2115   i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2116   self->cb = cb;
2117   self->userdata = userdata;
2118   self->maxlength = i_min(max_length, sizeof(self->buffer));
2119   if (self->maxlength < 0)
2120     self->maxlength = sizeof(self->buffer);
2121   self->filledto = 0;
2122
2123   return self;
2124 }
2125
2126 /*
2127 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2128
2129 Cleans up the write buffer.
2130
2131 Will flush any left-over data if I<flush> is non-zero.
2132
2133 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2134
2135 Return zero only if flush is non-zero and info->cb() returns zero.
2136 ie. if it fails.
2137
2138 =cut
2139 */
2140
2141 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2142 {
2143   int result = !flush || 
2144     info->filledto == 0 ||
2145     info->cb(info->userdata, info->buffer, info->filledto);
2146   myfree(info);
2147
2148   return result;
2149 }
2150
2151 struct magic_entry {
2152   unsigned char *magic;
2153   size_t magic_size;
2154   char *name;
2155   unsigned char *mask;  
2156 };
2157
2158 static int
2159 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
2160   if (length < magic->magic_size)
2161     return 0;
2162   if (magic->mask) {
2163     int i;
2164     unsigned char *bufp = buffer, 
2165       *maskp = magic->mask, 
2166       *magicp = magic->magic;
2167
2168     for (i = 0; i < magic->magic_size; ++i) {
2169       int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
2170       ++maskp;
2171
2172       if ((*bufp++ & mask) != (*magicp++ & mask)) 
2173         return 0;
2174     }
2175
2176     return 1;
2177   }
2178   else {
2179     return !memcmp(magic->magic, buffer, magic->magic_size);
2180   }
2181 }
2182
2183 /*
2184 =item i_test_format_probe(io_glue *data, int length)
2185
2186 Check the beginning of the supplied file for a 'magic number'
2187
2188 =cut
2189 */
2190
2191 #define FORMAT_ENTRY(magic, type) \
2192   { (unsigned char *)(magic ""), sizeof(magic)-1, type }
2193 #define FORMAT_ENTRY2(magic, type, mask) \
2194   { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
2195
2196 const char *
2197 i_test_format_probe(io_glue *data, int length) {
2198   static const struct magic_entry formats[] = {
2199     FORMAT_ENTRY("\xFF\xD8", "jpeg"),
2200     FORMAT_ENTRY("GIF87a", "gif"),
2201     FORMAT_ENTRY("GIF89a", "gif"),
2202     FORMAT_ENTRY("MM\0*", "tiff"),
2203     FORMAT_ENTRY("II*\0", "tiff"),
2204     FORMAT_ENTRY("BM", "bmp"),
2205     FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
2206     FORMAT_ENTRY("P1", "pnm"),
2207     FORMAT_ENTRY("P2", "pnm"),
2208     FORMAT_ENTRY("P3", "pnm"),
2209     FORMAT_ENTRY("P4", "pnm"),
2210     FORMAT_ENTRY("P5", "pnm"),
2211     FORMAT_ENTRY("P6", "pnm"),
2212     FORMAT_ENTRY("/* XPM", "xpm"),
2213     FORMAT_ENTRY("\x8aMNG", "mng"),
2214     FORMAT_ENTRY("\x8aJNG", "jng"),
2215     /* SGI RGB - with various possible parameters to avoid false positives
2216        on similar files 
2217        values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
2218     */
2219     FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
2220     FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
2221     FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
2222     FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
2223     
2224     FORMAT_ENTRY2("FORM    ILBM", "ilbm", "xxxx    xxxx"),
2225
2226     /* different versions of PCX format 
2227        http://www.fileformat.info/format/pcx/
2228     */
2229     FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
2230     FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
2231     FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
2232     FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
2233     FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
2234
2235     /* FITS - http://fits.gsfc.nasa.gov/ */
2236     FORMAT_ENTRY("SIMPLE  =", "fits"),
2237
2238     /* PSD - Photoshop */
2239     FORMAT_ENTRY("8BPS\x00\x01", "psd"),
2240     
2241     /* EPS - Encapsulated Postscript */
2242     /* only reading 18 chars, so we don't include the F in EPSF */
2243     FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
2244
2245     /* Utah RLE */
2246     FORMAT_ENTRY("\x52\xCC", "utah"),
2247
2248     /* GZIP compressed, only matching deflate for now */
2249     FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
2250
2251     /* bzip2 compressed */
2252     FORMAT_ENTRY("BZh", "bzip2"),
2253   };
2254   static const struct magic_entry more_formats[] = {
2255     /* these were originally both listed as ico, but cur files can
2256        include hotspot information */
2257     FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
2258     FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
2259     FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07", 
2260                   "xwd", "    xxxx"), /* X Windows Dump */
2261   };
2262
2263   unsigned int i;
2264   unsigned char head[18];
2265   ssize_t rc;
2266
2267   io_glue_commit_types(data);
2268   rc = data->readcb(data, head, 18);
2269   if (rc == -1) return NULL;
2270   data->seekcb(data, -rc, SEEK_CUR);
2271
2272   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
2273     struct magic_entry const *entry = formats + i;
2274
2275     if (test_magic(head, rc, entry)) 
2276       return entry->name;
2277   }
2278
2279   if ((rc == 18) &&
2280       tga_header_verify(head))
2281     return "tga";
2282
2283   for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) { 
2284     struct magic_entry const *entry = more_formats + i;
2285
2286     if (test_magic(head, rc, entry)) 
2287       return entry->name;
2288   }
2289
2290   return NULL;
2291 }
2292
2293 /*
2294 =item i_img_is_monochrome(img, &zero_is_white)
2295
2296 Tests an image to check it meets our monochrome tests.
2297
2298 The idea is that a file writer can use this to test where it should
2299 write the image in whatever bi-level format it uses, eg. pbm for pnm.
2300
2301 For performance of encoders we require monochrome images:
2302
2303 =over
2304
2305 =item *
2306
2307 be paletted
2308
2309 =item *
2310
2311 have a palette of two colors, containing only (0,0,0) and
2312 (255,255,255) in either order.
2313
2314 =back
2315
2316 zero_is_white is set to non-zero iff the first palette entry is white.
2317
2318 =cut
2319 */
2320
2321 int
2322 i_img_is_monochrome(i_img *im, int *zero_is_white) {
2323   if (im->type == i_palette_type
2324       && i_colorcount(im) == 2) {
2325     i_color colors[2];
2326     i_getcolors(im, 0, colors, 2);
2327     if (im->channels == 3) {
2328       if (colors[0].rgb.r == 255 && 
2329           colors[0].rgb.g == 255 &&
2330           colors[0].rgb.b == 255 &&
2331           colors[1].rgb.r == 0 &&
2332           colors[1].rgb.g == 0 &&
2333           colors[1].rgb.b == 0) {
2334         *zero_is_white = 0;
2335         return 1;
2336       }
2337       else if (colors[0].rgb.r == 0 && 
2338                colors[0].rgb.g == 0 &&
2339                colors[0].rgb.b == 0 &&
2340                colors[1].rgb.r == 255 &&
2341                colors[1].rgb.g == 255 &&
2342                colors[1].rgb.b == 255) {
2343         *zero_is_white = 1;
2344         return 1;
2345       }
2346     }
2347     else if (im->channels == 1) {
2348       if (colors[0].channel[0] == 255 &&
2349           colors[1].channel[1] == 0) {
2350         *zero_is_white = 0;
2351         return 1;
2352       }
2353       else if (colors[0].channel[0] == 0 &&
2354                colors[0].channel[0] == 255) {
2355         *zero_is_white = 1;
2356         return 1;         
2357       }
2358     }
2359   }
2360
2361   *zero_is_white = 0;
2362   return 0;
2363 }
2364
2365 /*
2366 =back
2367
2368 =head1 AUTHOR
2369
2370 Arnar M. Hrafnkelsson <addi@umich.edu>
2371
2372 Tony Cook <tony@develop-help.com>
2373
2374 =head1 SEE ALSO
2375
2376 L<Imager>, L<gif.c>
2377
2378 =cut
2379 */