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