File Coverage

image.c
Criterion Covered Total %
statement 494 660 74.8
branch 259 418 61.9
condition n/a
subroutine n/a
pod n/a
total 753 1078 69.8


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