]> git.imager.perl.org - imager.git/blob - image.c
5dba629f32ba0b8430775ce4698009de2cfe414c
[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   i_clear_error();
857   mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
858
859
860   if (Axis == XAXIS) {
861     hsize = (int)(0.5 + im->xsize * Value);
862     if (hsize < 1) {
863       hsize = 1;
864       Value = 1.0 / im->xsize;
865     }
866     vsize = im->ysize;
867     
868     jEnd = hsize;
869     iEnd = vsize;
870   } else {
871     hsize = im->xsize;
872     vsize = (int)(0.5 + im->ysize * Value);
873
874     if (vsize < 1) {
875       vsize = 1;
876       Value = 1.0 / im->ysize;
877     }
878
879     jEnd = vsize;
880     iEnd = hsize;
881   }
882   
883   new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
884   if (!new_img) {
885     i_push_error(0, "cannot create output image");
886     return NULL;
887   }
888   
889   /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
890   LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value); 
891   lMax = LanczosWidthFactor << 1;
892   
893   l0 = mymalloc(lMax * sizeof(float));
894   l1 = mymalloc(lMax * sizeof(float));
895   
896   for (j=0; j<jEnd; j++) {
897     OldLocation = ((float) j) / Value;
898     T = (int) (OldLocation);
899     F = OldLocation - (float) T;
900     
901     for (l = 0; l<lMax; l++) {
902       l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
903       l1[l]        = Lanczos(((float) (l+1)      - F) / (float) LanczosWidthFactor);
904     }
905     
906     /* Make sure filter is normalized */
907     t = 0.0;
908     for(l=0; l<lMax; l++) {
909       t+=l0[l];
910       t+=l1[l];
911     }
912     t /= (float)LanczosWidthFactor;
913     
914     for(l=0; l<lMax; l++) {
915       l0[l] /= t;
916       l1[l] /= t;
917     }
918
919     if (Axis == XAXIS) {
920       
921       for (i=0; i<iEnd; i++) {
922         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
923         for (l=0; l<lMax; l++) {
924           int mx = T-lMax+l+1;
925           int Mx = T+l+1;
926           mx = (mx < 0) ? 0 : mx;
927           Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
928           
929           i_gpix(im, Mx, i, &val1);
930           i_gpix(im, mx, i, &val2);
931           
932           for (k=0; k<im->channels; k++) {
933             PictureValue[k] += l1[l]        * val1.channel[k];
934             PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
935           }
936         }
937         for(k=0;k<im->channels;k++) {
938           psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
939           val.channel[k]=minmax(0,255,psave);
940         }
941         i_ppix(new_img, j, i, &val);
942       }
943       
944     } else {
945       
946       for (i=0; i<iEnd; i++) {
947         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
948         for (l=0; l < lMax; l++) {
949           int mx = T-lMax+l+1;
950           int Mx = T+l+1;
951           mx = (mx < 0) ? 0 : mx;
952           Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
953
954           i_gpix(im, i, Mx, &val1);
955           i_gpix(im, i, mx, &val2);
956           for (k=0; k<im->channels; k++) {
957             PictureValue[k] += l1[l]        * val1.channel[k];
958             PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; 
959           }
960         }
961         for (k=0; k<im->channels; k++) {
962           psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
963           val.channel[k] = minmax(0, 255, psave);
964         }
965         i_ppix(new_img, i, j, &val);
966       }
967       
968     }
969   }
970   myfree(l0);
971   myfree(l1);
972
973   mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
974
975   return new_img;
976 }
977
978
979 /* 
980 =item i_scale_nn(im, scx, scy)
981
982 Scale by using nearest neighbor 
983 Both axes scaled at the same time since 
984 nothing is gained by doing it in two steps 
985
986 =cut
987 */
988
989
990 i_img*
991 i_scale_nn(i_img *im, float scx, float scy) {
992
993   int nxsize,nysize,nx,ny;
994   i_img *new_img;
995   i_color val;
996
997   mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
998
999   nxsize = (int) ((float) im->xsize * scx);
1000   if (nxsize < 1) {
1001     nxsize = 1;
1002     scx = 1 / im->xsize;
1003   }
1004   nysize = (int) ((float) im->ysize * scy);
1005   if (nysize < 1) {
1006     nysize = 1;
1007     scy = 1 / im->ysize;
1008   }
1009     
1010   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1011   
1012   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1013     i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1014     i_ppix(new_img,nx,ny,&val);
1015   }
1016
1017   mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1018
1019   return new_img;
1020 }
1021
1022 /*
1023 =item i_sametype(i_img *im, int xsize, int ysize)
1024
1025 =category Image creation/destruction
1026 =synopsis i_img *img = i_sametype(src, width, height);
1027
1028 Returns an image of the same type (sample size, channels, paletted/direct).
1029
1030 For paletted images the palette is copied from the source.
1031
1032 =cut
1033 */
1034
1035 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1036   if (src->type == i_direct_type) {
1037     if (src->bits == 8) {
1038       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1039     }
1040     else if (src->bits == i_16_bits) {
1041       return i_img_16_new(xsize, ysize, src->channels);
1042     }
1043     else if (src->bits == i_double_bits) {
1044       return i_img_double_new(xsize, ysize, src->channels);
1045     }
1046     else {
1047       i_push_error(0, "Unknown image bits");
1048       return NULL;
1049     }
1050   }
1051   else {
1052     i_color col;
1053     int i;
1054
1055     i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1056     for (i = 0; i < i_colorcount(src); ++i) {
1057       i_getcolors(src, i, &col, 1);
1058       i_addcolors(targ, &col, 1);
1059     }
1060
1061     return targ;
1062   }
1063 }
1064
1065 /*
1066 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
1067
1068 =category Image creation/destruction
1069 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
1070
1071 Returns an image of the same type (sample size).
1072
1073 For paletted images the equivalent direct type is returned.
1074
1075 =cut
1076 */
1077
1078 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1079   if (src->bits == 8) {
1080     return i_img_empty_ch(NULL, xsize, ysize, channels);
1081   }
1082   else if (src->bits == i_16_bits) {
1083     return i_img_16_new(xsize, ysize, channels);
1084   }
1085   else if (src->bits == i_double_bits) {
1086     return i_img_double_new(xsize, ysize, channels);
1087   }
1088   else {
1089     i_push_error(0, "Unknown image bits");
1090     return NULL;
1091   }
1092 }
1093
1094 /*
1095 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1096
1097 Spatially transforms I<im> returning a new image.
1098
1099 opx for a length of opxl and opy for a length of opy are arrays of
1100 operators that modify the x and y positions to retreive the pixel data from.
1101
1102 parm and parmlen define extra parameters that the operators may use.
1103
1104 Note that this function is largely superseded by the more flexible
1105 L<transform.c/i_transform2>.
1106
1107 Returns the new image.
1108
1109 The operators for this function are defined in L<stackmach.c>.
1110
1111 =cut
1112 */
1113 i_img*
1114 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1115   double rx,ry;
1116   int nxsize,nysize,nx,ny;
1117   i_img *new_img;
1118   i_color val;
1119   
1120   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));
1121
1122   nxsize = im->xsize;
1123   nysize = im->ysize ;
1124   
1125   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1126   /*   fprintf(stderr,"parm[2]=%f\n",parm[2]);   */
1127   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1128     /*     parm[parmlen-2]=(double)nx;
1129            parm[parmlen-1]=(double)ny; */
1130
1131     parm[0]=(double)nx;
1132     parm[1]=(double)ny;
1133
1134     /*     fprintf(stderr,"(%d,%d) ->",nx,ny);  */
1135     rx=i_op_run(opx,opxl,parm,parmlen);
1136     ry=i_op_run(opy,opyl,parm,parmlen);
1137     /*    fprintf(stderr,"(%f,%f)\n",rx,ry); */
1138     i_gpix(im,rx,ry,&val);
1139     i_ppix(new_img,nx,ny,&val);
1140   }
1141
1142   mm_log((1,"(0x%x) <- i_transform\n",new_img));
1143   return new_img;
1144 }
1145
1146 /*
1147 =item i_img_diff(im1, im2)
1148
1149 Calculates the sum of the squares of the differences between
1150 correspoding channels in two images.
1151
1152 If the images are not the same size then only the common area is 
1153 compared, hence even if images are different sizes this function 
1154 can return zero.
1155
1156 =cut
1157 */
1158 float
1159 i_img_diff(i_img *im1,i_img *im2) {
1160   int x,y,ch,xb,yb,chb;
1161   float tdiff;
1162   i_color val1,val2;
1163
1164   mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1165
1166   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1167   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1168   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1169
1170   mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1171
1172   tdiff=0;
1173   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1174     i_gpix(im1,x,y,&val1);
1175     i_gpix(im2,x,y,&val2);
1176
1177     for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1178   }
1179   mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1180   return tdiff;
1181 }
1182
1183 /* just a tiny demo of haar wavelets */
1184
1185 i_img*
1186 i_haar(i_img *im) {
1187   int mx,my;
1188   int fx,fy;
1189   int x,y;
1190   int ch,c;
1191   i_img *new_img,*new_img2;
1192   i_color val1,val2,dval1,dval2;
1193   
1194   mx=im->xsize;
1195   my=im->ysize;
1196   fx=(mx+1)/2;
1197   fy=(my+1)/2;
1198
1199
1200   /* horizontal pass */
1201   
1202   new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1203   new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1204
1205   c=0; 
1206   for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1207     i_gpix(im,x*2,y,&val1);
1208     i_gpix(im,x*2+1,y,&val2);
1209     for(ch=0;ch<im->channels;ch++) {
1210       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1211       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1212     }
1213     i_ppix(new_img,x,y,&dval1);
1214     i_ppix(new_img,x+fx,y,&dval2);
1215   }
1216
1217   for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1218     i_gpix(new_img,x,y*2,&val1);
1219     i_gpix(new_img,x,y*2+1,&val2);
1220     for(ch=0;ch<im->channels;ch++) {
1221       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1222       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1223     }
1224     i_ppix(new_img2,x,y,&dval1);
1225     i_ppix(new_img2,x,y+fy,&dval2);
1226   }
1227
1228   i_img_destroy(new_img);
1229   return new_img2;
1230 }
1231
1232 /* 
1233 =item i_count_colors(im, maxc)
1234
1235 returns number of colors or -1 
1236 to indicate that it was more than max colors
1237
1238 =cut
1239 */
1240 /* This function has been changed and is now faster. It's using
1241  * i_gsamp instead of i_gpix */
1242 int
1243 i_count_colors(i_img *im,int maxc) {
1244   struct octt *ct;
1245   int x,y;
1246   int colorcnt;
1247   int channels[3];
1248   int *samp_chans;
1249   i_sample_t * samp;
1250   int xsize = im->xsize; 
1251   int ysize = im->ysize;
1252   int samp_cnt = 3 * xsize;
1253
1254   if (im->channels >= 3) {
1255     samp_chans = NULL;
1256   }
1257   else {
1258     channels[0] = channels[1] = channels[2] = 0;
1259     samp_chans = channels;
1260   }
1261
1262   ct = octt_new();
1263
1264   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1265
1266   colorcnt = 0;
1267   for(y = 0; y < ysize; ) {
1268       i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1269       for(x = 0; x < samp_cnt; ) {
1270           colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1271           x += 3;
1272           if (colorcnt > maxc) { 
1273               octt_delete(ct); 
1274               return -1; 
1275           }
1276       }
1277   }
1278   myfree(samp);
1279   octt_delete(ct);
1280   return colorcnt;
1281 }
1282
1283 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm 
1284  * (adapted from the Numerical Recipes)
1285  */
1286 /* Needed by get_anonymous_color_histo */
1287 static void
1288 hpsort(unsigned int n, unsigned *ra) {
1289     unsigned int i,
1290                  ir,
1291                  j,
1292                  l, 
1293                  rra;
1294
1295     if (n < 2) return;
1296     l = n >> 1;
1297     ir = n - 1;
1298     for(;;) {
1299         if (l > 0) {
1300             rra = ra[--l];
1301         }
1302         else {
1303             rra = ra[ir];
1304             ra[ir] = ra[0];
1305             if (--ir == 0) {
1306                 ra[0] = rra;
1307                 break;
1308             }
1309         }
1310         i = l;
1311         j = 2 * l + 1;
1312         while (j <= ir) {
1313             if (j < ir && ra[j] < ra[j+1]) j++;
1314             if (rra < ra[j]) {
1315                 ra[i] = ra[j];
1316                 i = j;
1317                 j++; j <<= 1; j--;
1318             }
1319             else break;
1320         }
1321         ra[i] = rra;
1322     }
1323 }
1324
1325 /* This function constructs an ordered list which represents how much the
1326  * different colors are used. So for instance (100, 100, 500) means that one
1327  * color is used for 500 pixels, another for 100 pixels and another for 100
1328  * pixels. It's tuned for performance. You might not like the way I've hardcoded
1329  * the maxc ;-) and you might want to change the name... */
1330 /* Uses octt_histo */
1331 int
1332 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1333   struct octt *ct;
1334   int x,y;
1335   int colorcnt;
1336   unsigned int *col_usage_it;
1337   i_sample_t * samp;
1338   int channels[3];
1339   int *samp_chans;
1340   
1341   int xsize = im->xsize; 
1342   int ysize = im->ysize;
1343   int samp_cnt = 3 * xsize;
1344   ct = octt_new();
1345   
1346   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1347   
1348   if (im->channels >= 3) {
1349     samp_chans = NULL;
1350   }
1351   else {
1352     channels[0] = channels[1] = channels[2] = 0;
1353     samp_chans = channels;
1354   }
1355
1356   colorcnt = 0;
1357   for(y = 0; y < ysize; ) {
1358     i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1359     for(x = 0; x < samp_cnt; ) {
1360       colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1361       x += 3;
1362       if (colorcnt > maxc) { 
1363         octt_delete(ct); 
1364         return -1; 
1365       }
1366     }
1367   }
1368   myfree(samp);
1369   /* Now that we know the number of colours... */
1370   col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1371   octt_histo(ct, &col_usage_it);
1372   hpsort(colorcnt, *col_usage);
1373   octt_delete(ct);
1374   return colorcnt;
1375 }
1376
1377 /*
1378 =back
1379
1380 =head2 8-bit per sample image internal functions
1381
1382 These are the functions installed in an 8-bit per sample image.
1383
1384 =over
1385
1386 =item i_ppix_d(im, x, y, col)
1387
1388 Internal function.
1389
1390 This is the function kept in the i_f_ppix member of an i_img object.
1391 It does a normal store of a pixel into the image with range checking.
1392
1393 Returns 0 if the pixel could be set, -1 otherwise.
1394
1395 =cut
1396 */
1397 static
1398 int
1399 i_ppix_d(i_img *im, int x, int y, const i_color *val) {
1400   int ch;
1401   
1402   if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1403     for(ch=0;ch<im->channels;ch++)
1404       if (im->ch_mask&(1<<ch)) 
1405         im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1406     return 0;
1407   }
1408   return -1; /* error was clipped */
1409 }
1410
1411 /*
1412 =item i_gpix_d(im, x, y, &col)
1413
1414 Internal function.
1415
1416 This is the function kept in the i_f_gpix member of an i_img object.
1417 It does normal retrieval of a pixel from the image with range checking.
1418
1419 Returns 0 if the pixel could be set, -1 otherwise.
1420
1421 =cut
1422 */
1423 static
1424 int 
1425 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1426   int ch;
1427   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1428     for(ch=0;ch<im->channels;ch++) 
1429       val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1430     return 0;
1431   }
1432   for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1433   return -1; /* error was cliped */
1434 }
1435
1436 /*
1437 =item i_glin_d(im, l, r, y, vals)
1438
1439 Reads a line of data from the image, storing the pixels at vals.
1440
1441 The line runs from (l,y) inclusive to (r,y) non-inclusive
1442
1443 vals should point at space for (r-l) pixels.
1444
1445 l should never be less than zero (to avoid confusion about where to
1446 put the pixels in vals).
1447
1448 Returns the number of pixels copied (eg. if r, l or y is out of range)
1449
1450 =cut
1451 */
1452 static
1453 int
1454 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1455   int ch, count, i;
1456   unsigned char *data;
1457   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1458     if (r > im->xsize)
1459       r = im->xsize;
1460     data = im->idata + (l+y*im->xsize) * im->channels;
1461     count = r - l;
1462     for (i = 0; i < count; ++i) {
1463       for (ch = 0; ch < im->channels; ++ch)
1464         vals[i].channel[ch] = *data++;
1465     }
1466     return count;
1467   }
1468   else {
1469     return 0;
1470   }
1471 }
1472
1473 /*
1474 =item i_plin_d(im, l, r, y, vals)
1475
1476 Writes a line of data into the image, using the pixels at vals.
1477
1478 The line runs from (l,y) inclusive to (r,y) non-inclusive
1479
1480 vals should point at (r-l) pixels.
1481
1482 l should never be less than zero (to avoid confusion about where to
1483 get the pixels in vals).
1484
1485 Returns the number of pixels copied (eg. if r, l or y is out of range)
1486
1487 =cut
1488 */
1489 static
1490 int
1491 i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) {
1492   int ch, count, i;
1493   unsigned char *data;
1494   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1495     if (r > im->xsize)
1496       r = im->xsize;
1497     data = im->idata + (l+y*im->xsize) * im->channels;
1498     count = r - l;
1499     for (i = 0; i < count; ++i) {
1500       for (ch = 0; ch < im->channels; ++ch) {
1501         if (im->ch_mask & (1 << ch)) 
1502           *data = vals[i].channel[ch];
1503         ++data;
1504       }
1505     }
1506     return count;
1507   }
1508   else {
1509     return 0;
1510   }
1511 }
1512
1513 /*
1514 =item i_ppixf_d(im, x, y, val)
1515
1516 =cut
1517 */
1518 static
1519 int
1520 i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) {
1521   int ch;
1522   
1523   if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1524     for(ch=0;ch<im->channels;ch++)
1525       if (im->ch_mask&(1<<ch)) {
1526         im->idata[(x+y*im->xsize)*im->channels+ch] = 
1527           SampleFTo8(val->channel[ch]);
1528       }
1529     return 0;
1530   }
1531   return -1; /* error was clipped */
1532 }
1533
1534 /*
1535 =item i_gpixf_d(im, x, y, val)
1536
1537 =cut
1538 */
1539 static
1540 int
1541 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1542   int ch;
1543   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1544     for(ch=0;ch<im->channels;ch++) {
1545       val->channel[ch] = 
1546         Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1547     }
1548     return 0;
1549   }
1550   return -1; /* error was cliped */
1551 }
1552
1553 /*
1554 =item i_glinf_d(im, l, r, y, vals)
1555
1556 Reads a line of data from the image, storing the pixels at vals.
1557
1558 The line runs from (l,y) inclusive to (r,y) non-inclusive
1559
1560 vals should point at space for (r-l) pixels.
1561
1562 l should never be less than zero (to avoid confusion about where to
1563 put the pixels in vals).
1564
1565 Returns the number of pixels copied (eg. if r, l or y is out of range)
1566
1567 =cut
1568 */
1569 static
1570 int
1571 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1572   int ch, count, i;
1573   unsigned char *data;
1574   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1575     if (r > im->xsize)
1576       r = im->xsize;
1577     data = im->idata + (l+y*im->xsize) * im->channels;
1578     count = r - l;
1579     for (i = 0; i < count; ++i) {
1580       for (ch = 0; ch < im->channels; ++ch)
1581         vals[i].channel[ch] = Sample8ToF(*data++);
1582     }
1583     return count;
1584   }
1585   else {
1586     return 0;
1587   }
1588 }
1589
1590 /*
1591 =item i_plinf_d(im, l, r, y, vals)
1592
1593 Writes a line of data into the image, using the pixels at vals.
1594
1595 The line runs from (l,y) inclusive to (r,y) non-inclusive
1596
1597 vals should point at (r-l) pixels.
1598
1599 l should never be less than zero (to avoid confusion about where to
1600 get the pixels in vals).
1601
1602 Returns the number of pixels copied (eg. if r, l or y is out of range)
1603
1604 =cut
1605 */
1606 static
1607 int
1608 i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) {
1609   int ch, count, i;
1610   unsigned char *data;
1611   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1612     if (r > im->xsize)
1613       r = im->xsize;
1614     data = im->idata + (l+y*im->xsize) * im->channels;
1615     count = r - l;
1616     for (i = 0; i < count; ++i) {
1617       for (ch = 0; ch < im->channels; ++ch) {
1618         if (im->ch_mask & (1 << ch)) 
1619           *data = SampleFTo8(vals[i].channel[ch]);
1620         ++data;
1621       }
1622     }
1623     return count;
1624   }
1625   else {
1626     return 0;
1627   }
1628 }
1629
1630 /*
1631 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1632
1633 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1634 for the channels specified by chans, an array of int with chan_count
1635 elements.
1636
1637 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1638
1639 =cut
1640 */
1641 static
1642 int
1643 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, 
1644               const int *chans, int chan_count) {
1645   int ch, count, i, w;
1646   unsigned char *data;
1647
1648   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1649     if (r > im->xsize)
1650       r = im->xsize;
1651     data = im->idata + (l+y*im->xsize) * im->channels;
1652     w = r - l;
1653     count = 0;
1654
1655     if (chans) {
1656       /* make sure we have good channel numbers */
1657       for (ch = 0; ch < chan_count; ++ch) {
1658         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1659           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1660           return 0;
1661         }
1662       }
1663       for (i = 0; i < w; ++i) {
1664         for (ch = 0; ch < chan_count; ++ch) {
1665           *samps++ = data[chans[ch]];
1666           ++count;
1667         }
1668         data += im->channels;
1669       }
1670     }
1671     else {
1672       if (chan_count <= 0 || chan_count > im->channels) {
1673         i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
1674                       chan_count);
1675         return 0;
1676       }
1677       for (i = 0; i < w; ++i) {
1678         for (ch = 0; ch < chan_count; ++ch) {
1679           *samps++ = data[ch];
1680           ++count;
1681         }
1682         data += im->channels;
1683       }
1684     }
1685
1686     return count;
1687   }
1688   else {
1689     return 0;
1690   }
1691 }
1692
1693 /*
1694 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1695
1696 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1697 for the channels specified by chan_mask, where bit 0 is the first
1698 channel.
1699
1700 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1701
1702 =cut
1703 */
1704 static
1705 int
1706 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, 
1707            const int *chans, int chan_count) {
1708   int ch, count, i, w;
1709   unsigned char *data;
1710   for (ch = 0; ch < chan_count; ++ch) {
1711     if (chans[ch] < 0 || chans[ch] >= im->channels) {
1712       i_push_errorf(0, "No channel %d in this image", chans[ch]);
1713     }
1714   }
1715   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1716     if (r > im->xsize)
1717       r = im->xsize;
1718     data = im->idata + (l+y*im->xsize) * im->channels;
1719     w = r - l;
1720     count = 0;
1721
1722     if (chans) {
1723       /* make sure we have good channel numbers */
1724       for (ch = 0; ch < chan_count; ++ch) {
1725         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1726           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1727           return 0;
1728         }
1729       }
1730       for (i = 0; i < w; ++i) {
1731         for (ch = 0; ch < chan_count; ++ch) {
1732           *samps++ = Sample8ToF(data[chans[ch]]);
1733           ++count;
1734         }
1735         data += im->channels;
1736       }
1737     }
1738     else {
1739       if (chan_count <= 0 || chan_count > im->channels) {
1740         i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", 
1741                       chan_count);
1742         return 0;
1743       }
1744       for (i = 0; i < w; ++i) {
1745         for (ch = 0; ch < chan_count; ++ch) {
1746           *samps++ = Sample8ToF(data[ch]);
1747           ++count;
1748         }
1749         data += im->channels;
1750       }
1751     }
1752     return count;
1753   }
1754   else {
1755     return 0;
1756   }
1757 }
1758
1759 /*
1760 =back
1761
1762 =head2 Image method wrappers
1763
1764 These functions provide i_fsample_t functions in terms of their
1765 i_sample_t versions.
1766
1767 =over
1768
1769 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1770
1771 =cut
1772 */
1773
1774 int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) {
1775   i_color temp;
1776   int ch;
1777
1778   for (ch = 0; ch < im->channels; ++ch)
1779     temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1780   
1781   return i_ppix(im, x, y, &temp);
1782 }
1783
1784 /*
1785 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1786
1787 =cut
1788 */
1789 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1790   i_color temp;
1791   int ch;
1792
1793   if (i_gpix(im, x, y, &temp)) {
1794     for (ch = 0; ch < im->channels; ++ch)
1795       pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1796     return 0;
1797   }
1798   else 
1799     return -1;
1800 }
1801
1802 /*
1803 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1804
1805 =cut
1806 */
1807 int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) {
1808   i_color *work;
1809
1810   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1811     if (r > im->xsize)
1812       r = im->xsize;
1813     if (r > l) {
1814       int ret;
1815       int i, ch;
1816       work = mymalloc(sizeof(i_color) * (r-l));
1817       for (i = 0; i < r-l; ++i) {
1818         for (ch = 0; ch < im->channels; ++ch) 
1819           work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1820       }
1821       ret = i_plin(im, l, r, y, work);
1822       myfree(work);
1823
1824       return ret;
1825     }
1826     else {
1827       return 0;
1828     }
1829   }
1830   else {
1831     return 0;
1832   }
1833 }
1834
1835 /*
1836 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1837
1838 =cut
1839 */
1840 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1841   i_color *work;
1842
1843   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1844     if (r > im->xsize)
1845       r = im->xsize;
1846     if (r > l) {
1847       int ret;
1848       int i, ch;
1849       work = mymalloc(sizeof(i_color) * (r-l));
1850       ret = i_plin(im, l, r, y, work);
1851       for (i = 0; i < r-l; ++i) {
1852         for (ch = 0; ch < im->channels; ++ch) 
1853           pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1854       }
1855       myfree(work);
1856
1857       return ret;
1858     }
1859     else {
1860       return 0;
1861     }
1862   }
1863   else {
1864     return 0;
1865   }
1866 }
1867
1868 /*
1869 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1870
1871 =cut
1872 */
1873 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, 
1874                 int const *chans, int chan_count) {
1875   i_sample_t *work;
1876
1877   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1878     if (r > im->xsize)
1879       r = im->xsize;
1880     if (r > l) {
1881       int ret;
1882       int i;
1883       work = mymalloc(sizeof(i_sample_t) * (r-l));
1884       ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1885       for (i = 0; i < ret; ++i) {
1886           samp[i] = Sample8ToF(work[i]);
1887       }
1888       myfree(work);
1889
1890       return ret;
1891     }
1892     else {
1893       return 0;
1894     }
1895   }
1896   else {
1897     return 0;
1898   }
1899 }
1900
1901 /*
1902 =back
1903
1904 =head2 Palette wrapper functions
1905
1906 Used for virtual images, these forward palette calls to a wrapped image, 
1907 assuming the wrapped image is the first pointer in the structure that 
1908 im->ext_data points at.
1909
1910 =over
1911
1912 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1913
1914 =cut
1915 */
1916 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1917   return i_addcolors(*(i_img **)im->ext_data, colors, count);
1918 }
1919
1920 /*
1921 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1922
1923 =cut
1924 */
1925 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1926   return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1927 }
1928
1929 /*
1930 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1931
1932 =cut
1933 */
1934 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1935   return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1936 }
1937
1938 /*
1939 =item i_colorcount_forward(i_img *im)
1940
1941 =cut
1942 */
1943 int i_colorcount_forward(i_img *im) {
1944   return i_colorcount(*(i_img **)im->ext_data);
1945 }
1946
1947 /*
1948 =item i_maxcolors_forward(i_img *im)
1949
1950 =cut
1951 */
1952 int i_maxcolors_forward(i_img *im) {
1953   return i_maxcolors(*(i_img **)im->ext_data);
1954 }
1955
1956 /*
1957 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1958
1959 =cut
1960 */
1961 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1962   return i_findcolor(*(i_img **)im->ext_data, color, entry);
1963 }
1964
1965 /*
1966 =back
1967
1968 =head2 Fallback handler
1969
1970 =over
1971
1972 =item i_gsamp_bits_fb
1973
1974 =cut
1975 */
1976
1977 int 
1978 i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, 
1979                 const int *chans, int chan_count, int bits) {
1980   if (bits < 1 || bits > 32) {
1981     i_push_error(0, "Invalid bits, must be 1..32");
1982     return -1;
1983   }
1984
1985   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1986     double scale;
1987     int ch, count, i, w;
1988     
1989     if (bits == 32)
1990       scale = 4294967295.0;
1991     else
1992       scale = (double)(1 << bits) - 1;
1993
1994     if (r > im->xsize)
1995       r = im->xsize;
1996     w = r - l;
1997     count = 0;
1998
1999     if (chans) {
2000       /* make sure we have good channel numbers */
2001       for (ch = 0; ch < chan_count; ++ch) {
2002         if (chans[ch] < 0 || chans[ch] >= im->channels) {
2003           i_push_errorf(0, "No channel %d in this image", chans[ch]);
2004           return -1;
2005         }
2006       }
2007       for (i = 0; i < w; ++i) {
2008         i_fcolor c;
2009         i_gpixf(im, l+i, y, &c);
2010         for (ch = 0; ch < chan_count; ++ch) {
2011           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
2012           ++count;
2013         }
2014       }
2015     }
2016     else {
2017       if (chan_count <= 0 || chan_count > im->channels) {
2018         i_push_error(0, "Invalid channel count");
2019         return -1;
2020       }
2021       for (i = 0; i < w; ++i) {
2022         i_fcolor c;
2023         i_gpixf(im, l+i, y, &c);
2024         for (ch = 0; ch < chan_count; ++ch) {
2025           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
2026           ++count;
2027         }
2028       }
2029     }
2030
2031     return count;
2032   }
2033   else {
2034     i_push_error(0, "Image position outside of image");
2035     return -1;
2036   }
2037 }
2038
2039 /*
2040 =back
2041
2042 =head2 Stream reading and writing wrapper functions
2043
2044 =over
2045
2046 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
2047
2048 Performs general read buffering for file readers that permit reading
2049 to be done through a callback.
2050
2051 The final callback gets two parameters, a I<need> value, and a I<want>
2052 value, where I<need> is the amount of data that the file library needs
2053 to read, and I<want> is the amount of space available in the buffer
2054 maintained by these functions.
2055
2056 This means if you need to read from a stream that you don't know the
2057 length of, you can return I<need> bytes, taking the performance hit of
2058 possibly expensive callbacks (eg. back to perl code), or if you are
2059 reading from a stream where it doesn't matter if some data is lost, or
2060 if the total length of the stream is known, you can return I<want>
2061 bytes.
2062
2063 =cut 
2064 */
2065
2066 int
2067 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
2068   int total;
2069
2070   if (length < gci->length - gci->cpos) {
2071     /* simplest case */
2072     memcpy(buf, gci->buffer+gci->cpos, length);
2073     gci->cpos += length;
2074     return length;
2075   }
2076   
2077   total = 0;
2078   memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
2079   total  += gci->length - gci->cpos;
2080   length -= gci->length - gci->cpos;
2081   buf    += gci->length - gci->cpos;
2082   if (length < (int)sizeof(gci->buffer)) {
2083     int did_read;
2084     int copy_size;
2085     while (length
2086            && (did_read = (gci->cb)(gci->userdata, gci->buffer, length, 
2087                                     sizeof(gci->buffer))) > 0) {
2088       gci->cpos = 0;
2089       gci->length = did_read;
2090
2091       copy_size = i_min(length, gci->length);
2092       memcpy(buf, gci->buffer, copy_size);
2093       gci->cpos += copy_size;
2094       buf += copy_size;
2095       total += copy_size;
2096       length -= copy_size;
2097     }
2098   }
2099   else {
2100     /* just read the rest - too big for our buffer*/
2101     int did_read;
2102     while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
2103       length -= did_read;
2104       total += did_read;
2105       buf += did_read;
2106     }
2107   }
2108   return total;
2109 }
2110
2111 /*
2112 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
2113
2114 For use by callback file readers to initialize the reader buffer.
2115
2116 Allocates, initializes and returns the reader buffer.
2117
2118 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
2119
2120 =cut
2121 */
2122 i_gen_read_data *
2123 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
2124   i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
2125   self->cb = cb;
2126   self->userdata = userdata;
2127   self->length = 0;
2128   self->cpos = 0;
2129
2130   return self;
2131 }
2132
2133 /*
2134 =item i_free_gen_read_data(i_gen_read_data *)
2135
2136 Cleans up.
2137
2138 =cut
2139 */
2140 void i_free_gen_read_data(i_gen_read_data *self) {
2141   myfree(self);
2142 }
2143
2144 /*
2145 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
2146
2147 Performs write buffering for a callback based file writer.
2148
2149 Failures are considered fatal, if a write fails then data will be
2150 dropped.
2151
2152 =cut
2153 */
2154 int 
2155 i_gen_writer(
2156 i_gen_write_data *self, 
2157 char const *data, 
2158 int size)
2159 {
2160   if (self->filledto && self->filledto+size > self->maxlength) {
2161     if (self->cb(self->userdata, self->buffer, self->filledto)) {
2162       self->filledto = 0;
2163     }
2164     else {
2165       self->filledto = 0;
2166       return 0;
2167     }
2168   }
2169   if (self->filledto+size <= self->maxlength) {
2170     /* just save it */
2171     memcpy(self->buffer+self->filledto, data, size);
2172     self->filledto += size;
2173     return 1;
2174   }
2175   /* doesn't fit - hand it off */
2176   return self->cb(self->userdata, data, size);
2177 }
2178
2179 /*
2180 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2181
2182 Allocates and initializes the data structure used by i_gen_writer.
2183
2184 This should be released with L<image.c/i_free_gen_write_data>
2185
2186 =cut
2187 */
2188 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, 
2189                                        char *userdata, int max_length)
2190 {
2191   i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2192   self->cb = cb;
2193   self->userdata = userdata;
2194   self->maxlength = i_min(max_length, sizeof(self->buffer));
2195   if (self->maxlength < 0)
2196     self->maxlength = sizeof(self->buffer);
2197   self->filledto = 0;
2198
2199   return self;
2200 }
2201
2202 /*
2203 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2204
2205 Cleans up the write buffer.
2206
2207 Will flush any left-over data if I<flush> is non-zero.
2208
2209 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2210
2211 Return zero only if flush is non-zero and info->cb() returns zero.
2212 ie. if it fails.
2213
2214 =cut
2215 */
2216
2217 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2218 {
2219   int result = !flush || 
2220     info->filledto == 0 ||
2221     info->cb(info->userdata, info->buffer, info->filledto);
2222   myfree(info);
2223
2224   return result;
2225 }
2226
2227 struct magic_entry {
2228   unsigned char *magic;
2229   size_t magic_size;
2230   char *name;
2231   unsigned char *mask;  
2232 };
2233
2234 static int
2235 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
2236   if (length < magic->magic_size)
2237     return 0;
2238   if (magic->mask) {
2239     int i;
2240     unsigned char *bufp = buffer, 
2241       *maskp = magic->mask, 
2242       *magicp = magic->magic;
2243
2244     for (i = 0; i < magic->magic_size; ++i) {
2245       int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
2246       ++maskp;
2247
2248       if ((*bufp++ & mask) != (*magicp++ & mask)) 
2249         return 0;
2250     }
2251
2252     return 1;
2253   }
2254   else {
2255     return !memcmp(magic->magic, buffer, magic->magic_size);
2256   }
2257 }
2258
2259 /*
2260 =item i_test_format_probe(io_glue *data, int length)
2261
2262 Check the beginning of the supplied file for a 'magic number'
2263
2264 =cut
2265 */
2266
2267 #define FORMAT_ENTRY(magic, type) \
2268   { (unsigned char *)(magic ""), sizeof(magic)-1, type }
2269 #define FORMAT_ENTRY2(magic, type, mask) \
2270   { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
2271
2272 const char *
2273 i_test_format_probe(io_glue *data, int length) {
2274   static const struct magic_entry formats[] = {
2275     FORMAT_ENTRY("\xFF\xD8", "jpeg"),
2276     FORMAT_ENTRY("GIF87a", "gif"),
2277     FORMAT_ENTRY("GIF89a", "gif"),
2278     FORMAT_ENTRY("MM\0*", "tiff"),
2279     FORMAT_ENTRY("II*\0", "tiff"),
2280     FORMAT_ENTRY("BM", "bmp"),
2281     FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
2282     FORMAT_ENTRY("P1", "pnm"),
2283     FORMAT_ENTRY("P2", "pnm"),
2284     FORMAT_ENTRY("P3", "pnm"),
2285     FORMAT_ENTRY("P4", "pnm"),
2286     FORMAT_ENTRY("P5", "pnm"),
2287     FORMAT_ENTRY("P6", "pnm"),
2288     FORMAT_ENTRY("/* XPM", "xpm"),
2289     FORMAT_ENTRY("\x8aMNG", "mng"),
2290     FORMAT_ENTRY("\x8aJNG", "jng"),
2291     /* SGI RGB - with various possible parameters to avoid false positives
2292        on similar files 
2293        values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
2294     */
2295     FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
2296     FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
2297     FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
2298     FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
2299     
2300     FORMAT_ENTRY2("FORM    ILBM", "ilbm", "xxxx    xxxx"),
2301
2302     /* different versions of PCX format 
2303        http://www.fileformat.info/format/pcx/
2304     */
2305     FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
2306     FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
2307     FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
2308     FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
2309     FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
2310
2311     /* FITS - http://fits.gsfc.nasa.gov/ */
2312     FORMAT_ENTRY("SIMPLE  =", "fits"),
2313
2314     /* PSD - Photoshop */
2315     FORMAT_ENTRY("8BPS\x00\x01", "psd"),
2316     
2317     /* EPS - Encapsulated Postscript */
2318     /* only reading 18 chars, so we don't include the F in EPSF */
2319     FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
2320
2321     /* Utah RLE */
2322     FORMAT_ENTRY("\x52\xCC", "utah"),
2323
2324     /* GZIP compressed, only matching deflate for now */
2325     FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
2326
2327     /* bzip2 compressed */
2328     FORMAT_ENTRY("BZh", "bzip2"),
2329   };
2330   static const struct magic_entry more_formats[] = {
2331     /* these were originally both listed as ico, but cur files can
2332        include hotspot information */
2333     FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
2334     FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
2335     FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07", 
2336                   "xwd", "    xxxx"), /* X Windows Dump */
2337   };
2338
2339   unsigned int i;
2340   unsigned char head[18];
2341   ssize_t rc;
2342
2343   io_glue_commit_types(data);
2344   rc = data->readcb(data, head, 18);
2345   if (rc == -1) return NULL;
2346   data->seekcb(data, -rc, SEEK_CUR);
2347
2348   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
2349     struct magic_entry const *entry = formats + i;
2350
2351     if (test_magic(head, rc, entry)) 
2352       return entry->name;
2353   }
2354
2355   if ((rc == 18) &&
2356       tga_header_verify(head))
2357     return "tga";
2358
2359   for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) { 
2360     struct magic_entry const *entry = more_formats + i;
2361
2362     if (test_magic(head, rc, entry)) 
2363       return entry->name;
2364   }
2365
2366   return NULL;
2367 }
2368
2369 /*
2370 =item i_img_is_monochrome(img, &zero_is_white)
2371
2372 Tests an image to check it meets our monochrome tests.
2373
2374 The idea is that a file writer can use this to test where it should
2375 write the image in whatever bi-level format it uses, eg. pbm for pnm.
2376
2377 For performance of encoders we require monochrome images:
2378
2379 =over
2380
2381 =item *
2382
2383 be paletted
2384
2385 =item *
2386
2387 have a palette of two colors, containing only (0,0,0) and
2388 (255,255,255) in either order.
2389
2390 =back
2391
2392 zero_is_white is set to non-zero iff the first palette entry is white.
2393
2394 =cut
2395 */
2396
2397 int
2398 i_img_is_monochrome(i_img *im, int *zero_is_white) {
2399   if (im->type == i_palette_type
2400       && i_colorcount(im) == 2) {
2401     i_color colors[2];
2402     i_getcolors(im, 0, colors, 2);
2403     if (im->channels == 3) {
2404       if (colors[0].rgb.r == 255 && 
2405           colors[0].rgb.g == 255 &&
2406           colors[0].rgb.b == 255 &&
2407           colors[1].rgb.r == 0 &&
2408           colors[1].rgb.g == 0 &&
2409           colors[1].rgb.b == 0) {
2410         *zero_is_white = 1;
2411         return 1;
2412       }
2413       else if (colors[0].rgb.r == 0 && 
2414                colors[0].rgb.g == 0 &&
2415                colors[0].rgb.b == 0 &&
2416                colors[1].rgb.r == 255 &&
2417                colors[1].rgb.g == 255 &&
2418                colors[1].rgb.b == 255) {
2419         *zero_is_white = 0;
2420         return 1;
2421       }
2422     }
2423     else if (im->channels == 1) {
2424       if (colors[0].channel[0] == 255 &&
2425           colors[1].channel[0] == 0) {
2426         *zero_is_white = 1;
2427         return 1;
2428       }
2429       else if (colors[0].channel[0] == 0 &&
2430                colors[1].channel[0] == 255) {
2431         *zero_is_white = 0;
2432         return 1;         
2433       }
2434     }
2435   }
2436
2437   *zero_is_white = 0;
2438   return 0;
2439 }
2440
2441 /*
2442 =item i_get_file_background(im, &bg)
2443
2444 Retrieve the file write background color tag from the image.
2445
2446 If not present, returns black.
2447
2448 =cut
2449 */
2450
2451 void
2452 i_get_file_background(i_img *im, i_color *bg) {
2453   if (!i_tags_get_color(&im->tags, "i_background", 0, bg)) {
2454     /* black default */
2455     bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
2456   }
2457   /* always full alpha */
2458   bg->channel[3] = 255;
2459 }
2460
2461 /*
2462 =item i_get_file_backgroundf(im, &bg)
2463
2464 Retrieve the file write background color tag from the image as a
2465 floating point color.
2466
2467 Implemented in terms of i_get_file_background().
2468
2469 If not present, returns black.
2470
2471 =cut
2472 */
2473
2474 void
2475 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
2476   i_color bg;
2477
2478   i_get_file_background(im, &bg);
2479   fbg->rgba.r = Sample8ToF(bg.rgba.r);
2480   fbg->rgba.g = Sample8ToF(bg.rgba.g);
2481   fbg->rgba.b = Sample8ToF(bg.rgba.b);
2482   fbg->rgba.a = 1.0;
2483 }
2484
2485 /*
2486 =back
2487
2488 =head1 AUTHOR
2489
2490 Arnar M. Hrafnkelsson <addi@umich.edu>
2491
2492 Tony Cook <tony@develop-help.com>
2493
2494 =head1 SEE ALSO
2495
2496 L<Imager>, L<gif.c>
2497
2498 =cut
2499 */