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