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