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