]> git.imager.perl.org - imager.git/blob - image.c
test for duplicate words in POD
[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;
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   for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1069     i_gpix(im,x*2,y,&val1);
1070     i_gpix(im,x*2+1,y,&val2);
1071     for(ch=0;ch<im->channels;ch++) {
1072       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1073       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1074     }
1075     i_ppix(new_img,x,y,&dval1);
1076     i_ppix(new_img,x+fx,y,&dval2);
1077   }
1078
1079   for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1080     i_gpix(new_img,x,y*2,&val1);
1081     i_gpix(new_img,x,y*2+1,&val2);
1082     for(ch=0;ch<im->channels;ch++) {
1083       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1084       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1085     }
1086     i_ppix(new_img2,x,y,&dval1);
1087     i_ppix(new_img2,x,y+fy,&dval2);
1088   }
1089
1090   i_img_destroy(new_img);
1091   return new_img2;
1092 }
1093
1094 /* 
1095 =item i_count_colors(im, maxc)
1096
1097 returns number of colors or -1 
1098 to indicate that it was more than max colors
1099
1100 =cut
1101 */
1102 /* This function has been changed and is now faster. It's using
1103  * i_gsamp instead of i_gpix */
1104 int
1105 i_count_colors(i_img *im,int maxc) {
1106   struct octt *ct;
1107   i_img_dim x,y;
1108   int colorcnt;
1109   int channels[3];
1110   int *samp_chans;
1111   i_sample_t * samp;
1112   i_img_dim xsize = im->xsize; 
1113   i_img_dim ysize = im->ysize;
1114   int samp_cnt = 3 * xsize;
1115
1116   if (im->channels >= 3) {
1117     samp_chans = NULL;
1118   }
1119   else {
1120     channels[0] = channels[1] = channels[2] = 0;
1121     samp_chans = channels;
1122   }
1123
1124   ct = octt_new();
1125
1126   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1127
1128   colorcnt = 0;
1129   for(y = 0; y < ysize; ) {
1130       i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1131       for(x = 0; x < samp_cnt; ) {
1132           colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1133           x += 3;
1134           if (colorcnt > maxc) { 
1135               octt_delete(ct); 
1136               return -1; 
1137           }
1138       }
1139   }
1140   myfree(samp);
1141   octt_delete(ct);
1142   return colorcnt;
1143 }
1144
1145 /* sorts the array ra[0..n-1] into increasing order using heapsort algorithm 
1146  * (adapted from the Numerical Recipes)
1147  */
1148 /* Needed by get_anonymous_color_histo */
1149 static void
1150 hpsort(unsigned int n, unsigned *ra) {
1151     unsigned int i,
1152                  ir,
1153                  j,
1154                  l, 
1155                  rra;
1156
1157     if (n < 2) return;
1158     l = n >> 1;
1159     ir = n - 1;
1160     for(;;) {
1161         if (l > 0) {
1162             rra = ra[--l];
1163         }
1164         else {
1165             rra = ra[ir];
1166             ra[ir] = ra[0];
1167             if (--ir == 0) {
1168                 ra[0] = rra;
1169                 break;
1170             }
1171         }
1172         i = l;
1173         j = 2 * l + 1;
1174         while (j <= ir) {
1175             if (j < ir && ra[j] < ra[j+1]) j++;
1176             if (rra < ra[j]) {
1177                 ra[i] = ra[j];
1178                 i = j;
1179                 j++; j <<= 1; j--;
1180             }
1181             else break;
1182         }
1183         ra[i] = rra;
1184     }
1185 }
1186
1187 /* This function constructs an ordered list which represents how much the
1188  * different colors are used. So for instance (100, 100, 500) means that one
1189  * color is used for 500 pixels, another for 100 pixels and another for 100
1190  * pixels. It's tuned for performance. You might not like the way I've hardcoded
1191  * the maxc ;-) and you might want to change the name... */
1192 /* Uses octt_histo */
1193 int
1194 i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
1195   struct octt *ct;
1196   i_img_dim x,y;
1197   int colorcnt;
1198   unsigned int *col_usage_it;
1199   i_sample_t * samp;
1200   int channels[3];
1201   int *samp_chans;
1202   
1203   i_img_dim xsize = im->xsize; 
1204   i_img_dim ysize = im->ysize;
1205   int samp_cnt = 3 * xsize;
1206   ct = octt_new();
1207   
1208   samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
1209   
1210   if (im->channels >= 3) {
1211     samp_chans = NULL;
1212   }
1213   else {
1214     channels[0] = channels[1] = channels[2] = 0;
1215     samp_chans = channels;
1216   }
1217
1218   colorcnt = 0;
1219   for(y = 0; y < ysize; ) {
1220     i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
1221     for(x = 0; x < samp_cnt; ) {
1222       colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
1223       x += 3;
1224       if (colorcnt > maxc) { 
1225         octt_delete(ct); 
1226         return -1; 
1227       }
1228     }
1229   }
1230   myfree(samp);
1231   /* Now that we know the number of colours... */
1232   col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
1233   octt_histo(ct, &col_usage_it);
1234   hpsort(colorcnt, *col_usage);
1235   octt_delete(ct);
1236   return colorcnt;
1237 }
1238
1239 /*
1240 =back
1241
1242 =head2 Image method wrappers
1243
1244 These functions provide i_fsample_t functions in terms of their
1245 i_sample_t versions.
1246
1247 =over
1248
1249 =item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1250
1251 =cut
1252 */
1253
1254 int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
1255   i_color temp;
1256   int ch;
1257
1258   for (ch = 0; ch < im->channels; ++ch)
1259     temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1260   
1261   return i_ppix(im, x, y, &temp);
1262 }
1263
1264 /*
1265 =item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
1266
1267 =cut
1268 */
1269 int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
1270   i_color temp;
1271   int ch;
1272
1273   if (i_gpix(im, x, y, &temp) == 0) {
1274     for (ch = 0; ch < im->channels; ++ch)
1275       pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1276     return 0;
1277   }
1278   else 
1279     return -1;
1280 }
1281
1282 /*
1283 =item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1284
1285 =cut
1286 */
1287 i_img_dim
1288 i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) {
1289   i_color *work;
1290
1291   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1292     if (r > im->xsize)
1293       r = im->xsize;
1294     if (r > l) {
1295       i_img_dim ret;
1296       i_img_dim i;
1297       int ch;
1298       work = mymalloc(sizeof(i_color) * (r-l));
1299       for (i = 0; i < r-l; ++i) {
1300         for (ch = 0; ch < im->channels; ++ch) 
1301           work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1302       }
1303       ret = i_plin(im, l, r, y, work);
1304       myfree(work);
1305
1306       return ret;
1307     }
1308     else {
1309       return 0;
1310     }
1311   }
1312   else {
1313     return 0;
1314   }
1315 }
1316
1317 /*
1318 =item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix)
1319
1320 =cut
1321 */
1322 i_img_dim
1323 i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) {
1324   i_color *work;
1325
1326   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1327     if (r > im->xsize)
1328       r = im->xsize;
1329     if (r > l) {
1330       i_img_dim ret;
1331       i_img_dim i;
1332       int ch;
1333       work = mymalloc(sizeof(i_color) * (r-l));
1334       ret = i_plin(im, l, r, y, work);
1335       for (i = 0; i < r-l; ++i) {
1336         for (ch = 0; ch < im->channels; ++ch) 
1337           pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1338       }
1339       myfree(work);
1340
1341       return ret;
1342     }
1343     else {
1344       return 0;
1345     }
1346   }
1347   else {
1348     return 0;
1349   }
1350 }
1351
1352 /*
1353 =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)
1354
1355 =cut
1356 */
1357
1358 i_img_dim
1359 i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, 
1360                 int const *chans, int chan_count) {
1361   i_sample_t *work;
1362
1363   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1364     if (r > im->xsize)
1365       r = im->xsize;
1366     if (r > l) {
1367       i_img_dim ret;
1368       i_img_dim i;
1369       work = mymalloc(sizeof(i_sample_t) * (r-l));
1370       ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1371       for (i = 0; i < ret; ++i) {
1372           samp[i] = Sample8ToF(work[i]);
1373       }
1374       myfree(work);
1375
1376       return ret;
1377     }
1378     else {
1379       return 0;
1380     }
1381   }
1382   else {
1383     return 0;
1384   }
1385 }
1386
1387 /*
1388 =back
1389
1390 =head2 Palette wrapper functions
1391
1392 Used for virtual images, these forward palette calls to a wrapped image, 
1393 assuming the wrapped image is the first pointer in the structure that 
1394 im->ext_data points at.
1395
1396 =over
1397
1398 =item i_addcolors_forward(i_img *im, const i_color *colors, int count)
1399
1400 =cut
1401 */
1402 int i_addcolors_forward(i_img *im, const i_color *colors, int count) {
1403   return i_addcolors(*(i_img **)im->ext_data, colors, count);
1404 }
1405
1406 /*
1407 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1408
1409 =cut
1410 */
1411 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1412   return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1413 }
1414
1415 /*
1416 =item i_setcolors_forward(i_img *im, int i, const i_color *color, int count)
1417
1418 =cut
1419 */
1420 int i_setcolors_forward(i_img *im, int i, const i_color *color, int count) {
1421   return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1422 }
1423
1424 /*
1425 =item i_colorcount_forward(i_img *im)
1426
1427 =cut
1428 */
1429 int i_colorcount_forward(i_img *im) {
1430   return i_colorcount(*(i_img **)im->ext_data);
1431 }
1432
1433 /*
1434 =item i_maxcolors_forward(i_img *im)
1435
1436 =cut
1437 */
1438 int i_maxcolors_forward(i_img *im) {
1439   return i_maxcolors(*(i_img **)im->ext_data);
1440 }
1441
1442 /*
1443 =item i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry)
1444
1445 =cut
1446 */
1447 int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1448   return i_findcolor(*(i_img **)im->ext_data, color, entry);
1449 }
1450
1451 /*
1452 =back
1453
1454 =head2 Fallback handler
1455
1456 =over
1457
1458 =item i_gsamp_bits_fb
1459
1460 =cut
1461 */
1462
1463 i_img_dim
1464 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, 
1465                 const int *chans, int chan_count, int bits) {
1466   dIMCTXim(im);
1467
1468   if (bits < 1 || bits > 32) {
1469     i_push_error(0, "Invalid bits, must be 1..32");
1470     return -1;
1471   }
1472
1473   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1474     double scale;
1475     int ch;
1476     i_img_dim count, i, w;
1477     
1478     if (bits == 32)
1479       scale = 4294967295.0;
1480     else
1481       scale = (double)(1 << bits) - 1;
1482
1483     if (r > im->xsize)
1484       r = im->xsize;
1485     w = r - l;
1486     count = 0;
1487
1488     if (chans) {
1489       /* make sure we have good channel numbers */
1490       for (ch = 0; ch < chan_count; ++ch) {
1491         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1492           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
1493           return -1;
1494         }
1495       }
1496       for (i = 0; i < w; ++i) {
1497         i_fcolor c;
1498         i_gpixf(im, l+i, y, &c);
1499         for (ch = 0; ch < chan_count; ++ch) {
1500           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1501           ++count;
1502         }
1503       }
1504     }
1505     else {
1506       if (chan_count <= 0 || chan_count > im->channels) {
1507         i_push_error(0, "Invalid channel count");
1508         return -1;
1509       }
1510       for (i = 0; i < w; ++i) {
1511         i_fcolor c;
1512         i_gpixf(im, l+i, y, &c);
1513         for (ch = 0; ch < chan_count; ++ch) {
1514           *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
1515           ++count;
1516         }
1517       }
1518     }
1519
1520     return count;
1521   }
1522   else {
1523     i_push_error(0, "Image position outside of image");
1524     return -1;
1525   }
1526 }
1527
1528 struct magic_entry {
1529   unsigned char *magic;
1530   size_t magic_size;
1531   char *name;
1532   unsigned char *mask;  
1533 };
1534
1535 static int
1536 test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
1537   if (length < magic->magic_size)
1538     return 0;
1539   if (magic->mask) {
1540     int i;
1541     unsigned char *bufp = buffer, 
1542       *maskp = magic->mask, 
1543       *magicp = magic->magic;
1544
1545     for (i = 0; i < magic->magic_size; ++i) {
1546       int mask = *maskp == 'x' ? 0xFF : *maskp == ' ' ? 0 : *maskp;
1547       ++maskp;
1548
1549       if ((*bufp++ & mask) != (*magicp++ & mask)) 
1550         return 0;
1551     }
1552
1553     return 1;
1554   }
1555   else {
1556     return !memcmp(magic->magic, buffer, magic->magic_size);
1557   }
1558 }
1559
1560 /*
1561 =item i_test_format_probe(io_glue *data, int length)
1562
1563 Check the beginning of the supplied file for a 'magic number'
1564
1565 =cut
1566 */
1567
1568 #define FORMAT_ENTRY(magic, type) \
1569   { (unsigned char *)(magic ""), sizeof(magic)-1, type }
1570 #define FORMAT_ENTRY2(magic, type, mask) \
1571   { (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
1572
1573 const char *
1574 i_test_format_probe(io_glue *data, int length) {
1575   static const struct magic_entry formats[] = {
1576     FORMAT_ENTRY("\xFF\xD8", "jpeg"),
1577     FORMAT_ENTRY("GIF87a", "gif"),
1578     FORMAT_ENTRY("GIF89a", "gif"),
1579     FORMAT_ENTRY("MM\0*", "tiff"),
1580     FORMAT_ENTRY("II*\0", "tiff"),
1581     FORMAT_ENTRY("BM", "bmp"),
1582     FORMAT_ENTRY("\x89PNG\x0d\x0a\x1a\x0a", "png"),
1583     FORMAT_ENTRY("P1", "pnm"),
1584     FORMAT_ENTRY("P2", "pnm"),
1585     FORMAT_ENTRY("P3", "pnm"),
1586     FORMAT_ENTRY("P4", "pnm"),
1587     FORMAT_ENTRY("P5", "pnm"),
1588     FORMAT_ENTRY("P6", "pnm"),
1589     FORMAT_ENTRY("/* XPM", "xpm"),
1590     FORMAT_ENTRY("\x8aMNG", "mng"),
1591     FORMAT_ENTRY("\x8aJNG", "jng"),
1592     /* SGI RGB - with various possible parameters to avoid false positives
1593        on similar files 
1594        values are: 2 byte magic, rle flags (0 or 1), bytes/sample (1 or 2)
1595     */
1596     FORMAT_ENTRY("\x01\xDA\x00\x01", "sgi"),
1597     FORMAT_ENTRY("\x01\xDA\x00\x02", "sgi"),
1598     FORMAT_ENTRY("\x01\xDA\x01\x01", "sgi"),
1599     FORMAT_ENTRY("\x01\xDA\x01\x02", "sgi"),
1600     
1601     FORMAT_ENTRY2("FORM    ILBM", "ilbm", "xxxx    xxxx"),
1602
1603     /* different versions of PCX format 
1604        http://www.fileformat.info/format/pcx/
1605     */
1606     FORMAT_ENTRY("\x0A\x00\x01", "pcx"),
1607     FORMAT_ENTRY("\x0A\x02\x01", "pcx"),
1608     FORMAT_ENTRY("\x0A\x03\x01", "pcx"),
1609     FORMAT_ENTRY("\x0A\x04\x01", "pcx"),
1610     FORMAT_ENTRY("\x0A\x05\x01", "pcx"),
1611
1612     /* FITS - http://fits.gsfc.nasa.gov/ */
1613     FORMAT_ENTRY("SIMPLE  =", "fits"),
1614
1615     /* PSD - Photoshop */
1616     FORMAT_ENTRY("8BPS\x00\x01", "psd"),
1617     
1618     /* EPS - Encapsulated Postscript */
1619     /* only reading 18 chars, so we don't include the F in EPSF */
1620     FORMAT_ENTRY("%!PS-Adobe-2.0 EPS", "eps"),
1621
1622     /* Utah RLE */
1623     FORMAT_ENTRY("\x52\xCC", "utah"),
1624
1625     /* GZIP compressed, only matching deflate for now */
1626     FORMAT_ENTRY("\x1F\x8B\x08", "gzip"),
1627
1628     /* bzip2 compressed */
1629     FORMAT_ENTRY("BZh", "bzip2"),
1630
1631     /* WEBP
1632        http://code.google.com/speed/webp/docs/riff_container.html */
1633     FORMAT_ENTRY2("RIFF    WEBP", "webp", "xxxx    xxxx"),
1634
1635     /* JPEG 2000 
1636        This might match a little loosely */
1637     FORMAT_ENTRY("\x00\x00\x00\x0CjP  \x0D\x0A\x87\x0A", "jp2"),
1638   };
1639   static const struct magic_entry more_formats[] = {
1640     /* these were originally both listed as ico, but cur files can
1641        include hotspot information */
1642     FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
1643     FORMAT_ENTRY("\x00\x00\x02\x00", "cur"), /* Windows cursor */
1644     FORMAT_ENTRY2("\x00\x00\x00\x00\x00\x00\x00\x07", 
1645                   "xwd", "    xxxx"), /* X Windows Dump */
1646   };
1647
1648   unsigned int i;
1649   unsigned char head[18];
1650   ssize_t rc;
1651
1652   rc = i_io_peekn(data, head, 18);
1653   if (rc == -1) return NULL;
1654 #if 0
1655   {
1656     int i;
1657     fprintf(stderr, "%d bytes -", (int)rc);
1658     for (i = 0; i < rc; ++i)
1659       fprintf(stderr, " %02x", head[i]);
1660     fprintf(stderr, "\n");
1661   }
1662 #endif
1663
1664   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
1665     struct magic_entry const *entry = formats + i;
1666
1667     if (test_magic(head, rc, entry)) 
1668       return entry->name;
1669   }
1670
1671   if ((rc == 18) &&
1672       tga_header_verify(head))
1673     return "tga";
1674
1675   for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) { 
1676     struct magic_entry const *entry = more_formats + i;
1677
1678     if (test_magic(head, rc, entry)) 
1679       return entry->name;
1680   }
1681
1682   return NULL;
1683 }
1684
1685 /*
1686 =item i_img_is_monochrome(img, &zero_is_white)
1687
1688 =category Image Information
1689
1690 Tests an image to check it meets our monochrome tests.
1691
1692 The idea is that a file writer can use this to test where it should
1693 write the image in whatever bi-level format it uses, eg. C<pbm> for
1694 C<pnm>.
1695
1696 For performance of encoders we require monochrome images:
1697
1698 =over
1699
1700 =item *
1701
1702 be paletted
1703
1704 =item *
1705
1706 have a palette of two colors, containing only C<(0,0,0)> and
1707 C<(255,255,255)> in either order.
1708
1709 =back
1710
1711 C<zero_is_white> is set to non-zero if the first palette entry is white.
1712
1713 =cut
1714 */
1715
1716 int
1717 i_img_is_monochrome(i_img *im, int *zero_is_white) {
1718   if (im->type == i_palette_type
1719       && i_colorcount(im) == 2) {
1720     i_color colors[2];
1721     i_getcolors(im, 0, colors, 2);
1722     if (im->channels == 3) {
1723       if (colors[0].rgb.r == 255 && 
1724           colors[0].rgb.g == 255 &&
1725           colors[0].rgb.b == 255 &&
1726           colors[1].rgb.r == 0 &&
1727           colors[1].rgb.g == 0 &&
1728           colors[1].rgb.b == 0) {
1729         *zero_is_white = 1;
1730         return 1;
1731       }
1732       else if (colors[0].rgb.r == 0 && 
1733                colors[0].rgb.g == 0 &&
1734                colors[0].rgb.b == 0 &&
1735                colors[1].rgb.r == 255 &&
1736                colors[1].rgb.g == 255 &&
1737                colors[1].rgb.b == 255) {
1738         *zero_is_white = 0;
1739         return 1;
1740       }
1741     }
1742     else if (im->channels == 1) {
1743       if (colors[0].channel[0] == 255 &&
1744           colors[1].channel[0] == 0) {
1745         *zero_is_white = 1;
1746         return 1;
1747       }
1748       else if (colors[0].channel[0] == 0 &&
1749                colors[1].channel[0] == 255) {
1750         *zero_is_white = 0;
1751         return 1;         
1752       }
1753     }
1754   }
1755
1756   *zero_is_white = 0;
1757   return 0;
1758 }
1759
1760 /*
1761 =item i_get_file_background(im, &bg)
1762
1763 =category Files
1764
1765 Retrieve the file write background color tag from the image.
1766
1767 If not present, C<bg> is set to black.
1768
1769 Returns 1 if the C<i_background> tag was found and valid.
1770
1771 =cut
1772 */
1773
1774 int
1775 i_get_file_background(i_img *im, i_color *bg) {
1776   int result = i_tags_get_color(&im->tags, "i_background", 0, bg);
1777   if (!result) {
1778     /* black default */
1779     bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
1780   }
1781   /* always full alpha */
1782   bg->channel[3] = 255;
1783
1784   return result;
1785 }
1786
1787 /*
1788 =item i_get_file_backgroundf(im, &bg)
1789
1790 =category Files
1791
1792 Retrieve the file write background color tag from the image as a
1793 floating point color.
1794
1795 Implemented in terms of i_get_file_background().
1796
1797 If not present, C<bg> is set to black.
1798
1799 Returns 1 if the C<i_background> tag was found and valid.
1800
1801 =cut
1802 */
1803
1804 int
1805 i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
1806   i_color bg;
1807   int result = i_get_file_background(im, &bg);
1808   fbg->rgba.r = Sample8ToF(bg.rgba.r);
1809   fbg->rgba.g = Sample8ToF(bg.rgba.g);
1810   fbg->rgba.b = Sample8ToF(bg.rgba.b);
1811   fbg->rgba.a = 1.0;
1812
1813   return result;
1814 }
1815
1816 /*
1817 =back
1818
1819 =head1 AUTHOR
1820
1821 Arnar M. Hrafnkelsson <addi@umich.edu>
1822
1823 Tony Cook <tonyc@cpan.org>
1824
1825 =head1 SEE ALSO
1826
1827 L<Imager>, L<gif.c>
1828
1829 =cut
1830 */