File Coverage

maskimg.c
Criterion Covered Total %
statement 279 279 100.0
branch 235 262 89.6
condition n/a
subroutine n/a
pod n/a
total 514 541 95.0


line stmt bran cond sub pod time code
1             /*
2             =head1 NAME
3              
4             maskimg.c - implements masked images/image subsets
5              
6             =head1 SYNOPSIS
7              
8             =head1 DESCRIPTION
9              
10             =over
11             =cut
12             */
13              
14             #define IMAGER_NO_CONTEXT
15              
16             #include "imager.h"
17             #include "imageri.h"
18              
19             #include
20             /*
21             =item i_img_mask_ext
22              
23             A pointer to this type of object is kept in the ext_data of a masked
24             image.
25              
26             =cut
27             */
28              
29             typedef struct {
30             i_img *targ;
31             i_img *mask;
32             i_img_dim xbase, ybase;
33             i_sample_t *samps; /* temp space */
34             } i_img_mask_ext;
35              
36             #define MASKEXT(im) ((i_img_mask_ext *)((im)->ext_data))
37              
38             static void i_destroy_masked(i_img *im);
39             static int i_ppix_masked(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix);
40             static int i_ppixf_masked(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix);
41             static i_img_dim i_plin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
42             static i_img_dim i_plinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
43             static int i_gpix_masked(i_img *im, i_img_dim x, i_img_dim y, i_color *pix);
44             static int i_gpixf_masked(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix);
45             static i_img_dim i_glin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
46             static i_img_dim i_glinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
47             static i_img_dim i_gsamp_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp,
48             int const *chans, int chan_count);
49             static i_img_dim i_gsampf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
50             int const *chans, int chan_count);
51             static i_img_dim i_gpal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals);
52             static i_img_dim i_ppal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals);
53             static i_img_dim
54             psamp_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
55             const i_sample_t *samples, const int *chans, int chan_count);
56             static i_img_dim
57             psampf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
58             const i_fsample_t *samples, const int *chans, int chan_count);
59              
60             /*
61             =item IIM_base_masked
62              
63             The basic data we copy into a masked image.
64              
65             =cut
66             */
67             static i_img IIM_base_masked =
68             {
69             0, /* channels set */
70             0, 0, 0, /* xsize, ysize, bytes */
71             ~0U, /* ch_mask */
72             i_8_bits, /* bits */
73             i_palette_type, /* type */
74             1, /* virtual */
75             NULL, /* idata */
76             { 0, 0, NULL }, /* tags */
77             NULL, /* ext_data */
78              
79             i_ppix_masked, /* i_f_ppix */
80             i_ppixf_masked, /* i_f_ppixf */
81             i_plin_masked, /* i_f_plin */
82             i_plinf_masked, /* i_f_plinf */
83             i_gpix_masked, /* i_f_gpix */
84             i_gpixf_masked, /* i_f_gpixf */
85             i_glin_masked, /* i_f_glin */
86             i_glinf_masked, /* i_f_glinf */
87             i_gsamp_masked, /* i_f_gsamp */
88             i_gsampf_masked, /* i_f_gsampf */
89              
90             i_gpal_masked, /* i_f_gpal */
91             i_ppal_masked, /* i_f_ppal */
92             i_addcolors_forward, /* i_f_addcolors */
93             i_getcolors_forward, /* i_f_getcolors */
94             i_colorcount_forward, /* i_f_colorcount */
95             i_maxcolors_forward, /* i_f_maxcolors */
96             i_findcolor_forward, /* i_f_findcolor */
97             i_setcolors_forward, /* i_f_setcolors */
98              
99             i_destroy_masked, /* i_f_destroy */
100              
101             NULL, /* i_f_gsamp_bits */
102             NULL, /* i_f_psamp_bits */
103              
104             psamp_masked, /* i_f_psamp */
105             psampf_masked /* i_f_psampf */
106             };
107              
108             /*
109             =item i_img_masked_new(i_img *targ, i_img *mask, i_img_dim xbase, i_img_dim ybase, i_img_dim w, i_img_dim h)
110              
111             Create a new masked image.
112              
113             The image mask is optional, in which case the image is just a view of
114             a rectangular portion of the image.
115              
116             The mask only has an effect of writing to the image, the entire view
117             of the underlying image is readable.
118              
119             pixel access to mimg(x,y) is translated to targ(x+xbase, y+ybase), as long
120             as (0 <= x < w) and (0 <= y < h).
121              
122             For a pixel to be writable, the pixel mask(x,y) must have non-zero in
123             it's first channel. No scaling of the pixel is done, the channel
124             sample is treated as boolean.
125              
126             =cut
127             */
128              
129             i_img *
130 24           i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y, i_img_dim w, i_img_dim h) {
131             i_img *im;
132             i_img_mask_ext *ext;
133 24           dIMCTXim(targ);
134              
135 24           im_clear_error(aIMCTX);
136 24 100         if (x < 0 || x >= targ->xsize || y < 0 || y >= targ->ysize) {
    100          
    100          
    50          
137 3           im_push_error(aIMCTX, 0, "subset outside of target image");
138 3           return NULL;
139             }
140 21 100         if (mask) {
141 7 100         if (w > mask->xsize)
142 3           w = mask->xsize;
143 7 100         if (h > mask->ysize)
144 3           h = mask->ysize;
145             }
146 21 100         if (x+w > targ->xsize)
147 1           w = targ->xsize - x;
148 21 100         if (y+h > targ->ysize)
149 1           h = targ->ysize - y;
150              
151 21 100         if (w < 1 || h < 1) {
    100          
152 4           im_push_error(aIMCTX, 0, "width and height must be greater than or equal to 1");
153 4           return NULL;
154             }
155              
156 17           im = im_img_alloc(aIMCTX);
157              
158 17           memcpy(im, &IIM_base_masked, sizeof(i_img));
159 17           i_tags_new(&im->tags);
160 17           im->xsize = w;
161 17           im->ysize = h;
162 17           im->channels = targ->channels;
163 17           im->bits = targ->bits;
164 17           im->type = targ->type;
165 17           ext = mymalloc(sizeof(*ext));
166 17           ext->targ = targ;
167 17           ext->mask = mask;
168 17           ext->xbase = x;
169 17           ext->ybase = y;
170 17           ext->samps = mymalloc(sizeof(i_sample_t) * im->xsize);
171 17           im->ext_data = ext;
172              
173 17           im_img_init(aIMCTX, im);
174              
175 17           return im;
176             }
177              
178             /*
179             =item i_destroy_masked(i_img *im)
180              
181             The destruction handler for masked images.
182              
183             Releases the ext_data.
184              
185             Internal function.
186              
187             =cut
188             */
189              
190 17           static void i_destroy_masked(i_img *im) {
191 17           myfree(MASKEXT(im)->samps);
192 17           myfree(im->ext_data);
193 17           }
194              
195             /*
196             =item i_ppix_masked(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix)
197              
198             Write a pixel to a masked image.
199              
200             Internal function.
201              
202             =cut
203             */
204 3           static int i_ppix_masked(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix) {
205 3           i_img_mask_ext *ext = MASKEXT(im);
206             int result;
207              
208 3 50         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    50          
    50          
209 1           return -1;
210 2 50         if (ext->mask) {
211             i_sample_t samp;
212            
213 2 50         if (i_gsamp(ext->mask, x, x+1, y, &samp, NULL, 1) && !samp)
    100          
214 1           return 0; /* pretend it was good */
215             }
216 1           result = i_ppix(ext->targ, x + ext->xbase, y + ext->ybase, pix);
217 1           im->type = ext->targ->type;
218 1           return result;
219             }
220              
221             /*
222             =item i_ppixf_masked(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix)
223              
224             Write a pixel to a masked image.
225              
226             Internal function.
227              
228             =cut
229             */
230 3           static int i_ppixf_masked(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) {
231 3           i_img_mask_ext *ext = MASKEXT(im);
232             int result;
233              
234 3 50         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    50          
    50          
    100          
235 1           return -1;
236 2 50         if (ext->mask) {
237             i_sample_t samp;
238            
239 2 50         if (i_gsamp(ext->mask, x, x+1, y, &samp, NULL, 1) && !samp)
    100          
240 1           return 0; /* pretend it was good */
241             }
242 1           result = i_ppixf(ext->targ, x + ext->xbase, y + ext->ybase, pix);
243 1           im->type = ext->targ->type;
244 1           return result;
245             }
246              
247             /*
248             =item i_plin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals)
249              
250             Write a row of data to a masked image.
251              
252             Internal function.
253              
254             =cut
255             */
256 265           static i_img_dim i_plin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) {
257 265           i_img_mask_ext *ext = MASKEXT(im);
258              
259 265 50         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    100          
    50          
260 264 100         if (r > im->xsize)
261 1           r = im->xsize;
262 264 100         if (ext->mask) {
263             i_img_dim i;
264 213           int simple = 0;
265 213           i_sample_t *samps = ext->samps;
266 213           i_img_dim w = r - l;
267              
268 213           i_gsamp(ext->mask, l, r, y, samps, NULL, 1);
269 213 100         if (w < 10)
270 1           simple = 1;
271             else {
272             /* the idea is to make a fast scan to see how often the state
273             changes */
274 212           i_img_dim changes = 0;
275 15392 100         for (i = 0; i < w-1; ++i)
276 15180 100         if (!samps[i] != !samps[i+1])
277 404           ++changes;
278 212 100         if (changes > w/3) /* just rough */
279 1           simple = 1;
280             }
281 213 100         if (simple) {
282             /* we'd be calling a usually more complicated i_plin function
283             almost as often as the usually simple i_ppix(), so just
284             do a simple scan
285             */
286 26 100         for (i = 0; i < w; ++i) {
287 24 100         if (samps[i])
288 10           i_ppix(ext->targ, l + i + ext->xbase, y + ext->ybase, vals + i);
289             }
290 2           im->type = ext->targ->type;
291 2           return r-l;
292             }
293             else {
294             /* the scan above indicates there should be some contiguous
295             regions, look for them and render
296             */
297             i_img_dim start;
298 211           i = 0;
299 615 100         while (i < w) {
300 4714 100         while (i < w && !samps[i])
    100          
301 4310           ++i;
302 404           start = i;
303 11466 100         while (i < w && samps[i])
    100          
304 11062           ++i;
305 404 100         if (i != start)
306 193           i_plin(ext->targ, l + start + ext->xbase, l + i + ext->xbase,
307             y + ext->ybase, vals + start);
308             }
309 211           im->type = ext->targ->type;
310 211           return w;
311             }
312             }
313             else {
314 51           i_img_dim result = i_plin(ext->targ, l + ext->xbase, r + ext->xbase,
315             y + ext->ybase, vals);
316 51           im->type = ext->targ->type;
317 51           return result;
318             }
319             }
320             else {
321 1           return 0;
322             }
323             }
324              
325             /*
326             =item i_plinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals)
327              
328             Write a row of data to a masked image.
329              
330             Internal function.
331              
332             =cut
333             */
334 5           static i_img_dim i_plinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) {
335 5           i_img_mask_ext *ext = MASKEXT(im);
336 5 50         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    100          
    50          
337 4 100         if (r > im->xsize)
338 1           r = im->xsize;
339 4 100         if (ext->mask) {
340             i_img_dim i;
341 3           int simple = 0;
342 3           i_sample_t *samps = ext->samps;
343 3           i_img_dim w = r - l;
344              
345 3           i_gsamp(ext->mask, l, r, y, samps, NULL, 1);
346 3 100         if (w < 10)
347 1           simple = 1;
348             else {
349             /* the idea is to make a fast scan to see how often the state
350             changes */
351 2           i_img_dim changes = 0;
352 92 100         for (i = 0; i < w-1; ++i)
353 90 100         if (!samps[i] != !samps[i+1])
354 20           ++changes;
355 2 100         if (changes > w/3) /* just rough */
356 1           simple = 1;
357             }
358 3 100         if (simple) {
359             /* we'd be calling a usually more complicated i_plin function
360             almost as often as the usually simple i_ppix(), so just
361             do a simple scan
362             */
363 26 100         for (i = 0; i < w; ++i) {
364 24 100         if (samps[i])
365 10           i_ppixf(ext->targ, l + i + ext->xbase, y + ext->ybase, vals+i);
366             }
367 2           im->type = ext->targ->type;
368 2           return r-l;
369             }
370             else {
371             /* the scan above indicates there should be some contiguous
372             regions, look for them and render
373             */
374             i_img_dim start;
375 1           i = 0;
376 3 100         while (i < w) {
377 38 100         while (i < w && !samps[i])
    100          
378 36           ++i;
379 2           start = i;
380 38 100         while (i < w && samps[i])
    100          
381 36           ++i;
382 2 100         if (i != start)
383 1           i_plinf(ext->targ, l + start + ext->xbase, l + i + ext->xbase,
384             y + ext->ybase, vals + start);
385             }
386 1           im->type = ext->targ->type;
387 1           return w;
388             }
389             }
390             else {
391 1           i_img_dim result = i_plinf(ext->targ, l + ext->xbase, r + ext->xbase,
392             y + ext->ybase, vals);
393 1           im->type = ext->targ->type;
394 1           return result;
395             }
396             }
397             else {
398 1           return 0;
399             }
400             }
401              
402             /*
403             =item i_gpix_masked(i_img *im, i_img_dim x, i_img_dim y, i_color *pix)
404              
405             Read a pixel from a masked image.
406              
407             Internal.
408              
409             =cut
410             */
411 23079           static int i_gpix_masked(i_img *im, i_img_dim x, i_img_dim y, i_color *pix) {
412 23079           i_img_mask_ext *ext = MASKEXT(im);
413              
414 23079 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
415 4           return -1;
416              
417 23075           return i_gpix(ext->targ, x + ext->xbase, y + ext->ybase, pix);
418             }
419              
420             /*
421             =item i_gpixf_masked(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix)
422              
423             Read a pixel from a masked image.
424              
425             Internal.
426              
427             =cut
428             */
429 5           static int i_gpixf_masked(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) {
430 5           i_img_mask_ext *ext = MASKEXT(im);
431              
432 5 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
433 4           return -1;
434              
435 1           return i_gpixf(ext->targ, x + ext->xbase, y + ext->ybase, pix);
436             }
437              
438 6           static i_img_dim i_glin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) {
439 6           i_img_mask_ext *ext = MASKEXT(im);
440 6 100         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
441 2 100         if (r > im->xsize)
442 1           r = im->xsize;
443 2           return i_glin(ext->targ, l + ext->xbase, r + ext->xbase,
444             y + ext->ybase, vals);
445             }
446             else {
447 4           return 0;
448             }
449             }
450              
451 6           static i_img_dim i_glinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) {
452 6           i_img_mask_ext *ext = MASKEXT(im);
453 6 100         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
454 2 100         if (r > im->xsize)
455 1           r = im->xsize;
456 2           return i_glinf(ext->targ, l + ext->xbase, r + ext->xbase,
457             y + ext->ybase, vals);
458             }
459             else {
460 4           return 0;
461             }
462             }
463              
464 310           static i_img_dim i_gsamp_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp,
465             int const *chans, int chan_count) {
466 310           i_img_mask_ext *ext = MASKEXT(im);
467 310 100         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
468 306 100         if (r > im->xsize)
469 1           r = im->xsize;
470 306           return i_gsamp(ext->targ, l + ext->xbase, r + ext->xbase,
471             y + ext->ybase, samp, chans, chan_count);
472             }
473             else {
474 4           return 0;
475             }
476             }
477              
478 6           static i_img_dim i_gsampf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
479             int const *chans, int chan_count) {
480 6           i_img_mask_ext *ext = MASKEXT(im);
481 6 100         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
482 2 100         if (r > im->xsize)
483 1           r = im->xsize;
484 2           return i_gsampf(ext->targ, l + ext->xbase, r + ext->xbase,
485             y + ext->ybase, samp, chans, chan_count);
486             }
487             else {
488 4           return 0;
489             }
490             }
491              
492 2           static i_img_dim i_gpal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals) {
493 2           i_img_mask_ext *ext = MASKEXT(im);
494 2 50         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    100          
495 1 50         if (r > im->xsize)
496 1           r = im->xsize;
497 1 50         return i_gpal(ext->targ, l + ext->xbase, r + ext->xbase,
498             y + ext->ybase, vals);
499             }
500             else {
501 1           return 0;
502             }
503             }
504              
505 4           static i_img_dim i_ppal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals) {
506 4           i_img_mask_ext *ext = MASKEXT(im);
507 4 50         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    100          
508 3 100         if (r > im->xsize)
509 1           r = im->xsize;
510 3 100         if (ext->mask) {
511             i_img_dim i;
512 2           i_sample_t *samps = ext->samps;
513 2           i_img_dim w = r - l;
514             i_img_dim start;
515            
516 2           i_gsamp(ext->mask, l, r, y, samps, NULL, 1);
517 2           i = 0;
518 5 100         while (i < w) {
519 14 100         while (i < w && !samps[i])
    100          
520 11           ++i;
521 3           start = i;
522 42 100         while (i < w && samps[i])
    100          
523 39           ++i;
524 3 100         if (i != start)
525 1 50         i_ppal(ext->targ, l+start+ext->xbase, l+i+ext->xbase,
526             y+ext->ybase, vals+start);
527             }
528 2           return w;
529             }
530             else {
531 1 50         return i_ppal(ext->targ, l + ext->xbase, r + ext->xbase,
532             y + ext->ybase, vals);
533             }
534             }
535             else {
536 1           return 0;
537             }
538             }
539              
540             /*
541             =item psamp_masked()
542              
543             i_psamp() implementation for masked images.
544              
545             =cut
546             */
547              
548             static i_img_dim
549 25           psamp_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
550             const i_sample_t *samples, const int *chans, int chan_count) {
551 25           i_img_mask_ext *ext = MASKEXT(im);
552              
553 25 100         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
554 17           unsigned old_ch_mask = ext->targ->ch_mask;
555 17           i_img_dim result = 0;
556 17           ext->targ->ch_mask = im->ch_mask;
557 17 100         if (r > im->xsize)
558 2           r = im->xsize;
559 17 100         if (ext->mask) {
560 9           i_img_dim w = r - l;
561 9           i_img_dim i = 0;
562 9           i_img_dim x = ext->xbase + l;
563 9           i_img_dim work_y = y + ext->ybase;
564 9           i_sample_t *mask_samps = ext->samps;
565            
566 9           i_gsamp(ext->mask, l, r, y, mask_samps, NULL, 1);
567             /* not optimizing this yet */
568 22 100         while (i < w) {
569 13 100         if (mask_samps[i]) {
570             /* found a set mask value, try to do a run */
571 10           i_img_dim run_left = x;
572 10           const i_sample_t *run_samps = samples;
573 10           ++i;
574 10           ++x;
575 10           samples += chan_count;
576            
577 26 100         while (i < w && mask_samps[i]) {
    100          
578 16           ++i;
579 16           ++x;
580 16           samples += chan_count;
581             }
582 10           result += i_psamp(ext->targ, run_left, x, work_y, run_samps, chans, chan_count);
583             }
584             else {
585 3           ++i;
586 3           ++x;
587 3           samples += chan_count;
588 3           result += chan_count; /* pretend we wrote masked off pixels */
589             }
590             }
591             }
592             else {
593 8           result = i_psamp(ext->targ, l + ext->xbase, r + ext->xbase,
594             y + ext->ybase, samples, chans, chan_count);
595 8           im->type = ext->targ->type;
596             }
597 17           ext->targ->ch_mask = old_ch_mask;
598 17           return result;
599             }
600             else {
601 8           dIMCTXim(im);
602 8           i_push_error(0, "Image position outside of image");
603 8           return -1;
604             }
605             }
606              
607             /*
608             =item psampf_masked()
609              
610             i_psampf() implementation for masked images.
611              
612             =cut
613             */
614              
615             static i_img_dim
616 25           psampf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
617             const i_fsample_t *samples, const int *chans, int chan_count) {
618 25           i_img_mask_ext *ext = MASKEXT(im);
619              
620 25 100         if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
621 17           i_img_dim result = 0;
622 17           unsigned old_ch_mask = ext->targ->ch_mask;
623 17           ext->targ->ch_mask = im->ch_mask;
624 17 100         if (r > im->xsize)
625 2           r = im->xsize;
626 17 100         if (ext->mask) {
627 9           i_img_dim w = r - l;
628 9           i_img_dim i = 0;
629 9           i_img_dim x = ext->xbase + l;
630 9           i_img_dim work_y = y + ext->ybase;
631 9           i_sample_t *mask_samps = ext->samps;
632            
633 9           i_gsamp(ext->mask, l, r, y, mask_samps, NULL, 1);
634             /* not optimizing this yet */
635 22 100         while (i < w) {
636 13 100         if (mask_samps[i]) {
637             /* found a set mask value, try to do a run */
638 10           i_img_dim run_left = x;
639 10           const i_fsample_t *run_samps = samples;
640 10           ++i;
641 10           ++x;
642 10           samples += chan_count;
643            
644 26 100         while (i < w && mask_samps[i]) {
    100          
645 16           ++i;
646 16           ++x;
647 16           samples += chan_count;
648             }
649 10           result += i_psampf(ext->targ, run_left, x, work_y, run_samps, chans, chan_count);
650             }
651             else {
652 3           ++i;
653 3           ++x;
654 3           samples += chan_count;
655 3           result += chan_count; /* pretend we wrote masked off pixels */
656             }
657             }
658             }
659             else {
660 8           result = i_psampf(ext->targ, l + ext->xbase, r + ext->xbase,
661             y + ext->ybase, samples,
662             chans, chan_count);
663 8           im->type = ext->targ->type;
664             }
665 17           ext->targ->ch_mask = old_ch_mask;
666 17           return result;
667             }
668             else {
669 8           dIMCTXim(im);
670 8           i_push_error(0, "Image position outside of image");
671 8           return -1;
672             }
673             }
674              
675              
676             /*
677             =back
678              
679             =head1 AUTHOR
680              
681             Tony Cook
682              
683             =head1 SEE ALSO
684              
685             Imager(3)
686              
687             =cut
688             */