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