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