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