]> git.imager.perl.org - imager.git/blob - image.c
doc cleanups for Imager::Fill
[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 void i_linker_bug_fake(void) { ceil(1); }
41
42 /*
43 =item i_img_alloc()
44 =category Image Implementation
45
46 Allocates a new i_img structure.
47
48 When implementing a new image type perform the following steps in your
49 image object creation function:
50
51 =over
52
53 =item 1.
54
55 allocate the image with i_img_alloc().
56
57 =item 2.
58
59 initialize any function pointers or other data as needed, you can
60 overwrite the whole block if you need to.
61
62 =item 3.
63
64 initialize Imager's internal data by calling i_img_init() on the image
65 object.
66
67 =back
68
69 =cut
70 */
71
72 i_img *
73 i_img_alloc(void) {
74   return mymalloc(sizeof(i_img));
75 }
76
77 /*
78 =item i_img_init(C<img>)
79 =category Image Implementation
80
81 Imager internal initialization of images.
82
83 Currently this does very little, in the future it may be used to
84 support threads, or color profiles.
85
86 =cut
87 */
88
89 void
90 i_img_init(i_img *img) {
91   img->im_data = NULL;
92 }
93
94 /* 
95 =item ICL_new_internal(r, g, b, a)
96
97 Return a new color object with values passed to it.
98
99    r - red   component (range: 0 - 255)
100    g - green component (range: 0 - 255)
101    b - blue  component (range: 0 - 255)
102    a - alpha component (range: 0 - 255)
103
104 =cut
105 */
106
107 i_color *
108 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
109   i_color *cl = NULL;
110
111   mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
112
113   if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
114   cl->rgba.r = r;
115   cl->rgba.g = g;
116   cl->rgba.b = b;
117   cl->rgba.a = a;
118   mm_log((1,"(%p) <- ICL_new_internal\n",cl));
119   return cl;
120 }
121
122
123 /*
124 =item ICL_set_internal(cl, r, g, b, a)
125
126  Overwrite a color with new values.
127
128    cl - pointer to color object
129    r - red   component (range: 0 - 255)
130    g - green component (range: 0 - 255)
131    b - blue  component (range: 0 - 255)
132    a - alpha component (range: 0 - 255)
133
134 =cut
135 */
136
137 i_color *
138 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
139   mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
140   if (cl == NULL)
141     if ( (cl=mymalloc(sizeof(i_color))) == NULL)
142       i_fatal(2,"malloc() error\n");
143   cl->rgba.r=r;
144   cl->rgba.g=g;
145   cl->rgba.b=b;
146   cl->rgba.a=a;
147   mm_log((1,"(%p) <- ICL_set_internal\n",cl));
148   return cl;
149 }
150
151
152 /* 
153 =item ICL_add(dst, src, ch)
154
155 Add src to dst inplace - dst is modified.
156
157    dst - pointer to destination color object
158    src - pointer to color object that is added
159    ch - number of channels
160
161 =cut
162 */
163
164 void
165 ICL_add(i_color *dst,i_color *src,int ch) {
166   int tmp,i;
167   for(i=0;i<ch;i++) {
168     tmp=dst->channel[i]+src->channel[i];
169     dst->channel[i]= tmp>255 ? 255:tmp;
170   }
171 }
172
173 /* 
174 =item ICL_info(cl)
175
176 Dump color information to log - strictly for debugging.
177
178    cl - pointer to color object
179
180 =cut
181 */
182
183 void
184 ICL_info(i_color const *cl) {
185   mm_log((1,"i_color_info(cl* %p)\n",cl));
186   mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
187 }
188
189 /* 
190 =item ICL_DESTROY
191
192 Destroy ancillary data for Color object.
193
194    cl - pointer to color object
195
196 =cut
197 */
198
199 void
200 ICL_DESTROY(i_color *cl) {
201   mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
202   myfree(cl);
203 }
204
205 /*
206 =item i_fcolor_new(double r, double g, double b, double a)
207
208 =cut
209 */
210 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
211   i_fcolor *cl = NULL;
212
213   mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
214
215   if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
216   cl->rgba.r = r;
217   cl->rgba.g = g;
218   cl->rgba.b = b;
219   cl->rgba.a = a;
220   mm_log((1,"(%p) <- i_fcolor_new\n",cl));
221
222   return cl;
223 }
224
225 /*
226 =item i_fcolor_destroy(i_fcolor *cl) 
227
228 =cut
229 */
230 void i_fcolor_destroy(i_fcolor *cl) {
231   myfree(cl);
232 }
233
234 /* 
235 =item i_img_exorcise(im)
236
237 Free image data.
238
239    im - Image pointer
240
241 =cut
242 */
243
244 void
245 i_img_exorcise(i_img *im) {
246   mm_log((1,"i_img_exorcise(im* %p)\n",im));
247   i_tags_destroy(&im->tags);
248   if (im->i_f_destroy)
249     (im->i_f_destroy)(im);
250   if (im->idata != NULL) { myfree(im->idata); }
251   im->idata    = NULL;
252   im->xsize    = 0;
253   im->ysize    = 0;
254   im->channels = 0;
255
256   im->ext_data=NULL;
257 }
258
259 /* 
260 =item i_img_destroy(C<img>)
261 =order 90
262 =category Image creation/destruction
263 =synopsis i_img_destroy(img)
264
265 Destroy an image object
266
267 =cut
268 */
269
270 void
271 i_img_destroy(i_img *im) {
272   mm_log((1,"i_img_destroy(im %p)\n",im));
273   i_img_exorcise(im);
274   if (im) { myfree(im); }
275 }
276
277 /* 
278 =item i_img_info(im, info)
279
280 =category Image
281
282 Return image information
283
284    im - Image pointer
285    info - pointer to array to return data
286
287 info is an array of 4 integers with the following values:
288
289  info[0] - width
290  info[1] - height
291  info[2] - channels
292  info[3] - channel mask
293
294 =cut
295 */
296
297
298 void
299 i_img_info(i_img *im, i_img_dim *info) {
300   mm_log((1,"i_img_info(im %p)\n",im));
301   if (im != NULL) {
302     mm_log((1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
303             "mask=%ud\n",
304             i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
305     mm_log((1,"i_img_info: idata=%p\n",im->idata));
306     info[0] = im->xsize;
307     info[1] = im->ysize;
308     info[2] = im->channels;
309     info[3] = im->ch_mask;
310   } else {
311     info[0] = 0;
312     info[1] = 0;
313     info[2] = 0;
314     info[3] = 0;
315   }
316 }
317
318 /*
319 =item i_img_setmask(C<im>, C<ch_mask>)
320 =category Image Information
321 =synopsis // only channel 0 writable 
322 =synopsis i_img_setmask(img, 0x01);
323
324 Set the image channel mask for C<im> to C<ch_mask>.
325
326 The image channel mask gives some control over which channels can be
327 written to in the image.
328
329 =cut
330 */
331 void
332 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
333
334
335 /*
336 =item i_img_getmask(C<im>)
337 =category Image Information
338 =synopsis int mask = i_img_getmask(img);
339
340 Get the image channel mask for C<im>.
341
342 =cut
343 */
344 int
345 i_img_getmask(i_img *im) { return im->ch_mask; }
346
347 /*
348 =item i_img_getchannels(C<im>)
349 =category Image Information
350 =synopsis int channels = i_img_getchannels(img);
351
352 Get the number of channels in C<im>.
353
354 =cut
355 */
356 int
357 i_img_getchannels(i_img *im) { return im->channels; }
358
359 /*
360 =item i_img_get_width(C<im>)
361 =category Image Information
362 =synopsis i_img_dim width = i_img_get_width(im);
363
364 Returns the width in pixels of the image.
365
366 =cut
367 */
368 i_img_dim
369 i_img_get_width(i_img *im) {
370   return im->xsize;
371 }
372
373 /*
374 =item i_img_get_height(C<im>)
375 =category Image Information
376 =synopsis i_img_dim height = i_img_get_height(im);
377
378 Returns the height in pixels of the image.
379
380 =cut
381 */
382 i_img_dim
383 i_img_get_height(i_img *im) {
384   return im->ysize;
385 }
386
387 /*
388 =item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
389
390 =category Image
391
392 (C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
393 source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
394 the target image.  pass NULL in C<trans> for non transparent i_colors.
395
396 =cut
397 */
398
399 void
400 i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans) {
401   i_color pv;
402   i_img_dim x,y,t,ttx,tty,tt;
403   int ch;
404
405   mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
406           "to(" i_DFp "), trans* %p)\n",
407           im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
408   
409   if (x2<x1) { t=x1; x1=x2; x2=t; }
410   if (y2<y1) { t=y1; y1=y2; y2=t; }
411
412   ttx=tx;
413   for(x=x1;x<x2;x++)
414     {
415       tty=ty;
416       for(y=y1;y<y2;y++)
417         {
418           i_gpix(src,x,y,&pv);
419           if ( trans != NULL)
420           {
421             tt=0;
422             for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
423             if (tt) i_ppix(im,ttx,tty,&pv);
424           } else i_ppix(im,ttx,tty,&pv);
425           tty++;
426         }
427       ttx++;
428     }
429 }
430
431 /*
432 =item i_copy(source)
433
434 =category Image
435
436 Creates a new image that is a copy of the image C<source>.
437
438 Tags are not copied, only the image data.
439
440 Returns: i_img *
441
442 =cut
443 */
444
445 i_img *
446 i_copy(i_img *src) {
447   i_img_dim y, y1, x1;
448   i_img *im = i_sametype(src, src->xsize, src->ysize);
449
450   mm_log((1,"i_copy(src %p)\n", src));
451
452   if (!im)
453     return NULL;
454
455   x1 = src->xsize;
456   y1 = src->ysize;
457   if (src->type == i_direct_type) {
458     if (src->bits == i_8_bits) {
459       i_color *pv;
460       pv = mymalloc(sizeof(i_color) * x1);
461       
462       for (y = 0; y < y1; ++y) {
463         i_glin(src, 0, x1, y, pv);
464         i_plin(im, 0, x1, y, pv);
465       }
466       myfree(pv);
467     }
468     else {
469       i_fcolor *pv;
470
471       pv = mymalloc(sizeof(i_fcolor) * x1);
472       for (y = 0; y < y1; ++y) {
473         i_glinf(src, 0, x1, y, pv);
474         i_plinf(im, 0, x1, y, pv);
475       }
476       myfree(pv);
477     }
478   }
479   else {
480     i_palidx *vals;
481
482     vals = mymalloc(sizeof(i_palidx) * x1);
483     for (y = 0; y < y1; ++y) {
484       i_gpal(src, 0, x1, y, vals);
485       i_ppal(im, 0, x1, y, vals);
486     }
487     myfree(vals);
488   }
489
490   return im;
491 }
492
493 /*
494
495 http://en.wikipedia.org/wiki/Lanczos_resampling
496
497 */
498
499 static
500 float
501 Lanczos(float x) {
502   float PIx, PIx2;
503   
504   PIx = PI * x;
505   PIx2 = PIx / 2.0;
506   
507   if ((x >= 2.0) || (x <= -2.0)) return (0.0);
508   else if (x == 0.0) return (1.0);
509   else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
510 }
511
512
513 /*
514 =item i_scaleaxis(im, value, axis)
515
516 Returns a new image object which is I<im> scaled by I<value> along
517 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
518
519 =cut
520 */
521
522 i_img*
523 i_scaleaxis(i_img *im, double Value, int Axis) {
524   i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
525   i_img_dim LanczosWidthFactor;
526   float *l0, *l1;
527   double OldLocation;
528   i_img_dim T; 
529   double t;
530   float F, PictureValue[MAXCHANNELS];
531   short psave;
532   i_color val,val1,val2;
533   i_img *new_img;
534   int has_alpha = i_img_has_alpha(im);
535   int color_chans = i_img_color_channels(im);
536
537   i_clear_error();
538   mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
539
540   if (Axis == XAXIS) {
541     hsize = (i_img_dim)(0.5 + im->xsize * Value);
542     if (hsize < 1) {
543       hsize = 1;
544       Value = 1.0 / im->xsize;
545     }
546     vsize = im->ysize;
547     
548     jEnd = hsize;
549     iEnd = vsize;
550   } else {
551     hsize = im->xsize;
552     vsize = (i_img_dim)(0.5 + im->ysize * Value);
553
554     if (vsize < 1) {
555       vsize = 1;
556       Value = 1.0 / im->ysize;
557     }
558
559     jEnd = vsize;
560     iEnd = hsize;
561   }
562   
563   new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
564   if (!new_img) {
565     i_push_error(0, "cannot create output image");
566     return NULL;
567   }
568   
569   /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
570   LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value); 
571   lMax = LanczosWidthFactor << 1;
572   
573   l0 = mymalloc(lMax * sizeof(float));
574   l1 = mymalloc(lMax * sizeof(float));
575   
576   for (j=0; j<jEnd; j++) {
577     OldLocation = ((double) j) / Value;
578     T = (i_img_dim) (OldLocation);
579     F = OldLocation - T;
580     
581     for (l = 0; l<lMax; l++) {
582       l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
583       l1[l]        = Lanczos(((float) (l+1)      - F) / (float) LanczosWidthFactor);
584     }
585     
586     /* Make sure filter is normalized */
587     t = 0.0;
588     for(l=0; l<lMax; l++) {
589       t+=l0[l];
590       t+=l1[l];
591     }
592     t /= (double)LanczosWidthFactor;
593     
594     for(l=0; l<lMax; l++) {
595       l0[l] /= t;
596       l1[l] /= t;
597     }
598
599     if (Axis == XAXIS) {
600       
601       for (i=0; i<iEnd; i++) {
602         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
603         for (l=0; l<lMax; l++) {
604           i_img_dim mx = T-lMax+l+1;
605           i_img_dim Mx = T+l+1;
606           mx = (mx < 0) ? 0 : mx;
607           Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
608           
609           i_gpix(im, Mx, i, &val1);
610           i_gpix(im, mx, i, &val2);
611
612           if (has_alpha) {
613             i_sample_t alpha1 = val1.channel[color_chans];
614             i_sample_t alpha2 = val2.channel[color_chans];
615             for (k=0; k < color_chans; k++) {
616               PictureValue[k] += l1[l]        * val1.channel[k] * alpha1 / 255;
617               PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
618             }
619             PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
620             PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
621           }
622           else {
623             for (k=0; k<im->channels; k++) {
624               PictureValue[k] += l1[l]        * val1.channel[k];
625               PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
626             }
627           }
628         }
629
630         if (has_alpha) {
631           float fa = PictureValue[color_chans] / LanczosWidthFactor;
632           int alpha = minmax(0, 255, fa+0.5);
633           if (alpha) {
634             for (k = 0; k < color_chans; ++k) {
635               psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
636               val.channel[k]=minmax(0,255,psave);
637             }
638             val.channel[color_chans] = alpha;
639           }
640           else {
641             /* zero alpha, so the pixel has no color */
642             for (k = 0; k < im->channels; ++k)
643               val.channel[k] = 0;
644           }
645         }
646         else {
647           for(k=0;k<im->channels;k++) {
648             psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
649             val.channel[k]=minmax(0,255,psave);
650           }
651         }
652         i_ppix(new_img, j, i, &val);
653       }
654       
655     } else {
656       
657       for (i=0; i<iEnd; i++) {
658         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
659         for (l=0; l < lMax; l++) {
660           i_img_dim mx = T-lMax+l+1;
661           i_img_dim Mx = T+l+1;
662           mx = (mx < 0) ? 0 : mx;
663           Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
664
665           i_gpix(im, i, Mx, &val1);
666           i_gpix(im, i, mx, &val2);
667           if (has_alpha) {
668             i_sample_t alpha1 = val1.channel[color_chans];
669             i_sample_t alpha2 = val2.channel[color_chans];
670             for (k=0; k < color_chans; k++) {
671               PictureValue[k] += l1[l]        * val1.channel[k] * alpha1 / 255;
672               PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255;
673             }
674             PictureValue[color_chans] += l1[l] * val1.channel[color_chans];
675             PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans];
676           }
677           else {
678             for (k=0; k<im->channels; k++) {
679               PictureValue[k] += l1[l]        * val1.channel[k];
680               PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
681             }
682           }
683         }
684         if (has_alpha) {
685           float fa = PictureValue[color_chans] / LanczosWidthFactor;
686           int alpha = minmax(0, 255, fa+0.5);
687           if (alpha) {
688             for (k = 0; k < color_chans; ++k) {
689               psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa));
690               val.channel[k]=minmax(0,255,psave);
691             }
692             val.channel[color_chans] = alpha;
693           }
694           else {
695             for (k = 0; k < im->channels; ++k)
696               val.channel[k] = 0;
697           }
698         }
699         else {
700           for(k=0;k<im->channels;k++) {
701             psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
702             val.channel[k]=minmax(0,255,psave);
703           }
704         }
705         i_ppix(new_img, i, j, &val);
706       }
707       
708     }
709   }
710   myfree(l0);
711   myfree(l1);
712
713   mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
714
715   return new_img;
716 }
717
718
719 /* 
720 =item i_scale_nn(im, scx, scy)
721
722 Scale by using nearest neighbor 
723 Both axes scaled at the same time since 
724 nothing is gained by doing it in two steps 
725
726 =cut
727 */
728
729
730 i_img*
731 i_scale_nn(i_img *im, double scx, double scy) {
732
733   i_img_dim nxsize,nysize,nx,ny;
734   i_img *new_img;
735   i_color val;
736
737   mm_log((1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
738
739   nxsize = (i_img_dim) ((double) im->xsize * scx);
740   if (nxsize < 1) {
741     nxsize = 1;
742     scx = 1.0 / im->xsize;
743   }
744   nysize = (i_img_dim) ((double) im->ysize * scy);
745   if (nysize < 1) {
746     nysize = 1;
747     scy = 1.0 / im->ysize;
748   }
749   im_assert(scx != 0 && scy != 0);
750     
751   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
752   
753   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
754     i_gpix(im,((double)nx)/scx,((double)ny)/scy,&val);
755     i_ppix(new_img,nx,ny,&val);
756   }
757
758   mm_log((1,"(%p) <- i_scale_nn\n",new_img));
759
760   return new_img;
761 }
762
763 /*
764 =item i_sametype(C<im>, C<xsize>, C<ysize>)
765
766 =category Image creation/destruction
767 =synopsis i_img *img = i_sametype(src, width, height);
768
769 Returns an image of the same type (sample size, channels, paletted/direct).
770
771 For paletted images the palette is copied from the source.
772
773 =cut
774 */
775
776 i_img *i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
777   if (src->type == i_direct_type) {
778     if (src->bits == 8) {
779       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
780     }
781     else if (src->bits == i_16_bits) {
782       return i_img_16_new(xsize, ysize, src->channels);
783     }
784     else if (src->bits == i_double_bits) {
785       return i_img_double_new(xsize, ysize, src->channels);
786     }
787     else {
788       i_push_error(0, "Unknown image bits");
789       return NULL;
790     }
791   }
792   else {
793     i_color col;
794     int i;
795
796     i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
797     for (i = 0; i < i_colorcount(src); ++i) {
798       i_getcolors(src, i, &col, 1);
799       i_addcolors(targ, &col, 1);
800     }
801
802     return targ;
803   }
804 }
805
806 /*
807 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
808
809 =category Image creation/destruction
810 =synopsis i_img *img = i_sametype_chans(src, width, height, channels);
811
812 Returns an image of the same type (sample size).
813
814 For paletted images the equivalent direct type is returned.
815
816 =cut
817 */
818
819 i_img *i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
820   if (src->bits == 8) {
821     return i_img_empty_ch(NULL, xsize, ysize, channels);
822   }
823   else if (src->bits == i_16_bits) {
824     return i_img_16_new(xsize, ysize, channels);
825   }
826   else if (src->bits == i_double_bits) {
827     return i_img_double_new(xsize, ysize, channels);
828   }
829   else {
830     i_push_error(0, "Unknown image bits");
831     return NULL;
832   }
833 }
834
835 /*
836 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
837
838 Spatially transforms I<im> returning a new image.
839
840 opx for a length of opxl and opy for a length of opy are arrays of
841 operators that modify the x and y positions to retreive the pixel data from.
842
843 parm and parmlen define extra parameters that the operators may use.
844
845 Note that this function is largely superseded by the more flexible
846 L<transform.c/i_transform2>.
847
848 Returns the new image.
849
850 The operators for this function are defined in L<stackmach.c>.
851
852 =cut
853 */
854 i_img*
855 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
856   double rx,ry;
857   i_img_dim nxsize,nysize,nx,ny;
858   i_img *new_img;
859   i_color val;
860   
861   mm_log((1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
862
863   nxsize = im->xsize;
864   nysize = im->ysize ;
865   
866   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
867   /*   fprintf(stderr,"parm[2]=%f\n",parm[2]);   */
868   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
869     /*     parm[parmlen-2]=(double)nx;
870            parm[parmlen-1]=(double)ny; */
871
872     parm[0]=(double)nx;
873     parm[1]=(double)ny;
874
875     /*     fprintf(stderr,"(%d,%d) ->",nx,ny);  */
876     rx=i_op_run(opx,opxl,parm,parmlen);
877     ry=i_op_run(opy,opyl,parm,parmlen);
878     /*    fprintf(stderr,"(%f,%f)\n",rx,ry); */
879     i_gpix(im,rx,ry,&val);
880     i_ppix(new_img,nx,ny,&val);
881   }
882
883   mm_log((1,"(%p) <- i_transform\n",new_img));
884   return new_img;
885 }
886
887 /*
888 =item i_img_diff(im1, im2)
889
890 Calculates the sum of the squares of the differences between
891 correspoding channels in two images.
892
893 If the images are not the same size then only the common area is 
894 compared, hence even if images are different sizes this function 
895 can return zero.
896
897 =cut
898 */
899
900 float
901 i_img_diff(i_img *im1,i_img *im2) {
902   i_img_dim x, y, xb, yb;
903   int ch, chb;
904   float tdiff;
905   i_color val1,val2;
906
907   mm_log((1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
908
909   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
910   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
911   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
912
913   mm_log((1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
914           i_DFcp(xb,yb), chb));
915
916   tdiff=0;
917   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
918     i_gpix(im1,x,y,&val1);
919     i_gpix(im2,x,y,&val2);
920
921     for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
922   }
923   mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
924   return tdiff;
925 }
926
927 /*
928 =item i_img_diffd(im1, im2)
929
930 Calculates the sum of the squares of the differences between
931 correspoding channels in two images.
932
933 If the images are not the same size then only the common area is 
934 compared, hence even if images are different sizes this function 
935 can return zero.
936
937 This is like i_img_diff() but looks at floating point samples instead.
938
939 =cut
940 */
941
942 double
943 i_img_diffd(i_img *im1,i_img *im2) {
944   i_img_dim x, y, xb, yb;
945   int ch, chb;
946   double tdiff;
947   i_fcolor val1,val2;
948
949   mm_log((1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
950
951   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
952   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
953   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
954
955   mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
956           i_DFcp(xb, yb), chb));
957
958   tdiff=0;
959   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
960     i_gpixf(im1,x,y,&val1);
961     i_gpixf(im2,x,y,&val2);
962
963     for(ch=0;ch<chb;ch++) {
964       double sdiff = val1.channel[ch]-val2.channel[ch];
965       tdiff += sdiff * sdiff;
966     }
967   }
968   mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
969
970   return tdiff;
971 }
972
973 int
974 i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) {
975   i_img_dim x,y,xb,yb;
976   int ch, chb;
977   i_fcolor val1,val2;
978
979   if (what == NULL)
980     what = "(null)";
981
982   mm_log((1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
983
984   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
985   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
986   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
987
988   mm_log((1,"i_img_samef: b(" i_DFp ") chb=%d\n",
989           i_DFcp(xb, yb), chb));
990
991   for(y = 0; y < yb; y++) {
992     for(x = 0; x < xb; x++) {
993       i_gpixf(im1, x, y, &val1);
994       i_gpixf(im2, x, y, &val2);
995       
996       for(ch = 0; ch < chb; ch++) {
997         double sdiff = val1.channel[ch] - val2.channel[ch];
998         if (fabs(sdiff) > epsilon) {
999           mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n",
1000                   sdiff, i_DFcp(x, y)));
1001           return 0;
1002         }
1003       }
1004     }
1005   }
1006   mm_log((1,"i_img_samef <- same\n"));
1007
1008   return 1;
1009 }
1010
1011 /* just a tiny demo of haar wavelets */
1012
1013 i_img*
1014 i_haar(i_img *im) {
1015   i_img_dim mx,my;
1016   i_img_dim fx,fy;
1017   i_img_dim x,y;
1018   int ch,c;
1019   i_img *new_img,*new_img2;
1020   i_color val1,val2,dval1,dval2;
1021   
1022   mx=im->xsize;
1023   my=im->ysize;
1024   fx=(mx+1)/2;
1025   fy=(my+1)/2;
1026
1027
1028   /* horizontal pass */
1029   
1030   new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1031   new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1032
1033   c=0; 
1034   for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1035     i_gpix(im,x*2,y,&val1);
1036     i_gpix(im,x*2+1,y,&val2);
1037     for(ch=0;ch<im->channels;ch++) {
1038       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1039       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1040     }
1041     i_ppix(new_img,x,y,&dval1);
1042     i_ppix(new_img,x+fx,y,&dval2);
1043   }
1044
1045   for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1046     i_gpix(new_img,x,y*2,&val1);
1047     i_gpix(new_img,x,y*2+1,&val2);
1048     for(ch=0;ch<im->channels;ch++) {
1049       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1050       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1051     }
1052     i_ppix(new_img2,x,y,&dval1);
1053     i_ppix(new_img2,x,y+fy,&dval2);
1054   }
1055
1056   i_img_destroy(new_img);
1057   return new_img2;
1058 }
1059
1060 /* 
1061 =item i_count_colors(im, maxc)
1062
1063 returns number of colors or -1 
1064 to indicate that it was more than max colors
1065
1066 =cut
1067 */
1068 /* This function has been changed and is now faster. It's using
1069  * i_gsamp instead of i_gpix */
1070 int
1071 i_count_colors(i_img *im,int maxc) {
1072   struct octt *ct;
1073   i_img_dim x,y;
1074   int colorcnt;
1075   int channels[3];
1076   int *samp_chans;
1077   i_sample_t * samp;
1078   i_img_dim xsize = im->xsize; 
1079   i_img_dim ysize = im->ysize;
1080   int samp_cnt = 3 * xsize;
1081
1082   if (im->channels >= 3) {
1083     samp_chans = NULL;
1084   }
1085   else {
1086     channels[0] = channels[1] = channels[2] = 0;
1087     samp_chans = channels;
1088   }
1089
1090   ct = octt_new();
1091
1092   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1093
1094   colorcnt = 0;
1095   for(y = 0; y < ysize; ) {
1096       i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1097       for(x = 0; x < samp_cnt; ) {
1098           colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1099           x += 3;
1100           if (colorcnt > maxc) { 
1101               octt_delete(ct); 
1102               return -1; 
1103           }
1104       }
1105   }
1106   myfree(samp);
1107   octt_delete(ct);
1108   return colorcnt;
1109 }
1110
1111 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm 
1112  * (adapted from the Numerical Recipes)
1113  */
1114 /* Needed by get_anonymous_color_histo */
1115 static void
1116 hpsort(unsigned int n, unsigned *ra) {
1117     unsigned int i,
1118                  ir,
1119                  j,
1120                  l, 
1121                  rra;
1122
1123     if (n < 2) return;
1124     l = n >> 1;
1125     ir = n - 1;
1126     for(;;) {
1127         if (l > 0) {
1128             rra = ra[--l];
1129         }
1130         else {
1131             rra = ra[ir];
1132             ra[ir] = ra[0];
1133             if (--ir == 0) {
1134                 ra[0] = rra;
1135                 break;
1136             }
1137         }
1138         i = l;
1139         j = 2 * l + 1;
1140         while (j <= ir) {
1141             if (j < ir && ra[j] < ra[j+1]) j++;
1142             if (rra < ra[j]) {
1143                 ra[i] = ra[j];
1144                 i = j;
1145                 j++; j <<= 1; j--;
1146             }
1147             else break;
1148         }
1149         ra[i] = rra;
1150     }
1151 }
1152
1153 /* This function constructs an ordered list which represents how much the
1154  * different colors are used. So for instance (100, 100, 500) means that one
1155  * color is used for 500 pixels, another for 100 pixels and another for 100
1156  * pixels. It's tuned for performance. You might not like the way I've hardcoded
1157  * the maxc ;-) and you might want to change the name... */
1158 /* Uses octt_histo */
1159 int
1160 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1161   struct octt *ct;
1162   i_img_dim x,y;
1163   int colorcnt;
1164   unsigned int *col_usage_it;
1165   i_sample_t * samp;
1166   int channels[3];
1167   int *samp_chans;
1168   
1169   i_img_dim xsize = im->xsize; 
1170   i_img_dim ysize = im->ysize;
1171   int samp_cnt = 3 * xsize;
1172   ct = octt_new();
1173   
1174   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1175   
1176   if (im->channels >= 3) {
1177     samp_chans = NULL;
1178   }
1179   else {
1180     channels[0] = channels[1] = channels[2] = 0;
1181     samp_chans = channels;
1182   }
1183
1184   colorcnt = 0;
1185   for(y = 0; y < ysize; ) {
1186     i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1187     for(x = 0; x < samp_cnt; ) {
1188       colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1189       x += 3;
1190       if (colorcnt > maxc) { 
1191         octt_delete(ct); 
1192         return -1; 
1193       }
1194     }
1195   }
1196   myfree(samp);
1197   /* Now that we know the number of colours... */
1198   col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1199   octt_histo(ct, &col_usage_it);
1200   hpsort(colorcnt, *col_usage);
1201   octt_delete(ct);
1202   return colorcnt;
1203 }
1204
1205 /*
1206 =back
1207
1208 =head2 Image method wrappers
1209
1210 These functions provide i_fsample_t functions in terms of their
1211 i_sample_t versions.
1212
1213 =over
1214
1215 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1216
1217 =cut
1218 */
1219
1220 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1221   i_color temp;
1222   int ch;
1223
1224   for (ch = 0; ch < im->channels; ++ch)
1225     temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1226   
1227   return i_ppix(im, x, y, &temp);
1228 }
1229
1230 /*
1231 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1232
1233 =cut
1234 */
1235 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1236   i_color temp;
1237   int ch;
1238
1239   if (i_gpix(im, x, y, &temp) == 0) {
1240     for (ch = 0; ch < im->channels; ++ch)
1241       pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1242     return 0;
1243   }
1244   else 
1245     return -1;
1246 }
1247
1248 /*
1249 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1250
1251 =cut
1252 */
1253 i_img_dim
1254 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1255   i_color *work;
1256
1257   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1258     if (r > im->xsize)
1259       r = im->xsize;
1260     if (r > l) {
1261       i_img_dim ret;
1262       i_img_dim i;
1263       int ch;
1264       work = mymalloc(sizeof(i_color) * (r-l));
1265       for (i = 0; i < r-l; ++i) {
1266         for (ch = 0; ch < im->channels; ++ch) 
1267           work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1268       }
1269       ret = i_plin(im, l, r, y, work);
1270       myfree(work);
1271
1272       return ret;
1273     }
1274     else {
1275       return 0;
1276     }
1277   }
1278   else {
1279     return 0;
1280   }
1281 }
1282
1283 /*
1284 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1285
1286 =cut
1287 */
1288 i_img_dim
1289 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1290   i_color *work;
1291
1292   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1293     if (r > im->xsize)
1294       r = im->xsize;
1295     if (r > l) {
1296       i_img_dim ret;
1297       i_img_dim i;
1298       int ch;
1299       work = mymalloc(sizeof(i_color) * (r-l));
1300       ret = i_plin(im, l, r, y, work);
1301       for (i = 0; i < r-l; ++i) {
1302         for (ch = 0; ch < im->channels; ++ch) 
1303           pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1304       }
1305       myfree(work);
1306
1307       return ret;
1308     }
1309     else {
1310       return 0;
1311     }
1312   }
1313   else {
1314     return 0;
1315   }
1316 }
1317
1318 /*
1319 =item i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int *chans, int chan_count)
1320
1321 =cut
1322 */
1323
1324 i_img_dim
1325 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, 
1326                 int const *chans, int chan_count) {
1327   i_sample_t *work;
1328
1329   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1330     if (r > im->xsize)
1331       r = im->xsize;
1332     if (r > l) {
1333       i_img_dim ret;
1334       i_img_dim i;
1335       work = mymalloc(sizeof(i_sample_t) * (r-l));
1336       ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1337       for (i = 0; i < ret; ++i) {
1338           samp[i] = Sample8ToF(work[i]);
1339       }
1340       myfree(work);
1341
1342       return ret;
1343     }
1344     else {
1345       return 0;
1346     }
1347   }
1348   else {
1349     return 0;
1350   }
1351 }
1352
1353 /*
1354 =back
1355
1356 =head2 Palette wrapper functions
1357
1358 Used for virtual images, these forward palette calls to a wrapped image, 
1359 assuming the wrapped image is the first pointer in the structure that 
1360 im->ext_data points at.
1361
1362 =over
1363
1364 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1365
1366 =cut
1367 */
1368 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1369   return i_addcolors(*(i_img **)im->ext_data, colors, count);
1370 }
1371
1372 /*
1373 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1374
1375 =cut
1376 */
1377 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1378   return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1379 }
1380
1381 /*
1382 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1383
1384 =cut
1385 */
1386 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1387   return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1388 }
1389
1390 /*
1391 =item i_colorcount_forward(i_img *im)
1392
1393 =cut
1394 */
1395 int i_colorcount_forward(i_img *im) {
1396   return i_colorcount(*(i_img **)im->ext_data);
1397 }
1398
1399 /*
1400 =item i_maxcolors_forward(i_img *im)
1401
1402 =cut
1403 */
1404 int i_maxcolors_forward(i_img *im) {
1405   return i_maxcolors(*(i_img **)im->ext_data);
1406 }
1407
1408 /*
1409 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1410
1411 =cut
1412 */
1413 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1414   return i_findcolor(*(i_img **)im->ext_data, color, entry);
1415 }
1416
1417 /*
1418 =back
1419
1420 =head2 Fallback handler
1421
1422 =over
1423
1424 =item i_gsamp_bits_fb
1425
1426 =cut
1427 */
1428
1429 i_img_dim
1430 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, 
1431                 const int *chans, int chan_count, int bits) {
1432   if (bits < 1 || bits > 32) {
1433     i_push_error(0, "Invalid bits, must be 1..32");
1434     return -1;
1435   }
1436
1437   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1438     double scale;
1439     int ch;
1440     i_img_dim count, i, w;
1441     
1442     if (bits == 32)
1443       scale = 4294967295.0;
1444     else
1445       scale = (double)(1 << bits) - 1;
1446
1447     if (r > im->xsize)
1448       r = im->xsize;
1449     w = r - l;
1450     count = 0;
1451
1452     if (chans) {
1453       /* make sure we have good channel numbers */
1454       for (ch = 0; ch < chan_count; ++ch) {
1455         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1456           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1457           return -1;
1458         }
1459       }
1460       for (i = 0; i < w; ++i) {
1461         i_fcolor c;
1462         i_gpixf(im, l+i, y, &c);
1463         for (ch = 0; ch < chan_count; ++ch) {
1464           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1465           ++count;
1466         }
1467       }
1468     }
1469     else {
1470       if (chan_count <= 0 || chan_count > im->channels) {
1471         i_push_error(0, "Invalid channel count");
1472         return -1;
1473       }
1474       for (i = 0; i < w; ++i) {
1475         i_fcolor c;
1476         i_gpixf(im, l+i, y, &c);
1477         for (ch = 0; ch < chan_count; ++ch) {
1478           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1479           ++count;
1480         }
1481       }
1482     }
1483
1484     return count;
1485   }
1486   else {
1487     i_push_error(0, "Image position outside of image");
1488     return -1;
1489   }
1490 }
1491
1492 struct magic_entry {
1493   unsigned char *magic;
1494   size_t magic_size;
1495   char *name;
1496   unsigned char *mask;  
1497 };
1498
1499 static int
1500 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
1501   if (length < magic->magic_size)
1502     return 0;
1503   if (magic->mask) {
1504     int i;
1505     unsigned char *bufp = buffer, 
1506       *maskp = magic->mask, 
1507       *magicp = magic->magic;
1508
1509     for (i = 0; i < magic->magic_size; ++i) {
1510       int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1511       ++maskp;
1512
1513       if ((*bufp++ & mask) != (*magicp++ & mask)) 
1514         return 0;
1515     }
1516
1517     return 1;
1518   }
1519   else {
1520     return !memcmp(magic->magic, buffer, magic->magic_size);
1521   }
1522 }
1523
1524 /*
1525 =item i_test_format_probe(io_glue *data, int length)
1526
1527 Check the beginning of the supplied file for a 'magic number'
1528
1529 =cut
1530 */
1531
1532 #define FORMAT_ENTRY(magic, type) \
1533   { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1534 #define FORMAT_ENTRY2(magic, type, mask) \
1535   { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1536
1537 const char *
1538 i_test_format_probe(io_glue *data, int length) {
1539   static const struct magic_entry formats[] = {
1540     FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1541     FORMAT_ENTRY("GIF87a", "gif"),
1542     FORMAT_ENTRY("GIF89a", "gif"),
1543     FORMAT_ENTRY("MM\0*", "tiff"),
1544     FORMAT_ENTRY("II*\0", "tiff"),
1545     FORMAT_ENTRY("BM", "bmp"),
1546     FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1547     FORMAT_ENTRY("P1", "pnm"),
1548     FORMAT_ENTRY("P2", "pnm"),
1549     FORMAT_ENTRY("P3", "pnm"),
1550     FORMAT_ENTRY("P4", "pnm"),
1551     FORMAT_ENTRY("P5", "pnm"),
1552     FORMAT_ENTRY("P6", "pnm"),
1553     FORMAT_ENTRY("/* XPM", "xpm"),
1554     FORMAT_ENTRY("\x8aMNG", "mng"),
1555     FORMAT_ENTRY("\x8aJNG", "jng"),
1556     /* SGI RGB - with various possible parameters to avoid false positives
1557        on similar files 
1558        values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1559     */
1560     FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1561     FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1562     FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1563     FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1564     
1565     FORMAT_ENTRY2("FORM    ILBM", "ilbm", "xxxx    xxxx"),
1566
1567     /* different versions of PCX format 
1568        http://www.fileformat.info/format/pcx/
1569     */
1570     FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1571     FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1572     FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1573     FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1574     FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1575
1576     /* FITS - http://fits.gsfc.nasa.gov/ */
1577     FORMAT_ENTRY("SIMPLE  =", "fits"),
1578
1579     /* PSD - Photoshop */
1580     FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1581     
1582     /* EPS - Encapsulated Postscript */
1583     /* only reading 18 chars, so we don't include the F in EPSF */
1584     FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1585
1586     /* Utah RLE */
1587     FORMAT_ENTRY("\x52\xCC", "utah"),
1588
1589     /* GZIP compressed, only matching deflate for now */
1590     FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1591
1592     /* bzip2 compressed */
1593     FORMAT_ENTRY("BZh", "bzip2"),
1594
1595     /* WEBP
1596        http://code.google.com/speed/webp/docs/riff_container.html */
1597     FORMAT_ENTRY2("RIFF    WEBP", "webp", "xxxx    xxxx"),
1598
1599     /* JPEG 2000 
1600        This might match a little loosely */
1601     FORMAT_ENTRY("\x00\x00\x00\x0CjP  \x0D\x0A\x87\x0A", "jp2"),
1602   };
1603   static const struct magic_entry more_formats[] = {
1604     /* these were originally both listed as ico, but cur files can
1605        include hotspot information */
1606     FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1607     FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1608     FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07", 
1609                   "xwd", "    xxxx"), /* X Windows Dump */
1610   };
1611
1612   unsigned int i;
1613   unsigned char head[18];
1614   ssize_t rc;
1615
1616   rc = i_io_peekn(data, head, 18);
1617   if (rc == -1) return NULL;
1618 #if 0
1619   {
1620     int i;
1621     fprintf(stderr, "%d bytes -", (int)rc);
1622     for (i = 0; i < rc; ++i)
1623       fprintf(stderr, " %02x", head[i]);
1624     fprintf(stderr, "\n");
1625   }
1626 #endif
1627
1628   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
1629     struct magic_entry const *entry = formats + i;
1630
1631     if (test_magic(head, rc, entry)) 
1632       return entry->name;
1633   }
1634
1635   if ((rc == 18) &&
1636       tga_header_verify(head))
1637     return "tga";
1638
1639   for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) { 
1640     struct magic_entry const *entry = more_formats + i;
1641
1642     if (test_magic(head, rc, entry)) 
1643       return entry->name;
1644   }
1645
1646   return NULL;
1647 }
1648
1649 /*
1650 =item i_img_is_monochrome(img, &zero_is_white)
1651
1652 =category Image Information
1653
1654 Tests an image to check it meets our monochrome tests.
1655
1656 The idea is that a file writer can use this to test where it should
1657 write the image in whatever bi-level format it uses, eg. C<pbm> for
1658 C<pnm>.
1659
1660 For performance of encoders we require monochrome images:
1661
1662 =over
1663
1664 =item *
1665
1666 be paletted
1667
1668 =item *
1669
1670 have a palette of two colors, containing only C<(0,0,0)> and
1671 C<(255,255,255)> in either order.
1672
1673 =back
1674
1675 C<zero_is_white> is set to non-zero if the first palette entry is white.
1676
1677 =cut
1678 */
1679
1680 int
1681 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1682   if (im->type == i_palette_type
1683       && i_colorcount(im) == 2) {
1684     i_color colors[2];
1685     i_getcolors(im, 0, colors, 2);
1686     if (im->channels == 3) {
1687       if (colors[0].rgb.r == 255 && 
1688           colors[0].rgb.g == 255 &&
1689           colors[0].rgb.b == 255 &&
1690           colors[1].rgb.r == 0 &&
1691           colors[1].rgb.g == 0 &&
1692           colors[1].rgb.b == 0) {
1693         *zero_is_white = 1;
1694         return 1;
1695       }
1696       else if (colors[0].rgb.r == 0 && 
1697                colors[0].rgb.g == 0 &&
1698                colors[0].rgb.b == 0 &&
1699                colors[1].rgb.r == 255 &&
1700                colors[1].rgb.g == 255 &&
1701                colors[1].rgb.b == 255) {
1702         *zero_is_white = 0;
1703         return 1;
1704       }
1705     }
1706     else if (im->channels == 1) {
1707       if (colors[0].channel[0] == 255 &&
1708           colors[1].channel[0] == 0) {
1709         *zero_is_white = 1;
1710         return 1;
1711       }
1712       else if (colors[0].channel[0] == 0 &&
1713                colors[1].channel[0] == 255) {
1714         *zero_is_white = 0;
1715         return 1;         
1716       }
1717     }
1718   }
1719
1720   *zero_is_white = 0;
1721   return 0;
1722 }
1723
1724 /*
1725 =item i_get_file_background(im, &bg)
1726
1727 =category Files
1728
1729 Retrieve the file write background color tag from the image.
1730
1731 If not present, C<bg> is set to black.
1732
1733 Returns 1 if the C<i_background> tag was found and valid.
1734
1735 =cut
1736 */
1737
1738 int
1739 i_get_file_background(i_img *im, i_color *bg) {
1740   int result = i_tags_get_color(&im->tags, "i_background", 0, bg);
1741   if (!result) {
1742     /* black default */
1743     bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1744   }
1745   /* always full alpha */
1746   bg->channel[3] = 255;
1747
1748   return result;
1749 }
1750
1751 /*
1752 =item i_get_file_backgroundf(im, &bg)
1753
1754 =category Files
1755
1756 Retrieve the file write background color tag from the image as a
1757 floating point color.
1758
1759 Implemented in terms of i_get_file_background().
1760
1761 If not present, C<bg> is set to black.
1762
1763 Returns 1 if the C<i_background> tag was found and valid.
1764
1765 =cut
1766 */
1767
1768 int
1769 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1770   i_color bg;
1771   int result = i_get_file_background(im, &bg);
1772   fbg->rgba.r = Sample8ToF(bg.rgba.r);
1773   fbg->rgba.g = Sample8ToF(bg.rgba.g);
1774   fbg->rgba.b = Sample8ToF(bg.rgba.b);
1775   fbg->rgba.a = 1.0;
1776
1777   return result;
1778 }
1779
1780 /*
1781 =back
1782
1783 =head1 AUTHOR
1784
1785 Arnar M. Hrafnkelsson <addi@umich.edu>
1786
1787 Tony Cook <tonyc@cpan.org>
1788
1789 =head1 SEE ALSO
1790
1791 L<Imager>, L<gif.c>
1792
1793 =cut
1794 */