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