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