File Coverage

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