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