File Coverage

img16.c
Criterion Covered Total %
statement 298 362 82.3
branch 279 352 79.2
condition n/a
subroutine n/a
pod n/a
total 577 714 80.8


line stmt bran cond sub pod time code
1             /*
2             =head1 NAME
3              
4             img16.c - implements 16-bit images
5              
6             =head1 SYNOPSIS
7              
8             i_img *im = i_img_16_new(i_img_dim x, i_img_dim y, int channels);
9             # use like a normal image
10              
11             =head1 DESCRIPTION
12              
13             Implements 16-bit/sample images.
14              
15             This basic implementation is required so that we have some larger
16             sample image type to work with.
17              
18             =over
19              
20             =cut
21             */
22              
23             #define IMAGER_NO_CONTEXT
24              
25             #include "imager.h"
26             #include "imageri.h"
27              
28             static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val);
29             static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val);
30             static i_img_dim i_glin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
31             static i_img_dim i_plin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
32             static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val);
33             static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val);
34             static i_img_dim i_glinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
35             static i_img_dim i_plinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
36             static i_img_dim i_gsamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
37             int const *chans, int chan_count);
38             static i_img_dim i_gsampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
39             int const *chans, int chan_count);
40             static i_img_dim i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
41             int const *chans, int chan_count, int bits);
42             static i_img_dim i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
43             int const *chans, int chan_count, int bits);
44             static i_img_dim i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_sample_t *samps, const int *chans, int chan_count);
45             static i_img_dim i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fsample_t *samps, const int *chans, int chan_count);
46              
47             /*
48             =item IIM_base_16bit_direct
49              
50             Base structure used to initialize a 16-bit/sample image.
51              
52             Internal.
53              
54             =cut
55             */
56             static i_img IIM_base_16bit_direct =
57             {
58             0, /* channels set */
59             0, 0, 0, /* xsize, ysize, bytes */
60             ~0U, /* ch_mask */
61             i_16_bits, /* bits */
62             i_direct_type, /* type */
63             0, /* virtual */
64             NULL, /* idata */
65             { 0, 0, NULL }, /* tags */
66             NULL, /* ext_data */
67              
68             i_ppix_d16, /* i_f_ppix */
69             i_ppixf_d16, /* i_f_ppixf */
70             i_plin_d16, /* i_f_plin */
71             i_plinf_d16, /* i_f_plinf */
72             i_gpix_d16, /* i_f_gpix */
73             i_gpixf_d16, /* i_f_gpixf */
74             i_glin_d16, /* i_f_glin */
75             i_glinf_d16, /* i_f_glinf */
76             i_gsamp_d16, /* i_f_gsamp */
77             i_gsampf_d16, /* i_f_gsampf */
78              
79             NULL, /* i_f_gpal */
80             NULL, /* i_f_ppal */
81             NULL, /* i_f_addcolors */
82             NULL, /* i_f_getcolors */
83             NULL, /* i_f_colorcount */
84             NULL, /* i_f_maxcolors */
85             NULL, /* i_f_findcolor */
86             NULL, /* i_f_setcolors */
87              
88             NULL, /* i_f_destroy */
89              
90             i_gsamp_bits_d16,
91             i_psamp_bits_d16,
92              
93             i_psamp_d16,
94             i_psampf_d16
95             };
96              
97             /* it's possible some platforms won't have a 16-bit integer type,
98             so we check for one otherwise we work by bytes directly
99              
100             We do assume 8-bit char
101              
102             "Compaq C V6.4-009 on Compaq Tru64 UNIX V5.1A (Rev. 1885)" says it
103             supports C99, but doesn't supply stdint.h, which is required for
104             both hosted and freestanding implementations. So guard against it.
105             */
106             #if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
107             /* C99 should define something useful */
108             #include
109             #ifdef UINT16_MAX
110             typedef uint16_t i_sample16_t;
111             #define GOT16
112             #endif
113             #endif
114              
115             /* check out unsigned short */
116             #ifndef GOT16
117             #include
118             #if USHRT_MAX == 65535
119             typedef unsigned short i_sample16_t;
120             #define GOT16
121             #endif
122             #endif
123              
124             #ifdef GOT16
125              
126             /* we have a real 16-bit unsigned integer */
127             #define STORE16(bytes, offset, word) \
128             (((i_sample16_t *)(bytes))[offset] = (word))
129             #define STORE8as16(bytes, offset, byte) \
130             (((i_sample16_t *)(bytes))[offset] = (byte) * 256 + (byte))
131             #define GET16(bytes, offset) \
132             (((i_sample16_t *)(bytes))[offset])
133             #else
134              
135             /* we have to do this the hard way */
136             #define STORE16(bytes, offset, word) \
137             ((((unsigned char *)(bytes))[(offset)*2] = (word) >> 8), \
138             (((unsigned char *)(bytes))[(offset)*2+1] = (word) & 0xFF))
139             #define STORE8as16(bytes, offset, byte) \
140             ((((unsigned char *)(bytes))[(offset)*2] = (byte)), \
141             (((unsigned char *)(bytes))[(offset)*2+1] = (byte)))
142            
143             #define GET16(bytes, offset) \
144             (((unsigned char *)(bytes))[(offset)*2] * 256 \
145             + ((unsigned char *)(bytes))[(offset)*2+1])
146              
147             #endif
148              
149             #define GET16as8(bytes, offset) \
150             ((((i_sample16_t *)(bytes))[offset]+127) / 257)
151              
152             /*
153             =item im_img_16_new(ctx, x, y, ch)
154             XX
155             =category Image creation/destruction
156             =synopsis i_img *img = im_img_16_new(aIMCTX, width, height, channels);
157             =synopsis i_img *img = i_img_16_new(width, height, channels);
158              
159             Create a new 16-bit/sample image.
160              
161             Returns the image on success, or NULL on failure.
162              
163             Also callable as C
164              
165             =cut
166             */
167              
168             i_img *
169 93           im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
170             i_img *im;
171             size_t bytes, line_bytes;
172              
173 93           im_log((aIMCTX, 1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
174             i_DFc(x), i_DFc(y), ch));
175              
176 93 100         if (x < 1 || y < 1) {
    100          
177 5           im_push_error(aIMCTX, 0, "Image sizes must be positive");
178 5           return NULL;
179             }
180 88 100         if (ch < 1 || ch > MAXCHANNELS) {
    100          
181 2           im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
182 2           return NULL;
183             }
184 86           bytes = x * y * ch * 2;
185 86 50         if (bytes / y / ch / 2 != x) {
186 0           im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
187 0           return NULL;
188             }
189            
190             /* basic assumption: we can always allocate a buffer representing a
191             line from the image, otherwise we're going to have trouble
192             working with the image */
193 86           line_bytes = sizeof(i_fcolor) * x;
194 86 50         if (line_bytes / x != sizeof(i_fcolor)) {
195 0           im_push_error(aIMCTX, 0, "integer overflow calculating scanline allocation");
196 0           return NULL;
197             }
198              
199 86           im = im_img_alloc(aIMCTX);
200 86           *im = IIM_base_16bit_direct;
201 86           i_tags_new(&im->tags);
202 86           im->xsize = x;
203 86           im->ysize = y;
204 86           im->channels = ch;
205 86           im->bytes = bytes;
206 86           im->ext_data = NULL;
207 86           im->idata = mymalloc(im->bytes);
208 86           memset(im->idata, 0, im->bytes);
209              
210 86           im_img_init(aIMCTX, im);
211              
212 86           return im;
213             }
214              
215             /*
216             =item i_img_to_rgb16(im)
217              
218             =category Image creation
219              
220             Returns a 16-bit/sample version of the supplied image.
221              
222             Returns the image on success, or NULL on failure.
223              
224             =cut
225             */
226              
227             i_img *
228 7           i_img_to_rgb16(i_img *im) {
229             i_img *targ;
230             i_fcolor *line;
231             i_img_dim y;
232 7           dIMCTXim(im);
233              
234 7           targ = im_img_16_new(aIMCTX, im->xsize, im->ysize, im->channels);
235 7 50         if (!targ)
236 0           return NULL;
237 7           line = mymalloc(sizeof(i_fcolor) * im->xsize);
238 885 100         for (y = 0; y < im->ysize; ++y) {
239 878           i_glinf(im, 0, im->xsize, y, line);
240 878           i_plinf(targ, 0, im->xsize, y, line);
241             }
242              
243 7           myfree(line);
244              
245 7           return targ;
246             }
247              
248 52147           static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
249             i_img_dim off;
250             int ch;
251              
252 52147 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
253 5           return -1;
254              
255 52142           off = (x + y * im->xsize) * im->channels;
256 52142 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
257 190870 100         for (ch = 0; ch < im->channels; ++ch)
258 138729           STORE8as16(im->idata, off+ch, val->channel[ch]);
259             }
260             else {
261 4 100         for (ch = 0; ch < im->channels; ++ch)
262 3 100         if (im->ch_mask & (1 << ch))
263 2           STORE8as16(im->idata, off+ch, val->channel[ch]);
264             }
265              
266 52142           return 0;
267             }
268              
269 451636           static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
270             i_img_dim off;
271             int ch;
272              
273 451636 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
274 8           return -1;
275              
276 451628           off = (x + y * im->xsize) * im->channels;
277 1806513 100         for (ch = 0; ch < im->channels; ++ch)
278 1354885           val->channel[ch] = GET16as8(im->idata, off+ch);
279              
280 451628           return 0;
281             }
282              
283 630007           static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
284             i_img_dim off;
285             int ch;
286              
287 630007 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
288 4           return -1;
289              
290 630003           off = (x + y * im->xsize) * im->channels;
291 630003 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
292 2250008 100         for (ch = 0; ch < im->channels; ++ch)
293 1620006           STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
294             }
295             else {
296 4 100         for (ch = 0; ch < im->channels; ++ch)
297 3 100         if (im->ch_mask & (1 << ch))
298 2           STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
299             }
300              
301 630003           return 0;
302             }
303              
304 5391923           static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
305             i_img_dim off;
306             int ch;
307              
308 5391923 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
309 146260           return -1;
310              
311 5245663           off = (x + y * im->xsize) * im->channels;
312 19632650 100         for (ch = 0; ch < im->channels; ++ch)
313 14386987           val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
314              
315 5245663           return 0;
316             }
317              
318 0           static i_img_dim i_glin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) {
319             int ch;
320             i_img_dim count, i;
321             i_img_dim off;
322 0 0         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    0          
    0          
    0          
323 0 0         if (r > im->xsize)
324 0           r = im->xsize;
325 0           off = (l+y*im->xsize) * im->channels;
326 0           count = r - l;
327 0 0         for (i = 0; i < count; ++i) {
328 0 0         for (ch = 0; ch < im->channels; ++ch) {
329 0           vals[i].channel[ch] = GET16as8(im->idata, off);
330 0           ++off;
331             }
332             }
333 0           return count;
334             }
335             else {
336 0           return 0;
337             }
338             }
339              
340 2046           static i_img_dim i_plin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) {
341             int ch;
342             i_img_dim count, i;
343             i_img_dim off;
344 2046 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
345 2046 50         if (r > im->xsize)
346 0           r = im->xsize;
347 2046           off = (l+y*im->xsize) * im->channels;
348 2046           count = r - l;
349 2046 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
350 125458 100         for (i = 0; i < count; ++i) {
351 419912 100         for (ch = 0; ch < im->channels; ++ch) {
352 296499           STORE8as16(im->idata, off, vals[i].channel[ch]);
353 296499           ++off;
354             }
355             }
356             }
357             else {
358 2 100         for (i = 0; i < count; ++i) {
359 4 100         for (ch = 0; ch < im->channels; ++ch) {
360 3 100         if (im->ch_mask & (1 << ch))
361 2           STORE8as16(im->idata, off, vals[i].channel[ch]);
362 3           ++off;
363             }
364             }
365             }
366 2046           return count;
367             }
368             else {
369 0           return 0;
370             }
371             }
372              
373 2024           static i_img_dim i_glinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) {
374             int ch;
375             i_img_dim count, i;
376             i_img_dim off;
377 2024 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
378 2024 50         if (r > im->xsize)
379 0           r = im->xsize;
380 2024           off = (l+y*im->xsize) * im->channels;
381 2024           count = r - l;
382 285660 100         for (i = 0; i < count; ++i) {
383 1092093 100         for (ch = 0; ch < im->channels; ++ch) {
384 808457           vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
385 808457           ++off;
386             }
387             }
388 2024           return count;
389             }
390             else {
391 0           return 0;
392             }
393             }
394              
395 4458           static i_img_dim i_plinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) {
396             int ch;
397             i_img_dim count, i;
398             i_img_dim off;
399 4458 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    50          
    50          
400 4457 50         if (r > im->xsize)
401 0           r = im->xsize;
402 4457           off = (l+y*im->xsize) * im->channels;
403 4457           count = r - l;
404 4457 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
405 584508 100         for (i = 0; i < count; ++i) {
406 2234829 100         for (ch = 0; ch < im->channels; ++ch) {
407 1654207           STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
408 1654207           ++off;
409             }
410             }
411             }
412             else {
413 70472 100         for (i = 0; i < count; ++i) {
414 279604 100         for (ch = 0; ch < im->channels; ++ch) {
415 209703 100         if (im->ch_mask & (1 << ch))
416 69902           STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
417 209703           ++off;
418             }
419             }
420             }
421 4457           return count;
422             }
423             else {
424 1           return 0;
425             }
426             }
427              
428 1652           static i_img_dim i_gsamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
429             int const *chans, int chan_count) {
430             int ch;
431             i_img_dim count, i, w;
432             i_img_dim off;
433              
434 1652 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
435 1652 50         if (r > im->xsize)
436 0           r = im->xsize;
437 1652           off = (l+y*im->xsize) * im->channels;
438 1652           w = r - l;
439 1652           count = 0;
440              
441 1652 100         if (chans) {
442             /* make sure we have good channel numbers */
443 8 100         for (ch = 0; ch < chan_count; ++ch) {
444 6 50         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    50          
445 0           dIMCTXim(im);
446 0           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
447 0           return 0;
448             }
449             }
450 22 100         for (i = 0; i < w; ++i) {
451 80 100         for (ch = 0; ch < chan_count; ++ch) {
452 60           *samps++ = GET16as8(im->idata, off+chans[ch]);
453 60           ++count;
454             }
455 20           off += im->channels;
456             }
457             }
458             else {
459 1650 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
460 0           dIMCTXim(im);
461 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
462             chan_count);
463 0           return 0;
464             }
465 294150 100         for (i = 0; i < w; ++i) {
466 1035000 100         for (ch = 0; ch < chan_count; ++ch) {
467 742500           *samps++ = GET16as8(im->idata, off+ch);
468 742500           ++count;
469             }
470 292500           off += im->channels;
471             }
472             }
473              
474 1652           return count;
475             }
476             else {
477 0           return 0;
478             }
479             }
480              
481 2494           static i_img_dim i_gsampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
482             int const *chans, int chan_count) {
483             int ch;
484             i_img_dim count, i, w;
485             i_img_dim off;
486              
487 2494 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
488 2494 50         if (r > im->xsize)
489 0           r = im->xsize;
490 2494           off = (l+y*im->xsize) * im->channels;
491 2494           w = r - l;
492 2494           count = 0;
493              
494 2494 100         if (chans) {
495             /* make sure we have good channel numbers */
496 3904 100         for (ch = 0; ch < chan_count; ++ch) {
497 1952 50         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    50          
498 0           dIMCTXim(im);
499 0           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
500 0           return 0;
501             }
502             }
503 429752 100         for (i = 0; i < w; ++i) {
504 855600 100         for (ch = 0; ch < chan_count; ++ch) {
505 427800           *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
506 427800           ++count;
507             }
508 427800           off += im->channels;
509             }
510             }
511             else {
512 542 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
513 0           dIMCTXim(im);
514 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
515             chan_count);
516 0           return 0;
517             }
518 73564 100         for (i = 0; i < w; ++i) {
519 292600 100         for (ch = 0; ch < chan_count; ++ch) {
520 219578           *samps++ = Sample16ToF(GET16(im->idata, off+ch));
521 219578           ++count;
522             }
523 73022           off += im->channels;
524             }
525             }
526              
527 2494           return count;
528             }
529             else {
530 0           return 0;
531             }
532             }
533              
534             static i_img_dim
535 6           i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
536             int const *chans, int chan_count, int bits) {
537             int ch;
538             i_img_dim count, i, w;
539             i_img_dim off;
540              
541 6 100         if (bits != 16) {
542 1           return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits);
543             }
544              
545 5 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
546 5 50         if (r > im->xsize)
547 0           r = im->xsize;
548 5           off = (l+y*im->xsize) * im->channels;
549 5           w = r - l;
550 5           count = 0;
551              
552 5 100         if (chans) {
553             /* make sure we have good channel numbers */
554 13 100         for (ch = 0; ch < chan_count; ++ch) {
555 10 50         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    100          
556 1           dIMCTXim(im);
557 1           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
558 1           return -1;
559             }
560             }
561 15 100         for (i = 0; i < w; ++i) {
562 44 100         for (ch = 0; ch < chan_count; ++ch) {
563 32           *samps++ = GET16(im->idata, off+chans[ch]);
564 32           ++count;
565             }
566 12           off += im->channels;
567             }
568             }
569             else {
570 1 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
571 0           dIMCTXim(im);
572 0           i_push_error(0, "Invalid channel count");
573 0           return -1;
574             }
575 11 100         for (i = 0; i < w; ++i) {
576 40 100         for (ch = 0; ch < chan_count; ++ch) {
577 30           *samps++ = GET16(im->idata, off+ch);
578 30           ++count;
579             }
580 10           off += im->channels;
581             }
582             }
583              
584 4           return count;
585             }
586             else {
587 0           dIMCTXim(im);
588 0           i_push_error(0, "Image position outside of image");
589 0           return -1;
590             }
591             }
592              
593             static i_img_dim
594 2           i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
595             int const *chans, int chan_count, int bits) {
596             int ch;
597             i_img_dim count, i, w;
598             i_img_dim off;
599              
600 2 50         if (bits != 16) {
601 0           dIMCTXim(im);
602 0           i_push_error(0, "Invalid bits for 16-bit image");
603 0           return -1;
604             }
605              
606 2 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
607 2 50         if (r > im->xsize)
608 0           r = im->xsize;
609 2           off = (l+y*im->xsize) * im->channels;
610 2           w = r - l;
611 2           count = 0;
612              
613 2 100         if (chans) {
614             /* make sure we have good channel numbers */
615 4 100         for (ch = 0; ch < chan_count; ++ch) {
616 3 50         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    50          
617 0           dIMCTXim(im);
618 0           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
619 0           return -1;
620             }
621             }
622 5 100         for (i = 0; i < w; ++i) {
623 16 100         for (ch = 0; ch < chan_count; ++ch) {
624 12 50         if (im->ch_mask & (1 << ch))
625 12           STORE16(im->idata, off+chans[ch], *samps);
626 12           ++samps;
627 12           ++count;
628             }
629 4           off += im->channels;
630             }
631             }
632             else {
633 1 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
634 0           dIMCTXim(im);
635 0           i_push_error(0, "Invalid channel count");
636 0           return -1;
637             }
638 11 100         for (i = 0; i < w; ++i) {
639 40 100         for (ch = 0; ch < chan_count; ++ch) {
640 30 50         if (im->ch_mask & (1 << ch))
641 30           STORE16(im->idata, off+ch, *samps);
642 30           ++samps;
643 30           ++count;
644             }
645 10           off += im->channels;
646             }
647             }
648              
649 2           return count;
650             }
651             else {
652 0           dIMCTXim(im);
653 0           i_push_error(0, "Image position outside of image");
654 0           return -1;
655             }
656             }
657              
658             /*
659             =item i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_sample_t *samps, int *chans, int chan_count)
660              
661             Writes sample values to im for the horizontal line (l, y) to (r-1,y)
662             for the channels specified by chans, an array of int with chan_count
663             elements.
664              
665             Returns the number of samples written (which should be (r-l) *
666             bits_set(chan_mask)
667              
668             =cut
669             */
670              
671             static
672             i_img_dim
673 12           i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
674             const i_sample_t *samps, const int *chans, int chan_count) {
675             int ch;
676             i_img_dim count, i, w;
677              
678 12 100         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
679             i_img_dim offset;
680 8 100         if (r > im->xsize)
681 1           r = im->xsize;
682 8           offset = (l+y*im->xsize) * im->channels;
683 8           w = r - l;
684 8           count = 0;
685              
686 8 100         if (chans) {
687             /* make sure we have good channel numbers */
688             /* and test if all channels specified are in the mask */
689 6           int all_in_mask = 1;
690 21 100         for (ch = 0; ch < chan_count; ++ch) {
691 17 100         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    100          
692 2           dIMCTXim(im);
693 2           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
694 2           return -1;
695             }
696 15 100         if (!((1 << chans[ch]) & im->ch_mask))
697 1           all_in_mask = 0;
698             }
699 4 100         if (all_in_mask) {
700 17 100         for (i = 0; i < w; ++i) {
701 54 100         for (ch = 0; ch < chan_count; ++ch) {
702 40           STORE8as16(im->idata, offset + chans[ch], *samps);
703 40           ++samps;
704 40           ++count;
705             }
706 14           offset += im->channels;
707             }
708             }
709             else {
710 5 100         for (i = 0; i < w; ++i) {
711 4 100         for (ch = 0; ch < chan_count; ++ch) {
712 3 100         if (im->ch_mask & (1 << (chans[ch])))
713 2           STORE8as16(im->idata, offset + chans[ch], *samps);
714 3           ++samps;
715 3           ++count;
716             }
717 1           offset += im->channels;
718             }
719             }
720             }
721             else {
722 2 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
723 0           dIMCTXim(im);
724 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
725             chan_count);
726 0           return -1;
727             }
728 4 100         for (i = 0; i < w; ++i) {
729 2           unsigned mask = 1;
730 8 100         for (ch = 0; ch < chan_count; ++ch) {
731 6 100         if (im->ch_mask & mask)
732 5           STORE8as16(im->idata, offset + ch, *samps);
733 6           ++samps;
734 6           ++count;
735 6           mask <<= 1;
736             }
737 2           offset += im->channels;
738             }
739             }
740              
741 6           return count;
742             }
743             else {
744 4           dIMCTXim(im);
745 4           i_push_error(0, "Image position outside of image");
746 4           return -1;
747             }
748             }
749              
750             /*
751             =item i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fsample_t *samps, int *chans, int chan_count)
752              
753             Writes sample values to im for the horizontal line (l, y) to (r-1,y)
754             for the channels specified by chans, an array of int with chan_count
755             elements.
756              
757             Returns the number of samples written (which should be (r-l) *
758             bits_set(chan_mask)
759              
760             =cut
761             */
762              
763             static
764             i_img_dim
765 12           i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
766             const i_fsample_t *samps, const int *chans, int chan_count) {
767             int ch;
768             i_img_dim count, i, w;
769              
770 12 100         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
771             i_img_dim offset;
772 8 100         if (r > im->xsize)
773 1           r = im->xsize;
774 8           offset = (l+y*im->xsize) * im->channels;
775 8           w = r - l;
776 8           count = 0;
777              
778 8 100         if (chans) {
779             /* make sure we have good channel numbers */
780             /* and test if all channels specified are in the mask */
781 6           int all_in_mask = 1;
782 21 100         for (ch = 0; ch < chan_count; ++ch) {
783 17 100         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    100          
784 2           dIMCTXim(im);
785 2           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
786 2           return -1;
787             }
788 15 100         if (!((1 << chans[ch]) & im->ch_mask))
789 1           all_in_mask = 0;
790             }
791 4 100         if (all_in_mask) {
792 17 100         for (i = 0; i < w; ++i) {
793 54 100         for (ch = 0; ch < chan_count; ++ch) {
794 40           unsigned samp16 = SampleFTo16(*samps);
795 40           STORE16(im->idata, offset + chans[ch], samp16);
796 40           ++samps;
797 40           ++count;
798             }
799 14           offset += im->channels;
800             }
801             }
802             else {
803 5 100         for (i = 0; i < w; ++i) {
804 4 100         for (ch = 0; ch < chan_count; ++ch) {
805 3 100         if (im->ch_mask & (1 << (chans[ch]))) {
806 2           unsigned samp16 = SampleFTo16(*samps);
807 2           STORE16(im->idata, offset + chans[ch], samp16);
808             }
809 3           ++samps;
810 3           ++count;
811             }
812 1           offset += im->channels;
813             }
814             }
815             }
816             else {
817 2 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
818 0           dIMCTXim(im);
819 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
820             chan_count);
821 0           return -1;
822             }
823 4 100         for (i = 0; i < w; ++i) {
824 2           unsigned mask = 1;
825 8 100         for (ch = 0; ch < chan_count; ++ch) {
826 6 100         if (im->ch_mask & mask) {
827 5           unsigned samp16 = SampleFTo16(*samps);
828 5           STORE16(im->idata, offset + ch, samp16);
829             }
830 6           ++samps;
831 6           ++count;
832 6           mask <<= 1;
833             }
834 2           offset += im->channels;
835             }
836             }
837              
838 6           return count;
839             }
840             else {
841 4           dIMCTXim(im);
842 4           i_push_error(0, "Image position outside of image");
843 4           return -1;
844             }
845             }
846              
847             /*
848             =back
849              
850             =head1 AUTHOR
851              
852             Tony Cook
853              
854             =head1 SEE ALSO
855              
856             Imager(3)
857              
858             =cut
859             */