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