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