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