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