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