]> git.imager.perl.org - imager.git/blob - image.c
- t1 library re-initialization modified to support T1Lib 5.1.0
[imager.git] / image.c
1 #include "image.h"
2 #include "imagei.h"
3
4 /*
5 =head1 NAME
6
7 image.c - implements most of the basic functions of Imager and much of the rest
8
9 =head1 SYNOPSIS
10
11   i_img *i;
12   i_color *c;
13   c = i_color_new(red, green, blue, alpha);
14   ICL_DESTROY(c);
15   i = i_img_new();
16   i_img_destroy(i);
17   // and much more
18
19 =head1 DESCRIPTION
20
21 image.c implements the basic functions to create and destroy image and
22 color objects for Imager.
23
24 =head1 FUNCTION REFERENCE
25
26 Some of these functions are internal.
27
28 =over
29
30 =cut
31 */
32
33 #define XAXIS 0
34 #define YAXIS 1
35 #define XYAXIS 2
36
37 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i   )) )
38
39 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
40 static void fake(void) { ceil(1); }
41
42 static int i_ppix_d(i_img *im, int x, int y, i_color *val);
43 static int i_gpix_d(i_img *im, int x, int y, i_color *val);
44 static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals);
45 static int i_plin_d(i_img *im, int l, int r, int y, i_color *vals);
46 static int i_ppixf_d(i_img *im, int x, int y, i_fcolor *val);
47 static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
48 static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
49 static int i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
50 static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
51 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
52 /*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
53   static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
54
55 /* 
56 =item ICL_new_internal(r, g, b, a)
57
58 Return a new color object with values passed to it.
59
60    r - red   component (range: 0 - 255)
61    g - green component (range: 0 - 255)
62    b - blue  component (range: 0 - 255)
63    a - alpha component (range: 0 - 255)
64
65 =cut
66 */
67
68 i_color *
69 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
70   i_color *cl = NULL;
71
72   mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
73
74   if ( (cl=mymalloc(sizeof(i_color))) == NULL) m_fatal(2,"malloc() error\n");
75   cl->rgba.r = r;
76   cl->rgba.g = g;
77   cl->rgba.b = b;
78   cl->rgba.a = a;
79   mm_log((1,"(%p) <- ICL_new_internal\n",cl));
80   return cl;
81 }
82
83
84 /*
85 =item ICL_set_internal(cl, r, g, b, a)
86
87  Overwrite a color with new values.
88
89    cl - pointer to color object
90    r - red   component (range: 0 - 255)
91    g - green component (range: 0 - 255)
92    b - blue  component (range: 0 - 255)
93    a - alpha component (range: 0 - 255)
94
95 =cut
96 */
97
98 i_color *
99 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
100   mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
101   if (cl == NULL)
102     if ( (cl=mymalloc(sizeof(i_color))) == NULL)
103       m_fatal(2,"malloc() error\n");
104   cl->rgba.r=r;
105   cl->rgba.g=g;
106   cl->rgba.b=b;
107   cl->rgba.a=a;
108   mm_log((1,"(%p) <- ICL_set_internal\n",cl));
109   return cl;
110 }
111
112
113 /* 
114 =item ICL_add(dst, src, ch)
115
116 Add src to dst inplace - dst is modified.
117
118    dst - pointer to destination color object
119    src - pointer to color object that is added
120    ch - number of channels
121
122 =cut
123 */
124
125 void
126 ICL_add(i_color *dst,i_color *src,int ch) {
127   int tmp,i;
128   for(i=0;i<ch;i++) {
129     tmp=dst->channel[i]+src->channel[i];
130     dst->channel[i]= tmp>255 ? 255:tmp;
131   }
132 }
133
134 /* 
135 =item ICL_info(cl)
136
137 Dump color information to log - strictly for debugging.
138
139    cl - pointer to color object
140
141 =cut
142 */
143
144 void
145 ICL_info(i_color *cl) {
146   mm_log((1,"i_color_info(cl* %p)\n",cl));
147   mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
148 }
149
150 /* 
151 =item ICL_DESTROY
152
153 Destroy ancillary data for Color object.
154
155    cl - pointer to color object
156
157 =cut
158 */
159
160 void
161 ICL_DESTROY(i_color *cl) {
162   mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
163   myfree(cl);
164 }
165
166 /*
167 =item i_fcolor_new(double r, double g, double b, double a)
168
169 =cut
170 */
171 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
172   i_fcolor *cl = NULL;
173
174   mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
175
176   if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) m_fatal(2,"malloc() error\n");
177   cl->rgba.r = r;
178   cl->rgba.g = g;
179   cl->rgba.b = b;
180   cl->rgba.a = a;
181   mm_log((1,"(%p) <- i_fcolor_new\n",cl));
182
183   return cl;
184 }
185
186 /*
187 =item i_fcolor_destroy(i_fcolor *cl) 
188
189 =cut
190 */
191 void i_fcolor_destroy(i_fcolor *cl) {
192   myfree(cl);
193 }
194
195 /*
196 =item IIM_base_8bit_direct (static)
197
198 A static i_img object used to initialize direct 8-bit per sample images.
199
200 =cut
201 */
202 static i_img IIM_base_8bit_direct =
203 {
204   0, /* channels set */
205   0, 0, 0, /* xsize, ysize, bytes */
206   ~0U, /* ch_mask */
207   i_8_bits, /* bits */
208   i_direct_type, /* type */
209   0, /* virtual */
210   NULL, /* idata */
211   { 0, 0, NULL }, /* tags */
212   NULL, /* ext_data */
213
214   i_ppix_d, /* i_f_ppix */
215   i_ppixf_d, /* i_f_ppixf */
216   i_plin_d, /* i_f_plin */
217   i_plinf_d, /* i_f_plinf */
218   i_gpix_d, /* i_f_gpix */
219   i_gpixf_d, /* i_f_gpixf */
220   i_glin_d, /* i_f_glin */
221   i_glinf_d, /* i_f_glinf */
222   i_gsamp_d, /* i_f_gsamp */
223   i_gsampf_d, /* i_f_gsampf */
224
225   NULL, /* i_f_gpal */
226   NULL, /* i_f_ppal */
227   NULL, /* i_f_addcolors */
228   NULL, /* i_f_getcolors */
229   NULL, /* i_f_colorcount */
230   NULL, /* i_f_maxcolors */
231   NULL, /* i_f_findcolor */
232   NULL, /* i_f_setcolors */
233
234   NULL, /* i_f_destroy */
235 };
236
237 /*static void set_8bit_direct(i_img *im) {
238   im->i_f_ppix = i_ppix_d;
239   im->i_f_ppixf = i_ppixf_d;
240   im->i_f_plin = i_plin_d;
241   im->i_f_plinf = i_plinf_d;
242   im->i_f_gpix = i_gpix_d;
243   im->i_f_gpixf = i_gpixf_d;
244   im->i_f_glin = i_glin_d;
245   im->i_f_glinf = i_glinf_d;
246   im->i_f_gpal = NULL;
247   im->i_f_ppal = NULL;
248   im->i_f_addcolor = NULL;
249   im->i_f_getcolor = NULL;
250   im->i_f_colorcount = NULL;
251   im->i_f_findcolor = NULL;
252   }*/
253
254 /*
255 =item IIM_new(x, y, ch)
256
257 Creates a new image object I<x> pixels wide, and I<y> pixels high with I<ch> channels.
258
259 =cut
260 */
261
262
263 i_img *
264 IIM_new(int x,int y,int ch) {
265   i_img *im;
266   mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
267
268   im=i_img_empty_ch(NULL,x,y,ch);
269   
270   mm_log((1,"(%p) <- IIM_new\n",im));
271   return im;
272 }
273
274
275 void
276 IIM_DESTROY(i_img *im) {
277   mm_log((1,"IIM_DESTROY(im* %p)\n",im));
278   i_img_destroy(im);
279   /*   myfree(cl); */
280 }
281
282
283
284 /* 
285 =item i_img_new()
286
287 Create new image reference - notice that this isn't an object yet and
288 this should be fixed asap.
289
290 =cut
291 */
292
293
294 i_img *
295 i_img_new() {
296   i_img *im;
297   
298   mm_log((1,"i_img_struct()\n"));
299   if ( (im=mymalloc(sizeof(i_img))) == NULL)
300     m_fatal(2,"malloc() error\n");
301   
302   *im = IIM_base_8bit_direct;
303   im->xsize=0;
304   im->ysize=0;
305   im->channels=3;
306   im->ch_mask=MAXINT;
307   im->bytes=0;
308   im->idata=NULL;
309   
310   mm_log((1,"(%p) <- i_img_struct\n",im));
311   return im;
312 }
313
314 /* 
315 =item i_img_empty(im, x, y)
316
317 Re-new image reference (assumes 3 channels)
318
319    im - Image pointer
320    x - xsize of destination image
321    y - ysize of destination image
322
323 **FIXME** what happens if a live image is passed in here?
324
325 Should this just call i_img_empty_ch()?
326
327 =cut
328 */
329
330 i_img *
331 i_img_empty(i_img *im,int x,int y) {
332   mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y));
333   return i_img_empty_ch(im, x, y, 3);
334 }
335
336 /* 
337 =item i_img_empty_ch(im, x, y, ch)
338
339 Re-new image reference 
340
341    im - Image pointer
342    x  - xsize of destination image
343    y  - ysize of destination image
344    ch - number of channels
345
346 =cut
347 */
348
349 i_img *
350 i_img_empty_ch(i_img *im,int x,int y,int ch) {
351   int bytes;
352
353   mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch));
354
355   if (x < 1 || y < 1) {
356     i_push_error(0, "Image sizes must be positive");
357     return NULL;
358   }
359   if (ch < 1 || ch > MAXCHANNELS) {
360     i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
361     return NULL;
362   }
363   /* check this multiplication doesn't overflow */
364   bytes = x*y*ch;
365   if (bytes / y / ch != x) {
366     i_push_errorf(0, "integer overflow calculating image allocation");
367     return NULL;
368   }
369
370   if (im == NULL)
371     if ( (im=mymalloc(sizeof(i_img))) == NULL)
372       m_fatal(2,"malloc() error\n");
373
374   memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
375   i_tags_new(&im->tags);
376   im->xsize    = x;
377   im->ysize    = y;
378   im->channels = ch;
379   im->ch_mask  = MAXINT;
380   im->bytes=bytes;
381   if ( (im->idata=mymalloc(im->bytes)) == NULL) 
382     m_fatal(2,"malloc() error\n"); 
383   memset(im->idata,0,(size_t)im->bytes);
384   
385   im->ext_data = NULL;
386   
387   mm_log((1,"(%p) <- i_img_empty_ch\n",im));
388   return im;
389 }
390
391 /* 
392 =item i_img_exorcise(im)
393
394 Free image data.
395
396    im - Image pointer
397
398 =cut
399 */
400
401 void
402 i_img_exorcise(i_img *im) {
403   mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
404   i_tags_destroy(&im->tags);
405   if (im->i_f_destroy)
406     (im->i_f_destroy)(im);
407   if (im->idata != NULL) { myfree(im->idata); }
408   im->idata    = NULL;
409   im->xsize    = 0;
410   im->ysize    = 0;
411   im->channels = 0;
412
413   im->i_f_ppix=i_ppix_d;
414   im->i_f_gpix=i_gpix_d;
415   im->i_f_plin=i_plin_d;
416   im->i_f_glin=i_glin_d;
417   im->ext_data=NULL;
418 }
419
420 /* 
421 =item i_img_destroy(im)
422
423 Destroy image and free data via exorcise.
424
425    im - Image pointer
426
427 =cut
428 */
429
430 void
431 i_img_destroy(i_img *im) {
432   mm_log((1,"i_img_destroy(im %p)\n",im));
433   i_img_exorcise(im);
434   if (im) { myfree(im); }
435 }
436
437 /* 
438 =item i_img_info(im, info)
439
440 Return image information
441
442    im - Image pointer
443    info - pointer to array to return data
444
445 info is an array of 4 integers with the following values:
446
447  info[0] - width
448  info[1] - height
449  info[2] - channels
450  info[3] - channel mask
451
452 =cut
453 */
454
455
456 void
457 i_img_info(i_img *im,int *info) {
458   mm_log((1,"i_img_info(im 0x%x)\n",im));
459   if (im != NULL) {
460     mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
461     mm_log((1,"i_img_info: idata=0x%d\n",im->idata));
462     info[0] = im->xsize;
463     info[1] = im->ysize;
464     info[2] = im->channels;
465     info[3] = im->ch_mask;
466   } else {
467     info[0] = 0;
468     info[1] = 0;
469     info[2] = 0;
470     info[3] = 0;
471   }
472 }
473
474 /*
475 =item i_img_setmask(im, ch_mask)
476
477 Set the image channel mask for I<im> to I<ch_mask>.
478
479 =cut
480 */
481 void
482 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
483
484
485 /*
486 =item i_img_getmask(im)
487
488 Get the image channel mask for I<im>.
489
490 =cut
491 */
492 int
493 i_img_getmask(i_img *im) { return im->ch_mask; }
494
495 /*
496 =item i_img_getchannels(im)
497
498 Get the number of channels in I<im>.
499
500 =cut
501 */
502 int
503 i_img_getchannels(i_img *im) { return im->channels; }
504
505
506
507 /*
508 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
509
510 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
511 (tx,ty) specifies the upper left corner for the target image.
512 pass NULL in trans for non transparent i_colors.
513
514 =cut
515 */
516
517 void
518 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans) {
519   i_color pv;
520   int x,y,t,ttx,tty,tt,ch;
521
522   mm_log((1,"i_copyto_trans(im* %p,src 0x%x, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d, trans* 0x%x)\n",
523           im, src, x1, y1, x2, y2, tx, ty, trans));
524   
525   if (x2<x1) { t=x1; x1=x2; x2=t; }
526   if (y2<y1) { t=y1; y1=y2; y2=t; }
527
528   ttx=tx;
529   for(x=x1;x<x2;x++)
530     {
531       tty=ty;
532       for(y=y1;y<y2;y++)
533         {
534           i_gpix(src,x,y,&pv);
535           if ( trans != NULL)
536           {
537             tt=0;
538             for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
539             if (tt) i_ppix(im,ttx,tty,&pv);
540           } else i_ppix(im,ttx,tty,&pv);
541           tty++;
542         }
543       ttx++;
544     }
545 }
546
547 /*
548 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
549
550 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
551 a rectangle the same size with it's top-left corner at (tx,ty) in the
552 destination image.
553
554 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
555
556 =cut
557 */
558
559 void
560 i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
561   int x, y, t, ttx, tty;
562   
563   if (x2<x1) { t=x1; x1=x2; x2=t; }
564   if (y2<y1) { t=y1; y1=y2; y2=t; }
565   
566   mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
567           im, src, x1, y1, x2, y2, tx, ty));
568   
569   if (im->bits == i_8_bits) {
570     i_color pv;
571     tty = ty;
572     for(y=y1; y<y2; y++) {
573       ttx = tx;
574       for(x=x1; x<x2; x++) {
575         i_gpix(src, x,   y,   &pv);
576         i_ppix(im,  ttx, tty, &pv);
577         ttx++;
578       }
579       tty++;
580     }
581   }
582   else {
583     i_fcolor pv;
584     tty = ty;
585     for(y=y1; y<y2; y++) {
586       ttx = tx;
587       for(x=x1; x<x2; x++) {
588         i_gpixf(src, x,   y,   &pv);
589         i_ppixf(im,  ttx, tty, &pv);
590         ttx++;
591       }
592       tty++;
593     }
594   }
595 }
596
597 /*
598 =item i_copy(im, src)
599
600 Copies the contents of the image I<src> over the image I<im>.
601
602 =cut
603 */
604
605 void
606 i_copy(i_img *im, i_img *src) {
607   int y, y1, x1;
608
609   mm_log((1,"i_copy(im* %p,src %p)\n", im, src));
610
611   x1 = src->xsize;
612   y1 = src->ysize;
613   if (src->type == i_direct_type) {
614     if (src->bits == i_8_bits) {
615       i_color *pv;
616       i_img_empty_ch(im, x1, y1, src->channels);
617       pv = mymalloc(sizeof(i_color) * x1);
618       
619       for (y = 0; y < y1; ++y) {
620         i_glin(src, 0, x1, y, pv);
621         i_plin(im, 0, x1, y, pv);
622       }
623       myfree(pv);
624     }
625     else {
626       i_fcolor *pv;
627       if (src->bits == i_16_bits)
628         i_img_16_new_low(im, x1, y1, src->channels);
629       else if (src->bits == i_double_bits)
630         i_img_double_new_low(im, x1, y1, src->channels);
631       else {
632         fprintf(stderr, "i_copy(): Unknown image bit size %d\n", src->bits);
633         return; /* I dunno */
634       }
635
636       pv = mymalloc(sizeof(i_fcolor) * x1);
637       for (y = 0; y < y1; ++y) {
638         i_glinf(src, 0, x1, y, pv);
639         i_plinf(im, 0, x1, y, pv);
640       }
641       myfree(pv);
642     }
643   }
644   else {
645     i_color temp;
646     int index;
647     int count;
648     i_palidx *vals;
649
650     /* paletted image */
651     i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
652     /* copy across the palette */
653     count = i_colorcount(src);
654     for (index = 0; index < count; ++index) {
655       i_getcolors(src, index, &temp, 1);
656       i_addcolors(im, &temp, 1);
657     }
658
659     vals = mymalloc(sizeof(i_palidx) * x1);
660     for (y = 0; y < y1; ++y) {
661       i_gpal(src, 0, x1, y, vals);
662       i_ppal(im, 0, x1, y, vals);
663     }
664     myfree(vals);
665   }
666 }
667
668
669 /*
670 =item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy )
671
672 Takes the sub image I<src[src_minx, src_maxx)[src_miny, src_maxy)> and
673 overlays it at (I<tx>,I<ty>) on the image object.
674
675 The alpha channel of each pixel in I<src> is used to control how much
676 the existing colour in I<im> is replaced, if it is 255 then the colour
677 is completely replaced, if it is 0 then the original colour is left 
678 unmodified.
679
680 =cut
681 */
682
683 int
684 i_rubthru(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny,
685           int src_maxx, int src_maxy) {
686   int x, y, ttx, tty;
687   int chancount;
688   int chans[3];
689   int alphachan;
690   int ch;
691
692   mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d, src_minx %d, "
693           "src_miny %d, src_maxx %d, src_maxy %d)\n",
694           im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy));
695   i_clear_error();
696
697   if (im->channels == 3 && src->channels == 4) {
698     chancount = 3;
699     chans[0] = 0; chans[1] = 1; chans[2] = 2;
700     alphachan = 3;
701   }
702   else if (im->channels == 3 && src->channels == 2) {
703     chancount = 3;
704     chans[0] = chans[1] = chans[2] = 0;
705     alphachan = 1;
706   }
707   else if (im->channels == 1 && src->channels == 2) {
708     chancount = 1;
709     chans[0] = 0;
710     alphachan = 1;
711   }
712   else {
713     i_push_error(0, "rubthru can only work where (dest, src) channels are (3,4), (3,2) or (1,2)");
714     return 0;
715   }
716
717   if (im->bits <= 8) {
718     /* if you change this code, please make sure the else branch is
719        changed in a similar fashion - TC */
720     int alpha;
721     i_color pv, orig, dest;
722     tty = ty;
723     for(y = src_miny; y < src_maxy; y++) {
724       ttx = tx;
725       for(x = src_minx; x < src_maxx; x++) {
726         i_gpix(src, x,   y,   &pv);
727         i_gpix(im,  ttx, tty, &orig);
728         alpha = pv.channel[alphachan];
729         for (ch = 0; ch < chancount; ++ch) {
730           dest.channel[ch] = (alpha * pv.channel[chans[ch]]
731                               + (255 - alpha) * orig.channel[ch])/255;
732         }
733         i_ppix(im, ttx, tty, &dest);
734         ttx++;
735       }
736       tty++;
737     }
738   }
739   else {
740     double alpha;
741     i_fcolor pv, orig, dest;
742
743     tty = ty;
744     for(y = src_miny; y < src_maxy; y++) {
745       ttx = tx;
746       for(x = src_minx; x < src_maxx; x++) {
747         i_gpixf(src, x,   y,   &pv);
748         i_gpixf(im,  ttx, tty, &orig);
749         alpha = pv.channel[alphachan];
750         for (ch = 0; ch < chancount; ++ch) {
751           dest.channel[ch] = alpha * pv.channel[chans[ch]]
752             + (1 - alpha) * orig.channel[ch];
753         }
754         i_ppixf(im, ttx, tty, &dest);
755         ttx++;
756       }
757       tty++;
758     }
759   }
760
761   return 1;
762 }
763
764
765 /*
766 =item i_flipxy(im, axis)
767
768 Flips the image inplace around the axis specified.
769 Returns 0 if parameters are invalid.
770
771    im   - Image pointer
772    axis - 0 = x, 1 = y, 2 = both
773
774 =cut
775 */
776
777 undef_int
778 i_flipxy(i_img *im, int direction) {
779   int x, x2, y, y2, xm, ym;
780   int xs = im->xsize;
781   int ys = im->ysize;
782   
783   mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
784
785   if (!im) return 0;
786
787   switch (direction) {
788   case XAXIS: /* Horizontal flip */
789     xm = xs/2;
790     ym = ys;
791     for(y=0; y<ym; y++) {
792       x2 = xs-1;
793       for(x=0; x<xm; x++) {
794         i_color val1, val2;
795         i_gpix(im, x,  y,  &val1);
796         i_gpix(im, x2, y,  &val2);
797         i_ppix(im, x,  y,  &val2);
798         i_ppix(im, x2, y,  &val1);
799         x2--;
800       }
801     }
802     break;
803   case YAXIS: /* Vertical flip */
804     xm = xs;
805     ym = ys/2;
806     y2 = ys-1;
807     for(y=0; y<ym; y++) {
808       for(x=0; x<xm; x++) {
809         i_color val1, val2;
810         i_gpix(im, x,  y,  &val1);
811         i_gpix(im, x,  y2, &val2);
812         i_ppix(im, x,  y,  &val2);
813         i_ppix(im, x,  y2, &val1);
814       }
815       y2--;
816     }
817     break;
818   case XYAXIS: /* Horizontal and Vertical flip */
819     xm = xs/2;
820     ym = ys/2;
821     y2 = ys-1;
822     for(y=0; y<ym; y++) {
823       x2 = xs-1;
824       for(x=0; x<xm; x++) {
825         i_color val1, val2;
826         i_gpix(im, x,  y,  &val1);
827         i_gpix(im, x2, y2, &val2);
828         i_ppix(im, x,  y,  &val2);
829         i_ppix(im, x2, y2, &val1);
830
831         i_gpix(im, x2, y,  &val1);
832         i_gpix(im, x,  y2, &val2);
833         i_ppix(im, x2, y,  &val2);
834         i_ppix(im, x,  y2, &val1);
835         x2--;
836       }
837       y2--;
838     }
839     if (xm*2 != xs) { /* odd number of column */
840       mm_log((1, "i_flipxy: odd number of columns\n"));
841       x = xm;
842       y2 = ys-1;
843       for(y=0; y<ym; y++) {
844         i_color val1, val2;
845         i_gpix(im, x,  y,  &val1);
846         i_gpix(im, x,  y2, &val2);
847         i_ppix(im, x,  y,  &val2);
848         i_ppix(im, x,  y2, &val1);
849         y2--;
850       }
851     }
852     if (ym*2 != ys) { /* odd number of rows */
853       mm_log((1, "i_flipxy: odd number of rows\n"));
854       y = ym;
855       x2 = xs-1;
856       for(x=0; x<xm; x++) {
857         i_color val1, val2;
858         i_gpix(im, x,  y,  &val1);
859         i_gpix(im, x2, y,  &val2);
860         i_ppix(im, x,  y,  &val2);
861         i_ppix(im, x2, y,  &val1);
862         x2--;
863       }
864     }
865     break;
866   default:
867     mm_log((1, "i_flipxy: direction is invalid\n" ));
868     return 0;
869   }
870   return 1;
871 }
872
873
874
875
876
877 static
878 float
879 Lanczos(float x) {
880   float PIx, PIx2;
881   
882   PIx = PI * x;
883   PIx2 = PIx / 2.0;
884   
885   if ((x >= 2.0) || (x <= -2.0)) return (0.0);
886   else if (x == 0.0) return (1.0);
887   else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
888 }
889
890
891 /*
892 =item i_scaleaxis(im, value, axis)
893
894 Returns a new image object which is I<im> scaled by I<value> along
895 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
896
897 =cut
898 */
899
900 i_img*
901 i_scaleaxis(i_img *im, float Value, int Axis) {
902   int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
903   int LanczosWidthFactor;
904   float *l0, *l1, OldLocation;
905   int T; 
906   float t;
907   float F, PictureValue[MAXCHANNELS];
908   short psave;
909   i_color val,val1,val2;
910   i_img *new_img;
911
912   mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
913
914
915   if (Axis == XAXIS) {
916     hsize = (int)(0.5 + im->xsize * Value);
917     if (hsize < 1) {
918       hsize = 1;
919       Value = 1.0 / im->xsize;
920     }
921     vsize = im->ysize;
922     
923     jEnd = hsize;
924     iEnd = vsize;
925   } else {
926     hsize = im->xsize;
927     vsize = (int)(0.5 + im->ysize * Value);
928
929     if (vsize < 1) {
930       vsize = 1;
931       Value = 1.0 / im->ysize;
932     }
933
934     jEnd = vsize;
935     iEnd = hsize;
936   }
937   
938   new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
939   
940   /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
941   LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value); 
942   lMax = LanczosWidthFactor << 1;
943   
944   l0 = mymalloc(lMax * sizeof(float));
945   l1 = mymalloc(lMax * sizeof(float));
946   
947   for (j=0; j<jEnd; j++) {
948     OldLocation = ((float) j) / Value;
949     T = (int) (OldLocation);
950     F = OldLocation - (float) T;
951     
952     for (l = 0; l<lMax; l++) {
953       l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
954       l1[l]        = Lanczos(((float) (l+1)      - F) / (float) LanczosWidthFactor);
955     }
956     
957     /* Make sure filter is normalized */
958     t = 0.0;
959     for(l=0; l<lMax; l++) {
960       t+=l0[l];
961       t+=l1[l];
962     }
963     t /= (float)LanczosWidthFactor;
964     
965     for(l=0; l<lMax; l++) {
966       l0[l] /= t;
967       l1[l] /= t;
968     }
969
970     if (Axis == XAXIS) {
971       
972       for (i=0; i<iEnd; i++) {
973         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
974         for (l=0; l<lMax; l++) {
975           int mx = T-lMax+l+1;
976           int Mx = T+l+1;
977           mx = (mx < 0) ? 0 : mx;
978           Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
979           
980           i_gpix(im, Mx, i, &val1);
981           i_gpix(im, mx, i, &val2);
982           
983           for (k=0; k<im->channels; k++) {
984             PictureValue[k] += l1[l]        * val1.channel[k];
985             PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
986           }
987         }
988         for(k=0;k<im->channels;k++) {
989           psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
990           val.channel[k]=minmax(0,255,psave);
991         }
992         i_ppix(new_img, j, i, &val);
993       }
994       
995     } else {
996       
997       for (i=0; i<iEnd; i++) {
998         for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
999         for (l=0; l < lMax; l++) {
1000           int mx = T-lMax+l+1;
1001           int Mx = T+l+1;
1002           mx = (mx < 0) ? 0 : mx;
1003           Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
1004
1005           i_gpix(im, i, Mx, &val1);
1006           i_gpix(im, i, mx, &val2);
1007           for (k=0; k<im->channels; k++) {
1008             PictureValue[k] += l1[l]        * val1.channel[k];
1009             PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; 
1010           }
1011         }
1012         for (k=0; k<im->channels; k++) {
1013           psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
1014           val.channel[k] = minmax(0, 255, psave);
1015         }
1016         i_ppix(new_img, i, j, &val);
1017       }
1018       
1019     }
1020   }
1021   myfree(l0);
1022   myfree(l1);
1023
1024   mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
1025
1026   return new_img;
1027 }
1028
1029
1030 /* 
1031 =item i_scale_nn(im, scx, scy)
1032
1033 Scale by using nearest neighbor 
1034 Both axes scaled at the same time since 
1035 nothing is gained by doing it in two steps 
1036
1037 =cut
1038 */
1039
1040
1041 i_img*
1042 i_scale_nn(i_img *im, float scx, float scy) {
1043
1044   int nxsize,nysize,nx,ny;
1045   i_img *new_img;
1046   i_color val;
1047
1048   mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
1049
1050   nxsize = (int) ((float) im->xsize * scx);
1051   if (nxsize < 1) {
1052     nxsize = 1;
1053     scx = 1 / im->xsize;
1054   }
1055   nysize = (int) ((float) im->ysize * scy);
1056   if (nysize < 1) {
1057     nysize = 1;
1058     scy = 1 / im->ysize;
1059   }
1060     
1061   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1062   
1063   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1064     i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
1065     i_ppix(new_img,nx,ny,&val);
1066   }
1067
1068   mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
1069
1070   return new_img;
1071 }
1072
1073 /*
1074 =item i_sametype(i_img *im, int xsize, int ysize)
1075
1076 Returns an image of the same type (sample size, channels, paletted/direct).
1077
1078 For paletted images the palette is copied from the source.
1079
1080 =cut
1081 */
1082
1083 i_img *i_sametype(i_img *src, int xsize, int ysize) {
1084   if (src->type == i_direct_type) {
1085     if (src->bits == 8) {
1086       return i_img_empty_ch(NULL, xsize, ysize, src->channels);
1087     }
1088     else if (src->bits == i_16_bits) {
1089       return i_img_16_new(xsize, ysize, src->channels);
1090     }
1091     else if (src->bits == i_double_bits) {
1092       return i_img_double_new(xsize, ysize, src->channels);
1093     }
1094     else {
1095       i_push_error(0, "Unknown image bits");
1096       return NULL;
1097     }
1098   }
1099   else {
1100     i_color col;
1101     int i;
1102
1103     i_img *targ = i_img_pal_new(xsize, ysize, src->channels, i_maxcolors(src));
1104     for (i = 0; i < i_colorcount(src); ++i) {
1105       i_getcolors(src, i, &col, 1);
1106       i_addcolors(targ, &col, 1);
1107     }
1108
1109     return targ;
1110   }
1111 }
1112
1113 /*
1114 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
1115
1116 Returns an image of the same type (sample size).
1117
1118 For paletted images the equivalent direct type is returned.
1119
1120 =cut
1121 */
1122
1123 i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
1124   if (src->bits == 8) {
1125     return i_img_empty_ch(NULL, xsize, ysize, channels);
1126   }
1127   else if (src->bits == i_16_bits) {
1128     return i_img_16_new(xsize, ysize, channels);
1129   }
1130   else if (src->bits == i_double_bits) {
1131     return i_img_double_new(xsize, ysize, channels);
1132   }
1133   else {
1134     i_push_error(0, "Unknown image bits");
1135     return NULL;
1136   }
1137 }
1138
1139 /*
1140 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
1141
1142 Spatially transforms I<im> returning a new image.
1143
1144 opx for a length of opxl and opy for a length of opy are arrays of
1145 operators that modify the x and y positions to retreive the pixel data from.
1146
1147 parm and parmlen define extra parameters that the operators may use.
1148
1149 Note that this function is largely superseded by the more flexible
1150 L<transform.c/i_transform2>.
1151
1152 Returns the new image.
1153
1154 The operators for this function are defined in L<stackmach.c>.
1155
1156 =cut
1157 */
1158 i_img*
1159 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
1160   double rx,ry;
1161   int nxsize,nysize,nx,ny;
1162   i_img *new_img;
1163   i_color val;
1164   
1165   mm_log((1,"i_transform(im 0x%x, opx 0x%x, opxl %d, opy 0x%x, opyl %d, parm 0x%x, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
1166
1167   nxsize = im->xsize;
1168   nysize = im->ysize ;
1169   
1170   new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
1171   /*   fprintf(stderr,"parm[2]=%f\n",parm[2]);   */
1172   for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
1173     /*     parm[parmlen-2]=(double)nx;
1174            parm[parmlen-1]=(double)ny; */
1175
1176     parm[0]=(double)nx;
1177     parm[1]=(double)ny;
1178
1179     /*     fprintf(stderr,"(%d,%d) ->",nx,ny);  */
1180     rx=i_op_run(opx,opxl,parm,parmlen);
1181     ry=i_op_run(opy,opyl,parm,parmlen);
1182     /*    fprintf(stderr,"(%f,%f)\n",rx,ry); */
1183     i_gpix(im,rx,ry,&val);
1184     i_ppix(new_img,nx,ny,&val);
1185   }
1186
1187   mm_log((1,"(0x%x) <- i_transform\n",new_img));
1188   return new_img;
1189 }
1190
1191 /*
1192 =item i_img_diff(im1, im2)
1193
1194 Calculates the sum of the squares of the differences between
1195 correspoding channels in two images.
1196
1197 If the images are not the same size then only the common area is 
1198 compared, hence even if images are different sizes this function 
1199 can return zero.
1200
1201 =cut
1202 */
1203 float
1204 i_img_diff(i_img *im1,i_img *im2) {
1205   int x,y,ch,xb,yb,chb;
1206   float tdiff;
1207   i_color val1,val2;
1208
1209   mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
1210
1211   xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
1212   yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
1213   chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
1214
1215   mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
1216
1217   tdiff=0;
1218   for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
1219     i_gpix(im1,x,y,&val1);
1220     i_gpix(im2,x,y,&val2);
1221
1222     for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
1223   }
1224   mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
1225   return tdiff;
1226 }
1227
1228 /* just a tiny demo of haar wavelets */
1229
1230 i_img*
1231 i_haar(i_img *im) {
1232   int mx,my;
1233   int fx,fy;
1234   int x,y;
1235   int ch,c;
1236   i_img *new_img,*new_img2;
1237   i_color val1,val2,dval1,dval2;
1238   
1239   mx=im->xsize;
1240   my=im->ysize;
1241   fx=(mx+1)/2;
1242   fy=(my+1)/2;
1243
1244
1245   /* horizontal pass */
1246   
1247   new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1248   new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
1249
1250   c=0; 
1251   for(y=0;y<my;y++) for(x=0;x<fx;x++) {
1252     i_gpix(im,x*2,y,&val1);
1253     i_gpix(im,x*2+1,y,&val2);
1254     for(ch=0;ch<im->channels;ch++) {
1255       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1256       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1257     }
1258     i_ppix(new_img,x,y,&dval1);
1259     i_ppix(new_img,x+fx,y,&dval2);
1260   }
1261
1262   for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
1263     i_gpix(new_img,x,y*2,&val1);
1264     i_gpix(new_img,x,y*2+1,&val2);
1265     for(ch=0;ch<im->channels;ch++) {
1266       dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
1267       dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
1268     }
1269     i_ppix(new_img2,x,y,&dval1);
1270     i_ppix(new_img2,x,y+fy,&dval2);
1271   }
1272
1273   i_img_destroy(new_img);
1274   return new_img2;
1275 }
1276
1277 /* 
1278 =item i_count_colors(im, maxc)
1279
1280 returns number of colors or -1 
1281 to indicate that it was more than max colors
1282
1283 =cut
1284 */
1285 int
1286 i_count_colors(i_img *im,int maxc) {
1287   struct octt *ct;
1288   int x,y;
1289   int xsize,ysize;
1290   i_color val;
1291   int colorcnt;
1292
1293   mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
1294
1295   xsize=im->xsize; 
1296   ysize=im->ysize;
1297   ct=octt_new();
1298  
1299   colorcnt=0;
1300   for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
1301     i_gpix(im,x,y,&val);
1302     colorcnt+=octt_add(ct,val.rgb.r,val.rgb.g,val.rgb.b);
1303     if (colorcnt > maxc) { octt_delete(ct); return -1; }
1304   }
1305   octt_delete(ct);
1306   return colorcnt;
1307 }
1308
1309 /*
1310 =back
1311
1312 =head2 8-bit per sample image internal functions
1313
1314 These are the functions installed in an 8-bit per sample image.
1315
1316 =over
1317
1318 =item i_ppix_d(im, x, y, col)
1319
1320 Internal function.
1321
1322 This is the function kept in the i_f_ppix member of an i_img object.
1323 It does a normal store of a pixel into the image with range checking.
1324
1325 Returns 0 if the pixel could be set, -1 otherwise.
1326
1327 =cut
1328 */
1329 static
1330 int
1331 i_ppix_d(i_img *im, int x, int y, i_color *val) {
1332   int ch;
1333   
1334   if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1335     for(ch=0;ch<im->channels;ch++)
1336       if (im->ch_mask&(1<<ch)) 
1337         im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
1338     return 0;
1339   }
1340   return -1; /* error was clipped */
1341 }
1342
1343 /*
1344 =item i_gpix_d(im, x, y, &col)
1345
1346 Internal function.
1347
1348 This is the function kept in the i_f_gpix member of an i_img object.
1349 It does normal retrieval of a pixel from the image with range checking.
1350
1351 Returns 0 if the pixel could be set, -1 otherwise.
1352
1353 =cut
1354 */
1355 static
1356 int 
1357 i_gpix_d(i_img *im, int x, int y, i_color *val) {
1358   int ch;
1359   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1360     for(ch=0;ch<im->channels;ch++) 
1361       val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
1362     return 0;
1363   }
1364   for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
1365   return -1; /* error was cliped */
1366 }
1367
1368 /*
1369 =item i_glin_d(im, l, r, y, vals)
1370
1371 Reads a line of data from the image, storing the pixels at vals.
1372
1373 The line runs from (l,y) inclusive to (r,y) non-inclusive
1374
1375 vals should point at space for (r-l) pixels.
1376
1377 l should never be less than zero (to avoid confusion about where to
1378 put the pixels in vals).
1379
1380 Returns the number of pixels copied (eg. if r, l or y is out of range)
1381
1382 =cut
1383 */
1384 static
1385 int
1386 i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
1387   int ch, count, i;
1388   unsigned char *data;
1389   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1390     if (r > im->xsize)
1391       r = im->xsize;
1392     data = im->idata + (l+y*im->xsize) * im->channels;
1393     count = r - l;
1394     for (i = 0; i < count; ++i) {
1395       for (ch = 0; ch < im->channels; ++ch)
1396         vals[i].channel[ch] = *data++;
1397     }
1398     return count;
1399   }
1400   else {
1401     return 0;
1402   }
1403 }
1404
1405 /*
1406 =item i_plin_d(im, l, r, y, vals)
1407
1408 Writes a line of data into the image, using the pixels at vals.
1409
1410 The line runs from (l,y) inclusive to (r,y) non-inclusive
1411
1412 vals should point at (r-l) pixels.
1413
1414 l should never be less than zero (to avoid confusion about where to
1415 get the pixels in vals).
1416
1417 Returns the number of pixels copied (eg. if r, l or y is out of range)
1418
1419 =cut
1420 */
1421 static
1422 int
1423 i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
1424   int ch, count, i;
1425   unsigned char *data;
1426   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1427     if (r > im->xsize)
1428       r = im->xsize;
1429     data = im->idata + (l+y*im->xsize) * im->channels;
1430     count = r - l;
1431     for (i = 0; i < count; ++i) {
1432       for (ch = 0; ch < im->channels; ++ch) {
1433         if (im->ch_mask & (1 << ch)) 
1434           *data = vals[i].channel[ch];
1435         ++data;
1436       }
1437     }
1438     return count;
1439   }
1440   else {
1441     return 0;
1442   }
1443 }
1444
1445 /*
1446 =item i_ppixf_d(im, x, y, val)
1447
1448 =cut
1449 */
1450 static
1451 int
1452 i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
1453   int ch;
1454   
1455   if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
1456     for(ch=0;ch<im->channels;ch++)
1457       if (im->ch_mask&(1<<ch)) {
1458         im->idata[(x+y*im->xsize)*im->channels+ch] = 
1459           SampleFTo8(val->channel[ch]);
1460       }
1461     return 0;
1462   }
1463   return -1; /* error was clipped */
1464 }
1465
1466 /*
1467 =item i_gpixf_d(im, x, y, val)
1468
1469 =cut
1470 */
1471 static
1472 int
1473 i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
1474   int ch;
1475   if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
1476     for(ch=0;ch<im->channels;ch++) {
1477       val->channel[ch] = 
1478         Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
1479     }
1480     return 0;
1481   }
1482   return -1; /* error was cliped */
1483 }
1484
1485 /*
1486 =item i_glinf_d(im, l, r, y, vals)
1487
1488 Reads a line of data from the image, storing the pixels at vals.
1489
1490 The line runs from (l,y) inclusive to (r,y) non-inclusive
1491
1492 vals should point at space for (r-l) pixels.
1493
1494 l should never be less than zero (to avoid confusion about where to
1495 put the pixels in vals).
1496
1497 Returns the number of pixels copied (eg. if r, l or y is out of range)
1498
1499 =cut
1500 */
1501 static
1502 int
1503 i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1504   int ch, count, i;
1505   unsigned char *data;
1506   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1507     if (r > im->xsize)
1508       r = im->xsize;
1509     data = im->idata + (l+y*im->xsize) * im->channels;
1510     count = r - l;
1511     for (i = 0; i < count; ++i) {
1512       for (ch = 0; ch < im->channels; ++ch)
1513         vals[i].channel[ch] = Sample8ToF(*data++);
1514     }
1515     return count;
1516   }
1517   else {
1518     return 0;
1519   }
1520 }
1521
1522 /*
1523 =item i_plinf_d(im, l, r, y, vals)
1524
1525 Writes a line of data into the image, using the pixels at vals.
1526
1527 The line runs from (l,y) inclusive to (r,y) non-inclusive
1528
1529 vals should point at (r-l) pixels.
1530
1531 l should never be less than zero (to avoid confusion about where to
1532 get the pixels in vals).
1533
1534 Returns the number of pixels copied (eg. if r, l or y is out of range)
1535
1536 =cut
1537 */
1538 static
1539 int
1540 i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
1541   int ch, count, i;
1542   unsigned char *data;
1543   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1544     if (r > im->xsize)
1545       r = im->xsize;
1546     data = im->idata + (l+y*im->xsize) * im->channels;
1547     count = r - l;
1548     for (i = 0; i < count; ++i) {
1549       for (ch = 0; ch < im->channels; ++ch) {
1550         if (im->ch_mask & (1 << ch)) 
1551           *data = SampleFTo8(vals[i].channel[ch]);
1552         ++data;
1553       }
1554     }
1555     return count;
1556   }
1557   else {
1558     return 0;
1559   }
1560 }
1561
1562 /*
1563 =item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count)
1564
1565 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1566 for the channels specified by chans, an array of int with chan_count
1567 elements.
1568
1569 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1570
1571 =cut
1572 */
1573 static
1574 int
1575 i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, 
1576               const int *chans, int chan_count) {
1577   int ch, count, i, w;
1578   unsigned char *data;
1579
1580   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1581     if (r > im->xsize)
1582       r = im->xsize;
1583     data = im->idata + (l+y*im->xsize) * im->channels;
1584     w = r - l;
1585     count = 0;
1586
1587     if (chans) {
1588       /* make sure we have good channel numbers */
1589       for (ch = 0; ch < chan_count; ++ch) {
1590         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1591           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1592           return 0;
1593         }
1594       }
1595       for (i = 0; i < w; ++i) {
1596         for (ch = 0; ch < chan_count; ++ch) {
1597           *samps++ = data[chans[ch]];
1598           ++count;
1599         }
1600         data += im->channels;
1601       }
1602     }
1603     else {
1604       for (i = 0; i < w; ++i) {
1605         for (ch = 0; ch < chan_count; ++ch) {
1606           *samps++ = data[ch];
1607           ++count;
1608         }
1609         data += im->channels;
1610       }
1611     }
1612
1613     return count;
1614   }
1615   else {
1616     return 0;
1617   }
1618 }
1619
1620 /*
1621 =item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count)
1622
1623 Reads sample values from im for the horizontal line (l, y) to (r-1,y)
1624 for the channels specified by chan_mask, where bit 0 is the first
1625 channel.
1626
1627 Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
1628
1629 =cut
1630 */
1631 static
1632 int
1633 i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, 
1634            const int *chans, int chan_count) {
1635   int ch, count, i, w;
1636   unsigned char *data;
1637   for (ch = 0; ch < chan_count; ++ch) {
1638     if (chans[ch] < 0 || chans[ch] >= im->channels) {
1639       i_push_errorf(0, "No channel %d in this image", chans[ch]);
1640     }
1641   }
1642   if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
1643     if (r > im->xsize)
1644       r = im->xsize;
1645     data = im->idata + (l+y*im->xsize) * im->channels;
1646     w = r - l;
1647     count = 0;
1648
1649     if (chans) {
1650       /* make sure we have good channel numbers */
1651       for (ch = 0; ch < chan_count; ++ch) {
1652         if (chans[ch] < 0 || chans[ch] >= im->channels) {
1653           i_push_errorf(0, "No channel %d in this image", chans[ch]);
1654           return 0;
1655         }
1656       }
1657       for (i = 0; i < w; ++i) {
1658         for (ch = 0; ch < chan_count; ++ch) {
1659           *samps++ = Sample8ToF(data[chans[ch]]);
1660           ++count;
1661         }
1662         data += im->channels;
1663       }
1664     }
1665     else {
1666       for (i = 0; i < w; ++i) {
1667         for (ch = 0; ch < chan_count; ++ch) {
1668           *samps++ = Sample8ToF(data[ch]);
1669           ++count;
1670         }
1671         data += im->channels;
1672       }
1673     }
1674     return count;
1675   }
1676   else {
1677     return 0;
1678   }
1679 }
1680
1681 /*
1682 =back
1683
1684 =head2 Image method wrappers
1685
1686 These functions provide i_fsample_t functions in terms of their
1687 i_sample_t versions.
1688
1689 =over
1690
1691 =item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1692
1693 =cut
1694 */
1695
1696 int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1697   i_color temp;
1698   int ch;
1699
1700   for (ch = 0; ch < im->channels; ++ch)
1701     temp.channel[ch] = SampleFTo8(pix->channel[ch]);
1702   
1703   return i_ppix(im, x, y, &temp);
1704 }
1705
1706 /*
1707 =item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix)
1708
1709 =cut
1710 */
1711 int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) {
1712   i_color temp;
1713   int ch;
1714
1715   if (i_gpix(im, x, y, &temp)) {
1716     for (ch = 0; ch < im->channels; ++ch)
1717       pix->channel[ch] = Sample8ToF(temp.channel[ch]);
1718     return 0;
1719   }
1720   else 
1721     return -1;
1722 }
1723
1724 /*
1725 =item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1726
1727 =cut
1728 */
1729 int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1730   i_color *work;
1731
1732   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1733     if (r > im->xsize)
1734       r = im->xsize;
1735     if (r > l) {
1736       int ret;
1737       int i, ch;
1738       work = mymalloc(sizeof(i_color) * (r-l));
1739       for (i = 0; i < r-l; ++i) {
1740         for (ch = 0; ch < im->channels; ++ch) 
1741           work[i].channel[ch] = SampleFTo8(pix[i].channel[ch]);
1742       }
1743       ret = i_plin(im, l, r, y, work);
1744       myfree(work);
1745
1746       return ret;
1747     }
1748     else {
1749       return 0;
1750     }
1751   }
1752   else {
1753     return 0;
1754   }
1755 }
1756
1757 /*
1758 =item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix)
1759
1760 =cut
1761 */
1762 int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) {
1763   i_color *work;
1764
1765   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1766     if (r > im->xsize)
1767       r = im->xsize;
1768     if (r > l) {
1769       int ret;
1770       int i, ch;
1771       work = mymalloc(sizeof(i_color) * (r-l));
1772       ret = i_plin(im, l, r, y, work);
1773       for (i = 0; i < r-l; ++i) {
1774         for (ch = 0; ch < im->channels; ++ch) 
1775           pix[i].channel[ch] = Sample8ToF(work[i].channel[ch]);
1776       }
1777       myfree(work);
1778
1779       return ret;
1780     }
1781     else {
1782       return 0;
1783     }
1784   }
1785   else {
1786     return 0;
1787   }
1788 }
1789
1790 /*
1791 =item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count)
1792
1793 =cut
1794 */
1795 int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, 
1796                 int const *chans, int chan_count) {
1797   i_sample_t *work;
1798
1799   if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
1800     if (r > im->xsize)
1801       r = im->xsize;
1802     if (r > l) {
1803       int ret;
1804       int i;
1805       work = mymalloc(sizeof(i_sample_t) * (r-l));
1806       ret = i_gsamp(im, l, r, y, work, chans, chan_count);
1807       for (i = 0; i < ret; ++i) {
1808           samp[i] = Sample8ToF(work[i]);
1809       }
1810       myfree(work);
1811
1812       return ret;
1813     }
1814     else {
1815       return 0;
1816     }
1817   }
1818   else {
1819     return 0;
1820   }
1821 }
1822
1823 /*
1824 =back
1825
1826 =head2 Palette wrapper functions
1827
1828 Used for virtual images, these forward palette calls to a wrapped image, 
1829 assuming the wrapped image is the first pointer in the structure that 
1830 im->ext_data points at.
1831
1832 =over
1833
1834 =item i_addcolors_forward(i_img *im, i_color *colors, int count)
1835
1836 =cut
1837 */
1838 int i_addcolors_forward(i_img *im, i_color *colors, int count) {
1839   return i_addcolors(*(i_img **)im->ext_data, colors, count);
1840 }
1841
1842 /*
1843 =item i_getcolors_forward(i_img *im, int i, i_color *color, int count)
1844
1845 =cut
1846 */
1847 int i_getcolors_forward(i_img *im, int i, i_color *color, int count) {
1848   return i_getcolors(*(i_img **)im->ext_data, i, color, count);
1849 }
1850
1851 /*
1852 =item i_setcolors_forward(i_img *im, int i, i_color *color, int count)
1853
1854 =cut
1855 */
1856 int i_setcolors_forward(i_img *im, int i, i_color *color, int count) {
1857   return i_setcolors(*(i_img **)im->ext_data, i, color, count);
1858 }
1859
1860 /*
1861 =item i_colorcount_forward(i_img *im)
1862
1863 =cut
1864 */
1865 int i_colorcount_forward(i_img *im) {
1866   return i_colorcount(*(i_img **)im->ext_data);
1867 }
1868
1869 /*
1870 =item i_maxcolors_forward(i_img *im)
1871
1872 =cut
1873 */
1874 int i_maxcolors_forward(i_img *im) {
1875   return i_maxcolors(*(i_img **)im->ext_data);
1876 }
1877
1878 /*
1879 =item i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry)
1880
1881 =cut
1882 */
1883 int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry) {
1884   return i_findcolor(*(i_img **)im->ext_data, color, entry);
1885 }
1886
1887 /*
1888 =back
1889
1890 =head2 Stream reading and writing wrapper functions
1891
1892 =over
1893
1894 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
1895
1896 Performs general read buffering for file readers that permit reading
1897 to be done through a callback.
1898
1899 The final callback gets two parameters, a I<need> value, and a I<want>
1900 value, where I<need> is the amount of data that the file library needs
1901 to read, and I<want> is the amount of space available in the buffer
1902 maintained by these functions.
1903
1904 This means if you need to read from a stream that you don't know the
1905 length of, you can return I<need> bytes, taking the performance hit of
1906 possibly expensive callbacks (eg. back to perl code), or if you are
1907 reading from a stream where it doesn't matter if some data is lost, or
1908 if the total length of the stream is known, you can return I<want>
1909 bytes.
1910
1911 =cut 
1912 */
1913
1914 int
1915 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
1916   int total;
1917
1918   if (length < gci->length - gci->cpos) {
1919     /* simplest case */
1920     memcpy(buf, gci->buffer+gci->cpos, length);
1921     gci->cpos += length;
1922     return length;
1923   }
1924   
1925   total = 0;
1926   memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
1927   total  += gci->length - gci->cpos;
1928   length -= gci->length - gci->cpos;
1929   buf    += gci->length - gci->cpos;
1930   if (length < (int)sizeof(gci->buffer)) {
1931     int did_read;
1932     int copy_size;
1933     while (length
1934            && (did_read = (gci->cb)(gci->userdata, gci->buffer, length, 
1935                                     sizeof(gci->buffer))) > 0) {
1936       gci->cpos = 0;
1937       gci->length = did_read;
1938
1939       copy_size = i_min(length, gci->length);
1940       memcpy(buf, gci->buffer, copy_size);
1941       gci->cpos += copy_size;
1942       buf += copy_size;
1943       total += copy_size;
1944       length -= copy_size;
1945     }
1946   }
1947   else {
1948     /* just read the rest - too big for our buffer*/
1949     int did_read;
1950     while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1951       length -= did_read;
1952       total += did_read;
1953       buf += did_read;
1954     }
1955   }
1956   return total;
1957 }
1958
1959 /*
1960 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1961
1962 For use by callback file readers to initialize the reader buffer.
1963
1964 Allocates, initializes and returns the reader buffer.
1965
1966 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1967
1968 =cut
1969 */
1970 i_gen_read_data *
1971 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1972   i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1973   self->cb = cb;
1974   self->userdata = userdata;
1975   self->length = 0;
1976   self->cpos = 0;
1977
1978   return self;
1979 }
1980
1981 /*
1982 =item i_free_gen_read_data(i_gen_read_data *)
1983
1984 Cleans up.
1985
1986 =cut
1987 */
1988 void i_free_gen_read_data(i_gen_read_data *self) {
1989   myfree(self);
1990 }
1991
1992 /*
1993 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1994
1995 Performs write buffering for a callback based file writer.
1996
1997 Failures are considered fatal, if a write fails then data will be
1998 dropped.
1999
2000 =cut
2001 */
2002 int 
2003 i_gen_writer(
2004 i_gen_write_data *self, 
2005 char const *data, 
2006 int size)
2007 {
2008   if (self->filledto && self->filledto+size > self->maxlength) {
2009     if (self->cb(self->userdata, self->buffer, self->filledto)) {
2010       self->filledto = 0;
2011     }
2012     else {
2013       self->filledto = 0;
2014       return 0;
2015     }
2016   }
2017   if (self->filledto+size <= self->maxlength) {
2018     /* just save it */
2019     memcpy(self->buffer+self->filledto, data, size);
2020     self->filledto += size;
2021     return 1;
2022   }
2023   /* doesn't fit - hand it off */
2024   return self->cb(self->userdata, data, size);
2025 }
2026
2027 /*
2028 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
2029
2030 Allocates and initializes the data structure used by i_gen_writer.
2031
2032 This should be released with L<image.c/i_free_gen_write_data>
2033
2034 =cut
2035 */
2036 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, 
2037                                        char *userdata, int max_length)
2038 {
2039   i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
2040   self->cb = cb;
2041   self->userdata = userdata;
2042   self->maxlength = i_min(max_length, sizeof(self->buffer));
2043   if (self->maxlength < 0)
2044     self->maxlength = sizeof(self->buffer);
2045   self->filledto = 0;
2046
2047   return self;
2048 }
2049
2050 /*
2051 =item i_free_gen_write_data(i_gen_write_data *info, int flush)
2052
2053 Cleans up the write buffer.
2054
2055 Will flush any left-over data if I<flush> is non-zero.
2056
2057 Returns non-zero if flush is zero or if info->cb() returns non-zero.
2058
2059 Return zero only if flush is non-zero and info->cb() returns zero.
2060 ie. if it fails.
2061
2062 =cut
2063 */
2064
2065 int i_free_gen_write_data(i_gen_write_data *info, int flush)
2066 {
2067   int result = !flush || 
2068     info->filledto == 0 ||
2069     info->cb(info->userdata, info->buffer, info->filledto);
2070   myfree(info);
2071
2072   return result;
2073 }
2074
2075
2076
2077 /*
2078 =item i_test_format_probe(io_glue *data, int length)
2079
2080 Check the beginning of the supplied file for a 'magic number'
2081
2082 =cut
2083 */
2084
2085
2086 char *
2087 i_test_format_probe(io_glue *data, int length) {
2088
2089   static struct {
2090     char *magic;
2091     char *name;
2092   } formats[] = {
2093     {"\xFF\xD8", "jpeg"},
2094     {"GIF87a", "gif"},
2095     {"GIF89a", "gif"},
2096     {"MM\0*", "tiff"},
2097     {"II*\0", "tiff"},
2098     {"BM", "bmp"},
2099     {"\x89PNG\x0d\x0a\x1a\x0a", "png"},
2100     {"P1", "pnm"},
2101     {"P2", "pnm"},
2102     {"P3", "pnm"},
2103     {"P4", "pnm"},
2104     {"P5", "pnm"},
2105     {"P6", "pnm"},
2106   };
2107   unsigned int i;
2108   char head[18];
2109   char *match = NULL;
2110   ssize_t rc;
2111
2112   io_glue_commit_types(data);
2113   rc = data->readcb(data, head, 18);
2114   if (rc == -1) return NULL;
2115   data->seekcb(data, -rc, SEEK_CUR);
2116
2117   for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) { 
2118     int c;
2119     ssize_t len = strlen(formats[i].magic);
2120     if (rc<len) continue;
2121     c = !strncmp(formats[i].magic, head, len);
2122     if (c) {
2123       match = formats[i].name;
2124       break;
2125     }
2126   }
2127
2128   /*
2129     if (match && !strcmp(match, "jpeg")) {
2130     unsigned int x0, x1;
2131     rc = data->readcb(data, head, 18);
2132     if (rc == -1) return NULL;
2133     x0 = (unsigned char)head[0];
2134     x1 = (unsigned char)head[1];
2135     data->seekcb(data, -rc, SEEK_CUR);
2136     printf("Jpeg reread: %x %x\n", x0, x1);
2137     }
2138   */
2139
2140   if (!match && 
2141       (rc == 18) &&
2142       tga_header_verify(head)) return "tga";
2143   return match;
2144 }
2145
2146
2147
2148
2149 /*
2150 =back
2151
2152 =head1 AUTHOR
2153
2154 Arnar M. Hrafnkelsson <addi@umich.edu>
2155
2156 Tony Cook <tony@develop-help.com>
2157
2158 =head1 SEE ALSO
2159
2160 L<Imager>, L<gif.c>
2161
2162 =cut
2163 */