update img16.c to avoid mm_log()
[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
156699af
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/*
bd8052a6 153=item i_img_16_new(x, y, ch)
faa9b3e7 154
6cfee9d1 155=category Image creation/destruction
bd8052a6
TC
156=synopsis i_img *img = i_img_16_new(width, height, channels);
157
158Create a new 16-bit/sample image.
159
160Returns the image on success, or NULL on failure.
365ea842
TC
161
162=cut
faa9b3e7 163*/
bd8052a6 164
156699af
TC
165i_img *
166im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
bd8052a6 167 i_img *im;
8d14daab 168 size_t bytes, line_bytes;
bd8052a6 169
98174be7 170 im_log((aIMCTX, 1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
8d14daab 171 i_DFc(x), i_DFc(y), ch));
1501d9b3
TC
172
173 if (x < 1 || y < 1) {
156699af 174 im_push_error(aIMCTX, 0, "Image sizes must be positive");
1501d9b3
TC
175 return NULL;
176 }
177 if (ch < 1 || ch > MAXCHANNELS) {
156699af 178 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
1501d9b3
TC
179 return NULL;
180 }
653ea321
TC
181 bytes = x * y * ch * 2;
182 if (bytes / y / ch / 2 != x) {
156699af 183 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
653ea321
TC
184 return NULL;
185 }
faa9b3e7 186
f0960b14
TC
187 /* basic assumption: we can always allocate a buffer representing a
188 line from the image, otherwise we're going to have trouble
189 working with the image */
190 line_bytes = sizeof(i_fcolor) * x;
191 if (line_bytes / x != sizeof(i_fcolor)) {
156699af 192 im_push_error(aIMCTX, 0, "integer overflow calculating scanline allocation");
f0960b14
TC
193 return NULL;
194 }
195
156699af 196 im = im_img_alloc(aIMCTX);
faa9b3e7
TC
197 *im = IIM_base_16bit_direct;
198 i_tags_new(&im->tags);
199 im->xsize = x;
200 im->ysize = y;
201 im->channels = ch;
653ea321 202 im->bytes = bytes;
faa9b3e7
TC
203 im->ext_data = NULL;
204 im->idata = mymalloc(im->bytes);
bd8052a6 205 memset(im->idata, 0, im->bytes);
92bda632 206
156699af 207 im_img_init(aIMCTX, im);
faa9b3e7 208
faa9b3e7
TC
209 return im;
210}
211
167660cd
TC
212/*
213=item i_img_to_rgb16(im)
214
215=category Image creation
216
217Returns a 16-bit/sample version of the supplied image.
218
219Returns the image on success, or NULL on failure.
220
221=cut
222*/
223
224i_img *
225i_img_to_rgb16(i_img *im) {
226 i_img *targ;
227 i_fcolor *line;
8d14daab 228 i_img_dim y;
156699af 229 dIMCTXim(im);
167660cd 230
156699af 231 targ = im_img_16_new(aIMCTX, im->xsize, im->ysize, im->channels);
167660cd
TC
232 if (!targ)
233 return NULL;
234 line = mymalloc(sizeof(i_fcolor) * im->xsize);
235 for (y = 0; y < im->ysize; ++y) {
236 i_glinf(im, 0, im->xsize, y, line);
237 i_plinf(targ, 0, im->xsize, y, line);
238 }
239
240 myfree(line);
241
242 return targ;
243}
244
8d14daab
TC
245static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
246 i_img_dim off;
247 int ch;
faa9b3e7 248
837a4b43 249 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
250 return -1;
251
252 off = (x + y * im->xsize) * im->channels;
9b8ce4f4
TC
253 if (I_ALL_CHANNELS_WRITABLE(im)) {
254 for (ch = 0; ch < im->channels; ++ch)
255 STORE8as16(im->idata, off+ch, val->channel[ch]);
256 }
257 else {
258 for (ch = 0; ch < im->channels; ++ch)
259 if (im->ch_mask & (1 << ch))
260 STORE8as16(im->idata, off+ch, val->channel[ch]);
261 }
faa9b3e7
TC
262
263 return 0;
264}
265
8d14daab
TC
266static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
267 i_img_dim off;
268 int ch;
faa9b3e7 269
837a4b43 270 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
271 return -1;
272
273 off = (x + y * im->xsize) * im->channels;
274 for (ch = 0; ch < im->channels; ++ch)
275 val->channel[ch] = GET16as8(im->idata, off+ch);
276
277 return 0;
278}
279
8d14daab
TC
280static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
281 i_img_dim off;
282 int ch;
faa9b3e7 283
837a4b43 284 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
285 return -1;
286
287 off = (x + y * im->xsize) * im->channels;
9b8ce4f4
TC
288 if (I_ALL_CHANNELS_WRITABLE(im)) {
289 for (ch = 0; ch < im->channels; ++ch)
290 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
291 }
292 else {
293 for (ch = 0; ch < im->channels; ++ch)
294 if (im->ch_mask & (1 << ch))
295 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
296 }
faa9b3e7
TC
297
298 return 0;
299}
300
8d14daab
TC
301static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
302 i_img_dim off;
303 int ch;
faa9b3e7 304
837a4b43 305 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
faa9b3e7
TC
306 return -1;
307
308 off = (x + y * im->xsize) * im->channels;
309 for (ch = 0; ch < im->channels; ++ch)
310 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
311
312 return 0;
313}
314
8d14daab
TC
315static i_img_dim i_glin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) {
316 int ch;
317 i_img_dim count, i;
318 i_img_dim off;
faa9b3e7
TC
319 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
320 if (r > im->xsize)
321 r = im->xsize;
322 off = (l+y*im->xsize) * im->channels;
323 count = r - l;
324 for (i = 0; i < count; ++i) {
325 for (ch = 0; ch < im->channels; ++ch) {
326 vals[i].channel[ch] = GET16as8(im->idata, off);
327 ++off;
328 }
329 }
330 return count;
331 }
332 else {
333 return 0;
334 }
335}
336
8d14daab
TC
337static 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) {
338 int ch;
339 i_img_dim count, i;
340 i_img_dim off;
faa9b3e7
TC
341 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
342 if (r > im->xsize)
343 r = im->xsize;
344 off = (l+y*im->xsize) * im->channels;
345 count = r - l;
9b8ce4f4
TC
346 if (I_ALL_CHANNELS_WRITABLE(im)) {
347 for (i = 0; i < count; ++i) {
348 for (ch = 0; ch < im->channels; ++ch) {
349 STORE8as16(im->idata, off, vals[i].channel[ch]);
350 ++off;
351 }
352 }
353 }
354 else {
355 for (i = 0; i < count; ++i) {
356 for (ch = 0; ch < im->channels; ++ch) {
357 if (im->ch_mask & (1 << ch))
358 STORE8as16(im->idata, off, vals[i].channel[ch]);
359 ++off;
360 }
faa9b3e7
TC
361 }
362 }
363 return count;
364 }
365 else {
366 return 0;
367 }
368}
369
8d14daab
TC
370static i_img_dim i_glinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) {
371 int ch;
372 i_img_dim count, i;
373 i_img_dim off;
faa9b3e7
TC
374 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
375 if (r > im->xsize)
376 r = im->xsize;
377 off = (l+y*im->xsize) * im->channels;
378 count = r - l;
379 for (i = 0; i < count; ++i) {
380 for (ch = 0; ch < im->channels; ++ch) {
381 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
382 ++off;
383 }
384 }
385 return count;
386 }
387 else {
388 return 0;
389 }
390}
391
8d14daab
TC
392static 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) {
393 int ch;
394 i_img_dim count, i;
395 i_img_dim off;
faa9b3e7
TC
396 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
397 if (r > im->xsize)
398 r = im->xsize;
399 off = (l+y*im->xsize) * im->channels;
400 count = r - l;
9b8ce4f4
TC
401 if (I_ALL_CHANNELS_WRITABLE(im)) {
402 for (i = 0; i < count; ++i) {
403 for (ch = 0; ch < im->channels; ++ch) {
404 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
405 ++off;
406 }
407 }
408 }
409 else {
410 for (i = 0; i < count; ++i) {
411 for (ch = 0; ch < im->channels; ++ch) {
412 if (im->ch_mask & (1 << ch))
413 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
414 ++off;
415 }
faa9b3e7
TC
416 }
417 }
418 return count;
419 }
420 else {
421 return 0;
422 }
423}
424
8d14daab 425static 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 426 int const *chans, int chan_count) {
8d14daab
TC
427 int ch;
428 i_img_dim count, i, w;
429 i_img_dim off;
faa9b3e7
TC
430
431 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
432 if (r > im->xsize)
433 r = im->xsize;
434 off = (l+y*im->xsize) * im->channels;
435 w = r - l;
436 count = 0;
437
438 if (chans) {
439 /* make sure we have good channel numbers */
440 for (ch = 0; ch < chan_count; ++ch) {
441 if (chans[ch] < 0 || chans[ch] >= im->channels) {
98174be7
TC
442 dIMCTXim(im);
443 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
faa9b3e7
TC
444 return 0;
445 }
446 }
447 for (i = 0; i < w; ++i) {
448 for (ch = 0; ch < chan_count; ++ch) {
449 *samps++ = GET16as8(im->idata, off+chans[ch]);
450 ++count;
451 }
452 off += im->channels;
453 }
454 }
455 else {
c7481ae1 456 if (chan_count <= 0 || chan_count > im->channels) {
98174be7
TC
457 dIMCTXim(im);
458 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
c7481ae1
TC
459 chan_count);
460 return 0;
461 }
faa9b3e7
TC
462 for (i = 0; i < w; ++i) {
463 for (ch = 0; ch < chan_count; ++ch) {
464 *samps++ = GET16as8(im->idata, off+ch);
465 ++count;
466 }
467 off += im->channels;
468 }
469 }
470
471 return count;
472 }
473 else {
474 return 0;
475 }
476}
477
8d14daab 478static 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 479 int const *chans, int chan_count) {
8d14daab
TC
480 int ch;
481 i_img_dim count, i, w;
482 i_img_dim off;
faa9b3e7
TC
483
484 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
485 if (r > im->xsize)
486 r = im->xsize;
487 off = (l+y*im->xsize) * im->channels;
488 w = r - l;
489 count = 0;
490
491 if (chans) {
492 /* make sure we have good channel numbers */
493 for (ch = 0; ch < chan_count; ++ch) {
494 if (chans[ch] < 0 || chans[ch] >= im->channels) {
98174be7
TC
495 dIMCTXim(im);
496 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
faa9b3e7
TC
497 return 0;
498 }
499 }
500 for (i = 0; i < w; ++i) {
501 for (ch = 0; ch < chan_count; ++ch) {
502 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
503 ++count;
504 }
505 off += im->channels;
506 }
507 }
508 else {
c7481ae1 509 if (chan_count <= 0 || chan_count > im->channels) {
98174be7
TC
510 dIMCTXim(im);
511 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
c7481ae1
TC
512 chan_count);
513 return 0;
514 }
faa9b3e7
TC
515 for (i = 0; i < w; ++i) {
516 for (ch = 0; ch < chan_count; ++ch) {
517 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
518 ++count;
519 }
520 off += im->channels;
521 }
522 }
523
524 return count;
525 }
526 else {
527 return 0;
528 }
529}
530
8d14daab
TC
531static i_img_dim
532i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
bd8052a6 533 int const *chans, int chan_count, int bits) {
8d14daab
TC
534 int ch;
535 i_img_dim count, i, w;
536 i_img_dim off;
bd8052a6
TC
537
538 if (bits != 16) {
539 return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits);
540 }
541
542 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
543 if (r > im->xsize)
544 r = im->xsize;
545 off = (l+y*im->xsize) * im->channels;
546 w = r - l;
547 count = 0;
548
549 if (chans) {
550 /* make sure we have good channel numbers */
551 for (ch = 0; ch < chan_count; ++ch) {
552 if (chans[ch] < 0 || chans[ch] >= im->channels) {
98174be7
TC
553 dIMCTXim(im);
554 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
bd8052a6
TC
555 return -1;
556 }
557 }
558 for (i = 0; i < w; ++i) {
559 for (ch = 0; ch < chan_count; ++ch) {
560 *samps++ = GET16(im->idata, off+chans[ch]);
561 ++count;
562 }
563 off += im->channels;
564 }
565 }
566 else {
567 if (chan_count <= 0 || chan_count > im->channels) {
156699af 568 dIMCTXim(im);
bd8052a6
TC
569 i_push_error(0, "Invalid channel count");
570 return -1;
571 }
572 for (i = 0; i < w; ++i) {
573 for (ch = 0; ch < chan_count; ++ch) {
574 *samps++ = GET16(im->idata, off+ch);
575 ++count;
576 }
577 off += im->channels;
578 }
579 }
580
581 return count;
582 }
583 else {
156699af 584 dIMCTXim(im);
bd8052a6
TC
585 i_push_error(0, "Image position outside of image");
586 return -1;
587 }
588}
589
8d14daab
TC
590static i_img_dim
591i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
bd8052a6 592 int const *chans, int chan_count, int bits) {
8d14daab
TC
593 int ch;
594 i_img_dim count, i, w;
595 i_img_dim off;
bd8052a6
TC
596
597 if (bits != 16) {
156699af 598 dIMCTXim(im);
bd8052a6
TC
599 i_push_error(0, "Invalid bits for 16-bit image");
600 return -1;
601 }
602
603 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
604 if (r > im->xsize)
605 r = im->xsize;
606 off = (l+y*im->xsize) * im->channels;
607 w = r - l;
608 count = 0;
609
610 if (chans) {
611 /* make sure we have good channel numbers */
612 for (ch = 0; ch < chan_count; ++ch) {
613 if (chans[ch] < 0 || chans[ch] >= im->channels) {
98174be7
TC
614 dIMCTXim(im);
615 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
bd8052a6
TC
616 return -1;
617 }
618 }
619 for (i = 0; i < w; ++i) {
620 for (ch = 0; ch < chan_count; ++ch) {
621 if (im->ch_mask & (1 << ch))
622 STORE16(im->idata, off+chans[ch], *samps);
623 ++samps;
624 ++count;
625 }
626 off += im->channels;
627 }
628 }
629 else {
630 if (chan_count <= 0 || chan_count > im->channels) {
156699af 631 dIMCTXim(im);
bd8052a6
TC
632 i_push_error(0, "Invalid channel count");
633 return -1;
634 }
635 for (i = 0; i < w; ++i) {
636 for (ch = 0; ch < chan_count; ++ch) {
637 if (im->ch_mask & (1 << ch))
638 STORE16(im->idata, off+ch, *samps);
639 ++samps;
640 ++count;
641 }
642 off += im->channels;
643 }
644 }
645
646 return count;
647 }
648 else {
156699af 649 dIMCTXim(im);
bd8052a6
TC
650 i_push_error(0, "Image position outside of image");
651 return -1;
652 }
653}
654
836d9f54
TC
655/*
656=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)
657
658Writes sample values to im for the horizontal line (l, y) to (r-1,y)
659for the channels specified by chans, an array of int with chan_count
660elements.
661
662Returns the number of samples written (which should be (r-l) *
663bits_set(chan_mask)
664
665=cut
666*/
667
668static
669i_img_dim
670i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
671 const i_sample_t *samps, const int *chans, int chan_count) {
672 int ch;
673 i_img_dim count, i, w;
674
675 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
836d9f54
TC
676 i_img_dim offset;
677 if (r > im->xsize)
678 r = im->xsize;
679 offset = (l+y*im->xsize) * im->channels;
680 w = r - l;
681 count = 0;
682
683 if (chans) {
684 /* make sure we have good channel numbers */
685 /* and test if all channels specified are in the mask */
686 int all_in_mask = 1;
687 for (ch = 0; ch < chan_count; ++ch) {
688 if (chans[ch] < 0 || chans[ch] >= im->channels) {
98174be7
TC
689 dIMCTXim(im);
690 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
836d9f54
TC
691 return -1;
692 }
693 if (!((1 << chans[ch]) & im->ch_mask))
694 all_in_mask = 0;
695 }
696 if (all_in_mask) {
697 for (i = 0; i < w; ++i) {
698 for (ch = 0; ch < chan_count; ++ch) {
699 STORE8as16(im->idata, offset + chans[ch], *samps);
700 ++samps;
701 ++count;
702 }
703 offset += im->channels;
704 }
705 }
706 else {
707 for (i = 0; i < w; ++i) {
708 for (ch = 0; ch < chan_count; ++ch) {
709 if (im->ch_mask & (1 << (chans[ch])))
710 STORE8as16(im->idata, offset + chans[ch], *samps);
711 ++samps;
712 ++count;
713 }
714 offset += im->channels;
715 }
716 }
717 }
718 else {
719 if (chan_count <= 0 || chan_count > im->channels) {
98174be7
TC
720 dIMCTXim(im);
721 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
836d9f54
TC
722 chan_count);
723 return -1;
724 }
725 for (i = 0; i < w; ++i) {
726 unsigned mask = 1;
727 for (ch = 0; ch < chan_count; ++ch) {
728 if (im->ch_mask & mask)
729 STORE8as16(im->idata, offset + ch, *samps);
730 ++samps;
731 ++count;
732 mask <<= 1;
733 }
734 offset += im->channels;
735 }
736 }
737
738 return count;
739 }
740 else {
156699af 741 dIMCTXim(im);
836d9f54
TC
742 i_push_error(0, "Image position outside of image");
743 return -1;
744 }
745}
746
747/*
748=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)
749
750Writes sample values to im for the horizontal line (l, y) to (r-1,y)
751for the channels specified by chans, an array of int with chan_count
752elements.
753
754Returns the number of samples written (which should be (r-l) *
755bits_set(chan_mask)
756
757=cut
758*/
759
760static
761i_img_dim
762i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
763 const i_fsample_t *samps, const int *chans, int chan_count) {
764 int ch;
765 i_img_dim count, i, w;
766
767 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
836d9f54
TC
768 i_img_dim offset;
769 if (r > im->xsize)
770 r = im->xsize;
771 offset = (l+y*im->xsize) * im->channels;
772 w = r - l;
773 count = 0;
774
775 if (chans) {
776 /* make sure we have good channel numbers */
777 /* and test if all channels specified are in the mask */
778 int all_in_mask = 1;
779 for (ch = 0; ch < chan_count; ++ch) {
780 if (chans[ch] < 0 || chans[ch] >= im->channels) {
98174be7
TC
781 dIMCTXim(im);
782 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
836d9f54
TC
783 return -1;
784 }
785 if (!((1 << chans[ch]) & im->ch_mask))
786 all_in_mask = 0;
787 }
788 if (all_in_mask) {
789 for (i = 0; i < w; ++i) {
790 for (ch = 0; ch < chan_count; ++ch) {
791 unsigned samp16 = SampleFTo16(*samps);
792 STORE16(im->idata, offset + chans[ch], samp16);
793 ++samps;
794 ++count;
795 }
796 offset += im->channels;
797 }
798 }
799 else {
800 for (i = 0; i < w; ++i) {
801 for (ch = 0; ch < chan_count; ++ch) {
802 if (im->ch_mask & (1 << (chans[ch]))) {
803 unsigned samp16 = SampleFTo16(*samps);
804 STORE16(im->idata, offset + chans[ch], samp16);
805 }
806 ++samps;
807 ++count;
808 }
809 offset += im->channels;
810 }
811 }
812 }
813 else {
814 if (chan_count <= 0 || chan_count > im->channels) {
98174be7
TC
815 dIMCTXim(im);
816 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
836d9f54
TC
817 chan_count);
818 return -1;
819 }
820 for (i = 0; i < w; ++i) {
821 unsigned mask = 1;
822 for (ch = 0; ch < chan_count; ++ch) {
823 if (im->ch_mask & mask) {
824 unsigned samp16 = SampleFTo16(*samps);
825 STORE16(im->idata, offset + ch, samp16);
826 }
827 ++samps;
828 ++count;
829 mask <<= 1;
830 }
831 offset += im->channels;
832 }
833 }
834
835 return count;
836 }
837 else {
156699af 838 dIMCTXim(im);
836d9f54
TC
839 i_push_error(0, "Image position outside of image");
840 return -1;
841 }
842}
843
b8c2033e
AMH
844/*
845=back
846
847=head1 AUTHOR
848
849Tony Cook <tony@develop-help.com>
850
851=head1 SEE ALSO
852
853Imager(3)
854
855=cut
856*/