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