avoid an unneeded check in the FT1 has_chars() method implementation
[imager.git] / img16.c
CommitLineData
faa9b3e7
TC
1/*
2=head1 NAME
3
4img16.c - implements 16-bit images
5
6=head1 SYNOPSIS
7
8d14daab 8 i_img *im = i_img_16_new(i_img_dim x, i_img_dim y, int channels);
faa9b3e7
TC
9 # use like a normal image
10
11=head1 DESCRIPTION
12
13Implements 16-bit/sample images.
14
15This basic implementation is required so that we have some larger
16sample image type to work with.
17
18=over
19
20=cut
21*/
22
696cb85d
TC
23#define IMAGER_NO_CONTEXT
24
92bda632
TC
25#include "imager.h"
26#include "imageri.h"
faa9b3e7 27
8d14daab
TC
28static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val);
29static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val);
30static i_img_dim i_glin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
31static 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);
32static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val);
33static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val);
34static i_img_dim i_glinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
35static 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);
36static 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,
18accb2a 37 int const *chans, int chan_count);
8d14daab 38static 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,
18accb2a 39 int const *chans, int chan_count);
8d14daab 40static i_img_dim i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
bd8052a6 41 int const *chans, int chan_count, int bits);
8d14daab 42static 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,
bd8052a6 43 int const *chans, int chan_count, int bits);
836d9f54
TC
44static 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);
45static 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);
faa9b3e7
TC
46
47/*
48=item IIM_base_16bit_direct
49
50Base structure used to initialize a 16-bit/sample image.
51
52Internal.
53
54=cut
55*/
56static i_img IIM_base_16bit_direct =
57{
58 0, /* channels set */
59 0, 0, 0, /* xsize, ysize, bytes */
9a88a5e6 60 ~0U, /* ch_mask */
faa9b3e7
TC
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 */
bd8052a6
TC
81 NULL, /* i_f_addcolors */
82 NULL, /* i_f_getcolors */
faa9b3e7 83 NULL, /* i_f_colorcount */
bd8052a6 84 NULL, /* i_f_maxcolors */
faa9b3e7 85 NULL, /* i_f_findcolor */
bd8052a6 86 NULL, /* i_f_setcolors */
faa9b3e7
TC
87
88 NULL, /* i_f_destroy */
bd8052a6
TC
89
90 i_gsamp_bits_d16,
91 i_psamp_bits_d16,
836d9f54
TC
92
93 i_psamp_d16,
94 i_psampf_d16
faa9b3e7
TC
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
26fd367b
TC
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.
faa9b3e7 105*/
26fd367b 106#if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
faa9b3e7
TC
107/* C99 should define something useful */
108#include <stdint.h>
109#ifdef UINT16_MAX
110typedef uint16_t i_sample16_t;
111#define GOT16
112#endif
113#endif
114
115/* check out unsigned short */
116#ifndef GOT16
117#include <limits.h>
118#if USHRT_MAX == 65535
119typedef 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) \
bd8052a6 130 (((i_sample16_t *)(bytes))[offset] = (byte) * 256 + (byte))
faa9b3e7
TC
131#define GET16(bytes, offset) \
132 (((i_sample16_t *)(bytes))[offset])
faa9b3e7
TC
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)), \
bd8052a6 141 (((unsigned char *)(bytes))[(offset)*2+1] = (byte)))
faa9b3e7
TC
142
143#define GET16(bytes, offset) \
144 (((unsigned char *)(bytes))[(offset)*2] * 256 \
145 + ((unsigned char *)(bytes))[(offset)*2+1])
faa9b3e7
TC
146
147#endif
148
bd8052a6
TC
149#define GET16as8(bytes, offset) \
150 ((((i_sample16_t *)(bytes))[offset]+127) / 257)
151
faa9b3e7 152/*
abffffed
TC
153=item im_img_16_new(ctx, x, y, ch)
154X<im_img_16_new API>X<i_img_16_new API>
6cfee9d1 155=category Image creation/destruction
abffffed 156=synopsis i_img *img = im_img_16_new(aIMCTX, width, height, channels);
bd8052a6
TC
157=synopsis i_img *img = i_img_16_new(width, height, channels);
158
159Create a new 16-bit/sample image.
160
161Returns the image on success, or NULL on failure.
365ea842 162
abffffed
TC
163Also callable as C<i_img_16_new(x, y, ch)>
164
365ea842 165=cut
faa9b3e7 166*/
bd8052a6 167
696cb85d
TC
168i_img *
169im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
bd8052a6 170 i_img *im;
8d14daab 171 size_t bytes, line_bytes;
bd8052a6 172
b7a0ad88 173 im_log((aIMCTX, 1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
8d14daab 174 i_DFc(x), i_DFc(y), ch));
1501d9b3
TC
175
176 if (x < 1 || y < 1) {
696cb85d 177 im_push_error(aIMCTX, 0, "Image sizes must be positive");
1501d9b3
TC
178 return NULL;
179 }
180 if (ch < 1 || ch > MAXCHANNELS) {
696cb85d 181 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
1501d9b3
TC
182 return NULL;
183 }
653ea321
TC
184 bytes = x * y * ch * 2;
185 if (bytes / y / ch / 2 != x) {
696cb85d 186 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
653ea321
TC
187 return NULL;
188 }
faa9b3e7 189
f0960b14
TC
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 line_bytes = sizeof(i_fcolor) * x;
194 if (line_bytes / x != sizeof(i_fcolor)) {
696cb85d 195 im_push_error(aIMCTX, 0, "integer overflow calculating scanline allocation");
f0960b14
TC
196 return NULL;
197 }
198
696cb85d 199 im = im_img_alloc(aIMCTX);
faa9b3e7
TC
200 *im = IIM_base_16bit_direct;
201 i_tags_new(&im->tags);
202 im->xsize = x;
203 im->ysize = y;
204 im->channels = ch;
653ea321 205 im->bytes = bytes;
faa9b3e7
TC
206 im->ext_data = NULL;
207 im->idata = mymalloc(im->bytes);
bd8052a6 208 memset(im->idata, 0, im->bytes);
92bda632 209
696cb85d 210 im_img_init(aIMCTX, im);
faa9b3e7 211
faa9b3e7
TC
212 return im;
213}
214
167660cd
TC
215/*
216=item i_img_to_rgb16(im)
217
218=category Image creation
219
220Returns a 16-bit/sample version of the supplied image.
221
222Returns the image on success, or NULL on failure.
223
224=cut
225*/
226
227i_img *
228i_img_to_rgb16(i_img *im) {
229 i_img *targ;
230 i_fcolor *line;
8d14daab 231 i_img_dim y;
696cb85d 232 dIMCTXim(im);
167660cd 233
696cb85d 234 targ = im_img_16_new(aIMCTX, im->xsize, im->ysize, im->channels);
167660cd
TC
235 if (!targ)
236 return NULL;
237 line = mymalloc(sizeof(i_fcolor) * im->xsize);
238 for (y = 0; y < im->ysize; ++y) {
239 i_glinf(im, 0, im->xsize, y, line);
240 i_plinf(targ, 0, im->xsize, y, line);
241 }
242
243 myfree(line);
244
245 return targ;
246}
247
8d14daab
TC
248static 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;
faa9b3e7 251
837a4b43 252 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
253 return -1;
254
255 off = (x + y * im->xsize) * im->channels;
9b8ce4f4
TC
256 if (I_ALL_CHANNELS_WRITABLE(im)) {
257 for (ch = 0; ch < im->channels; ++ch)
258 STORE8as16(im->idata, off+ch, val->channel[ch]);
259 }
260 else {
261 for (ch = 0; ch < im->channels; ++ch)
262 if (im->ch_mask & (1 << ch))
263 STORE8as16(im->idata, off+ch, val->channel[ch]);
264 }
faa9b3e7
TC
265
266 return 0;
267}
268
8d14daab
TC
269static 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;
faa9b3e7 272
837a4b43 273 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
274 return -1;
275
276 off = (x + y * im->xsize) * im->channels;
277 for (ch = 0; ch < im->channels; ++ch)
278 val->channel[ch] = GET16as8(im->idata, off+ch);
279
280 return 0;
281}
282
8d14daab
TC
283static 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;
faa9b3e7 286
837a4b43 287 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
288 return -1;
289
290 off = (x + y * im->xsize) * im->channels;
9b8ce4f4
TC
291 if (I_ALL_CHANNELS_WRITABLE(im)) {
292 for (ch = 0; ch < im->channels; ++ch)
293 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
294 }
295 else {
296 for (ch = 0; ch < im->channels; ++ch)
297 if (im->ch_mask & (1 << ch))
298 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
299 }
faa9b3e7
TC
300
301 return 0;
302}
303
8d14daab
TC
304static 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;
faa9b3e7 307
837a4b43 308 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
309 return -1;
310
311 off = (x + y * im->xsize) * im->channels;
312 for (ch = 0; ch < im->channels; ++ch)
313 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
314
315 return 0;
316}
317
8d14daab
TC
318static 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;
faa9b3e7
TC
322 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
323 if (r > im->xsize)
324 r = im->xsize;
325 off = (l+y*im->xsize) * im->channels;
326 count = r - l;
327 for (i = 0; i < count; ++i) {
328 for (ch = 0; ch < im->channels; ++ch) {
329 vals[i].channel[ch] = GET16as8(im->idata, off);
330 ++off;
331 }
332 }
333 return count;
334 }
335 else {
336 return 0;
337 }
338}
339
8d14daab
TC
340static 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;
faa9b3e7
TC
344 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
345 if (r > im->xsize)
346 r = im->xsize;
347 off = (l+y*im->xsize) * im->channels;
348 count = r - l;
9b8ce4f4
TC
349 if (I_ALL_CHANNELS_WRITABLE(im)) {
350 for (i = 0; i < count; ++i) {
351 for (ch = 0; ch < im->channels; ++ch) {
352 STORE8as16(im->idata, off, vals[i].channel[ch]);
353 ++off;
354 }
355 }
356 }
357 else {
358 for (i = 0; i < count; ++i) {
359 for (ch = 0; ch < im->channels; ++ch) {
360 if (im->ch_mask & (1 << ch))
361 STORE8as16(im->idata, off, vals[i].channel[ch]);
362 ++off;
363 }
faa9b3e7
TC
364 }
365 }
366 return count;
367 }
368 else {
369 return 0;
370 }
371}
372
8d14daab
TC
373static 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;
faa9b3e7
TC
377 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
378 if (r > im->xsize)
379 r = im->xsize;
380 off = (l+y*im->xsize) * im->channels;
381 count = r - l;
382 for (i = 0; i < count; ++i) {
383 for (ch = 0; ch < im->channels; ++ch) {
384 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
385 ++off;
386 }
387 }
388 return count;
389 }
390 else {
391 return 0;
392 }
393}
394
8d14daab
TC
395static 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;
faa9b3e7
TC
399 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
400 if (r > im->xsize)
401 r = im->xsize;
402 off = (l+y*im->xsize) * im->channels;
403 count = r - l;
9b8ce4f4
TC
404 if (I_ALL_CHANNELS_WRITABLE(im)) {
405 for (i = 0; i < count; ++i) {
406 for (ch = 0; ch < im->channels; ++ch) {
407 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
408 ++off;
409 }
410 }
411 }
412 else {
413 for (i = 0; i < count; ++i) {
414 for (ch = 0; ch < im->channels; ++ch) {
415 if (im->ch_mask & (1 << ch))
416 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
417 ++off;
418 }
faa9b3e7
TC
419 }
420 }
421 return count;
422 }
423 else {
424 return 0;
425 }
426}
427
8d14daab 428static 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,
18accb2a 429 int const *chans, int chan_count) {
8d14daab
TC
430 int ch;
431 i_img_dim count, i, w;
432 i_img_dim off;
faa9b3e7
TC
433
434 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
435 if (r > im->xsize)
436 r = im->xsize;
437 off = (l+y*im->xsize) * im->channels;
438 w = r - l;
439 count = 0;
440
441 if (chans) {
442 /* make sure we have good channel numbers */
443 for (ch = 0; ch < chan_count; ++ch) {
444 if (chans[ch] < 0 || chans[ch] >= im->channels) {
b7a0ad88
TC
445 dIMCTXim(im);
446 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
faa9b3e7
TC
447 return 0;
448 }
449 }
450 for (i = 0; i < w; ++i) {
451 for (ch = 0; ch < chan_count; ++ch) {
452 *samps++ = GET16as8(im->idata, off+chans[ch]);
453 ++count;
454 }
455 off += im->channels;
456 }
457 }
458 else {
c7481ae1 459 if (chan_count <= 0 || chan_count > im->channels) {
b7a0ad88
TC
460 dIMCTXim(im);
461 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
c7481ae1
TC
462 chan_count);
463 return 0;
464 }
faa9b3e7
TC
465 for (i = 0; i < w; ++i) {
466 for (ch = 0; ch < chan_count; ++ch) {
467 *samps++ = GET16as8(im->idata, off+ch);
468 ++count;
469 }
470 off += im->channels;
471 }
472 }
473
474 return count;
475 }
476 else {
477 return 0;
478 }
479}
480
8d14daab 481static 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,
18accb2a 482 int const *chans, int chan_count) {
8d14daab
TC
483 int ch;
484 i_img_dim count, i, w;
485 i_img_dim off;
faa9b3e7
TC
486
487 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
488 if (r > im->xsize)
489 r = im->xsize;
490 off = (l+y*im->xsize) * im->channels;
491 w = r - l;
492 count = 0;
493
494 if (chans) {
495 /* make sure we have good channel numbers */
496 for (ch = 0; ch < chan_count; ++ch) {
497 if (chans[ch] < 0 || chans[ch] >= im->channels) {
b7a0ad88
TC
498 dIMCTXim(im);
499 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
faa9b3e7
TC
500 return 0;
501 }
502 }
503 for (i = 0; i < w; ++i) {
504 for (ch = 0; ch < chan_count; ++ch) {
505 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
506 ++count;
507 }
508 off += im->channels;
509 }
510 }
511 else {
c7481ae1 512 if (chan_count <= 0 || chan_count > im->channels) {
b7a0ad88
TC
513 dIMCTXim(im);
514 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
c7481ae1
TC
515 chan_count);
516 return 0;
517 }
faa9b3e7
TC
518 for (i = 0; i < w; ++i) {
519 for (ch = 0; ch < chan_count; ++ch) {
520 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
521 ++count;
522 }
523 off += im->channels;
524 }
525 }
526
527 return count;
528 }
529 else {
530 return 0;
531 }
532}
533
8d14daab
TC
534static i_img_dim
535i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
bd8052a6 536 int const *chans, int chan_count, int bits) {
8d14daab
TC
537 int ch;
538 i_img_dim count, i, w;
539 i_img_dim off;
bd8052a6
TC
540
541 if (bits != 16) {
542 return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits);
543 }
544
545 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
546 if (r > im->xsize)
547 r = im->xsize;
548 off = (l+y*im->xsize) * im->channels;
549 w = r - l;
550 count = 0;
551
552 if (chans) {
553 /* make sure we have good channel numbers */
554 for (ch = 0; ch < chan_count; ++ch) {
555 if (chans[ch] < 0 || chans[ch] >= im->channels) {
b7a0ad88
TC
556 dIMCTXim(im);
557 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
bd8052a6
TC
558 return -1;
559 }
560 }
561 for (i = 0; i < w; ++i) {
562 for (ch = 0; ch < chan_count; ++ch) {
563 *samps++ = GET16(im->idata, off+chans[ch]);
564 ++count;
565 }
566 off += im->channels;
567 }
568 }
569 else {
570 if (chan_count <= 0 || chan_count > im->channels) {
696cb85d 571 dIMCTXim(im);
bd8052a6
TC
572 i_push_error(0, "Invalid channel count");
573 return -1;
574 }
575 for (i = 0; i < w; ++i) {
576 for (ch = 0; ch < chan_count; ++ch) {
577 *samps++ = GET16(im->idata, off+ch);
578 ++count;
579 }
580 off += im->channels;
581 }
582 }
583
584 return count;
585 }
586 else {
696cb85d 587 dIMCTXim(im);
bd8052a6
TC
588 i_push_error(0, "Image position outside of image");
589 return -1;
590 }
591}
592
8d14daab
TC
593static i_img_dim
594i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
bd8052a6 595 int const *chans, int chan_count, int bits) {
8d14daab
TC
596 int ch;
597 i_img_dim count, i, w;
598 i_img_dim off;
bd8052a6
TC
599
600 if (bits != 16) {
696cb85d 601 dIMCTXim(im);
bd8052a6
TC
602 i_push_error(0, "Invalid bits for 16-bit image");
603 return -1;
604 }
605
606 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
607 if (r > im->xsize)
608 r = im->xsize;
609 off = (l+y*im->xsize) * im->channels;
610 w = r - l;
611 count = 0;
612
613 if (chans) {
614 /* make sure we have good channel numbers */
615 for (ch = 0; ch < chan_count; ++ch) {
616 if (chans[ch] < 0 || chans[ch] >= im->channels) {
b7a0ad88
TC
617 dIMCTXim(im);
618 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
bd8052a6
TC
619 return -1;
620 }
621 }
622 for (i = 0; i < w; ++i) {
623 for (ch = 0; ch < chan_count; ++ch) {
624 if (im->ch_mask & (1 << ch))
625 STORE16(im->idata, off+chans[ch], *samps);
626 ++samps;
627 ++count;
628 }
629 off += im->channels;
630 }
631 }
632 else {
633 if (chan_count <= 0 || chan_count > im->channels) {
696cb85d 634 dIMCTXim(im);
bd8052a6
TC
635 i_push_error(0, "Invalid channel count");
636 return -1;
637 }
638 for (i = 0; i < w; ++i) {
639 for (ch = 0; ch < chan_count; ++ch) {
640 if (im->ch_mask & (1 << ch))
641 STORE16(im->idata, off+ch, *samps);
642 ++samps;
643 ++count;
644 }
645 off += im->channels;
646 }
647 }
648
649 return count;
650 }
651 else {
696cb85d 652 dIMCTXim(im);
bd8052a6
TC
653 i_push_error(0, "Image position outside of image");
654 return -1;
655 }
656}
657
836d9f54
TC
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
661Writes sample values to im for the horizontal line (l, y) to (r-1,y)
662for the channels specified by chans, an array of int with chan_count
663elements.
664
665Returns the number of samples written (which should be (r-l) *
666bits_set(chan_mask)
667
668=cut
669*/
670
671static
672i_img_dim
673i_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 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
836d9f54
TC
679 i_img_dim offset;
680 if (r > im->xsize)
681 r = im->xsize;
682 offset = (l+y*im->xsize) * im->channels;
683 w = r - l;
684 count = 0;
685
686 if (chans) {
687 /* make sure we have good channel numbers */
688 /* and test if all channels specified are in the mask */
689 int all_in_mask = 1;
690 for (ch = 0; ch < chan_count; ++ch) {
691 if (chans[ch] < 0 || chans[ch] >= im->channels) {
b7a0ad88
TC
692 dIMCTXim(im);
693 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
836d9f54
TC
694 return -1;
695 }
696 if (!((1 << chans[ch]) & im->ch_mask))
697 all_in_mask = 0;
698 }
699 if (all_in_mask) {
700 for (i = 0; i < w; ++i) {
701 for (ch = 0; ch < chan_count; ++ch) {
702 STORE8as16(im->idata, offset + chans[ch], *samps);
703 ++samps;
704 ++count;
705 }
706 offset += im->channels;
707 }
708 }
709 else {
710 for (i = 0; i < w; ++i) {
711 for (ch = 0; ch < chan_count; ++ch) {
712 if (im->ch_mask & (1 << (chans[ch])))
713 STORE8as16(im->idata, offset + chans[ch], *samps);
714 ++samps;
715 ++count;
716 }
717 offset += im->channels;
718 }
719 }
720 }
721 else {
722 if (chan_count <= 0 || chan_count > im->channels) {
b7a0ad88
TC
723 dIMCTXim(im);
724 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
836d9f54
TC
725 chan_count);
726 return -1;
727 }
728 for (i = 0; i < w; ++i) {
729 unsigned mask = 1;
730 for (ch = 0; ch < chan_count; ++ch) {
731 if (im->ch_mask & mask)
732 STORE8as16(im->idata, offset + ch, *samps);
733 ++samps;
734 ++count;
735 mask <<= 1;
736 }
737 offset += im->channels;
738 }
739 }
740
741 return count;
742 }
743 else {
696cb85d 744 dIMCTXim(im);
836d9f54
TC
745 i_push_error(0, "Image position outside of image");
746 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
753Writes sample values to im for the horizontal line (l, y) to (r-1,y)
754for the channels specified by chans, an array of int with chan_count
755elements.
756
757Returns the number of samples written (which should be (r-l) *
758bits_set(chan_mask)
759
760=cut
761*/
762
763static
764i_img_dim
765i_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 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
836d9f54
TC
771 i_img_dim offset;
772 if (r > im->xsize)
773 r = im->xsize;
774 offset = (l+y*im->xsize) * im->channels;
775 w = r - l;
776 count = 0;
777
778 if (chans) {
779 /* make sure we have good channel numbers */
780 /* and test if all channels specified are in the mask */
781 int all_in_mask = 1;
782 for (ch = 0; ch < chan_count; ++ch) {
783 if (chans[ch] < 0 || chans[ch] >= im->channels) {
b7a0ad88
TC
784 dIMCTXim(im);
785 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
836d9f54
TC
786 return -1;
787 }
788 if (!((1 << chans[ch]) & im->ch_mask))
789 all_in_mask = 0;
790 }
791 if (all_in_mask) {
792 for (i = 0; i < w; ++i) {
793 for (ch = 0; ch < chan_count; ++ch) {
794 unsigned samp16 = SampleFTo16(*samps);
795 STORE16(im->idata, offset + chans[ch], samp16);
796 ++samps;
797 ++count;
798 }
799 offset += im->channels;
800 }
801 }
802 else {
803 for (i = 0; i < w; ++i) {
804 for (ch = 0; ch < chan_count; ++ch) {
805 if (im->ch_mask & (1 << (chans[ch]))) {
806 unsigned samp16 = SampleFTo16(*samps);
807 STORE16(im->idata, offset + chans[ch], samp16);
808 }
809 ++samps;
810 ++count;
811 }
812 offset += im->channels;
813 }
814 }
815 }
816 else {
817 if (chan_count <= 0 || chan_count > im->channels) {
b7a0ad88
TC
818 dIMCTXim(im);
819 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
836d9f54
TC
820 chan_count);
821 return -1;
822 }
823 for (i = 0; i < w; ++i) {
824 unsigned mask = 1;
825 for (ch = 0; ch < chan_count; ++ch) {
826 if (im->ch_mask & mask) {
827 unsigned samp16 = SampleFTo16(*samps);
828 STORE16(im->idata, offset + ch, samp16);
829 }
830 ++samps;
831 ++count;
832 mask <<= 1;
833 }
834 offset += im->channels;
835 }
836 }
837
838 return count;
839 }
840 else {
696cb85d 841 dIMCTXim(im);
836d9f54
TC
842 i_push_error(0, "Image position outside of image");
843 return -1;
844 }
845}
846
b8c2033e
AMH
847/*
848=back
849
850=head1 AUTHOR
851
852Tony Cook <tony@develop-help.com>
853
854=head1 SEE ALSO
855
856Imager(3)
857
858=cut
859*/