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