4 img16.c - implements 16-bit images
8 i_img *im = i_img_16_new(i_img_dim x, i_img_dim y, int channels);
9 # use like a normal image
13 Implements 16-bit/sample images.
15 This basic implementation is required so that we have some larger
16 sample image type to work with.
23 #define IMAGER_NO_CONTEXT
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);
48 =item IIM_base_16bit_direct
50 Base structure used to initialize a 16-bit/sample image.
56 static i_img IIM_base_16bit_direct =
59 0, 0, 0, /* xsize, ysize, bytes */
62 i_direct_type, /* type */
65 { 0, 0, NULL }, /* tags */
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 */
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 */
88 NULL, /* i_f_destroy */
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
100 We do assume 8-bit char
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.
106 #if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
107 /* C99 should define something useful */
110 typedef uint16_t i_sample16_t;
115 /* check out unsigned short */
118 #if USHRT_MAX == 65535
119 typedef unsigned short i_sample16_t;
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])
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)))
143 #define GET16(bytes, offset) \
144 (((unsigned char *)(bytes))[(offset)*2] * 256 \
145 + ((unsigned char *)(bytes))[(offset)*2+1])
149 #define GET16as8(bytes, offset) \
150 ((((i_sample16_t *)(bytes))[offset]+127) / 257)
153 =item i_img_16_new(x, y, ch)
155 =category Image creation/destruction
156 =synopsis i_img *img = i_img_16_new(width, height, channels);
158 Create a new 16-bit/sample image.
160 Returns the image on success, or NULL on failure.
166 im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
168 size_t bytes, line_bytes;
170 mm_log((1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
171 i_DFc(x), i_DFc(y), ch));
173 if (x < 1 || y < 1) {
174 im_push_error(aIMCTX, 0, "Image sizes must be positive");
177 if (ch < 1 || ch > MAXCHANNELS) {
178 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
181 bytes = x * y * ch * 2;
182 if (bytes / y / ch / 2 != x) {
183 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
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)) {
192 im_push_error(aIMCTX, 0, "integer overflow calculating scanline allocation");
196 im = im_img_alloc(aIMCTX);
197 *im = IIM_base_16bit_direct;
198 i_tags_new(&im->tags);
204 im->idata = mymalloc(im->bytes);
205 memset(im->idata, 0, im->bytes);
207 im_img_init(aIMCTX, im);
213 =item i_img_to_rgb16(im)
215 =category Image creation
217 Returns a 16-bit/sample version of the supplied image.
219 Returns the image on success, or NULL on failure.
225 i_img_to_rgb16(i_img *im) {
231 targ = im_img_16_new(aIMCTX, im->xsize, im->ysize, im->channels);
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);
245 static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
249 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
252 off = (x + y * im->xsize) * im->channels;
253 if (I_ALL_CHANNELS_WRITABLE(im)) {
254 for (ch = 0; ch < im->channels; ++ch)
255 STORE8as16(im->idata, off+ch, val->channel[ch]);
258 for (ch = 0; ch < im->channels; ++ch)
259 if (im->ch_mask & (1 << ch))
260 STORE8as16(im->idata, off+ch, val->channel[ch]);
266 static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
270 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
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);
280 static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
284 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
287 off = (x + y * im->xsize) * im->channels;
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]));
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]));
301 static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
305 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
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));
315 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 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
322 off = (l+y*im->xsize) * im->channels;
324 for (i = 0; i < count; ++i) {
325 for (ch = 0; ch < im->channels; ++ch) {
326 vals[i].channel[ch] = GET16as8(im->idata, off);
337 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 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
344 off = (l+y*im->xsize) * im->channels;
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]);
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]);
370 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 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
377 off = (l+y*im->xsize) * im->channels;
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));
392 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 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
399 off = (l+y*im->xsize) * im->channels;
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]));
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]));
425 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,
426 int const *chans, int chan_count) {
428 i_img_dim count, i, w;
431 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
434 off = (l+y*im->xsize) * im->channels;
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) {
442 i_push_errorf(0, "No channel %d in this image", chans[ch]);
446 for (i = 0; i < w; ++i) {
447 for (ch = 0; ch < chan_count; ++ch) {
448 *samps++ = GET16as8(im->idata, off+chans[ch]);
455 if (chan_count <= 0 || chan_count > im->channels) {
456 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
460 for (i = 0; i < w; ++i) {
461 for (ch = 0; ch < chan_count; ++ch) {
462 *samps++ = GET16as8(im->idata, off+ch);
476 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,
477 int const *chans, int chan_count) {
479 i_img_dim count, i, w;
482 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
485 off = (l+y*im->xsize) * im->channels;
490 /* make sure we have good channel numbers */
491 for (ch = 0; ch < chan_count; ++ch) {
492 if (chans[ch] < 0 || chans[ch] >= im->channels) {
493 i_push_errorf(0, "No channel %d in this image", chans[ch]);
497 for (i = 0; i < w; ++i) {
498 for (ch = 0; ch < chan_count; ++ch) {
499 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
506 if (chan_count <= 0 || chan_count > im->channels) {
507 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
511 for (i = 0; i < w; ++i) {
512 for (ch = 0; ch < chan_count; ++ch) {
513 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
528 i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
529 int const *chans, int chan_count, int bits) {
531 i_img_dim count, i, w;
535 return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits);
538 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
541 off = (l+y*im->xsize) * im->channels;
546 /* make sure we have good channel numbers */
547 for (ch = 0; ch < chan_count; ++ch) {
548 if (chans[ch] < 0 || chans[ch] >= im->channels) {
549 i_push_errorf(0, "No channel %d in this image", chans[ch]);
553 for (i = 0; i < w; ++i) {
554 for (ch = 0; ch < chan_count; ++ch) {
555 *samps++ = GET16(im->idata, off+chans[ch]);
562 if (chan_count <= 0 || chan_count > im->channels) {
564 i_push_error(0, "Invalid channel count");
567 for (i = 0; i < w; ++i) {
568 for (ch = 0; ch < chan_count; ++ch) {
569 *samps++ = GET16(im->idata, off+ch);
580 i_push_error(0, "Image position outside of image");
586 i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
587 int const *chans, int chan_count, int bits) {
589 i_img_dim count, i, w;
594 i_push_error(0, "Invalid bits for 16-bit image");
598 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
601 off = (l+y*im->xsize) * im->channels;
606 /* make sure we have good channel numbers */
607 for (ch = 0; ch < chan_count; ++ch) {
608 if (chans[ch] < 0 || chans[ch] >= im->channels) {
609 i_push_errorf(0, "No channel %d in this image", chans[ch]);
613 for (i = 0; i < w; ++i) {
614 for (ch = 0; ch < chan_count; ++ch) {
615 if (im->ch_mask & (1 << ch))
616 STORE16(im->idata, off+chans[ch], *samps);
624 if (chan_count <= 0 || chan_count > im->channels) {
626 i_push_error(0, "Invalid channel count");
629 for (i = 0; i < w; ++i) {
630 for (ch = 0; ch < chan_count; ++ch) {
631 if (im->ch_mask & (1 << ch))
632 STORE16(im->idata, off+ch, *samps);
644 i_push_error(0, "Image position outside of image");
650 =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)
652 Writes sample values to im for the horizontal line (l, y) to (r-1,y)
653 for the channels specified by chans, an array of int with chan_count
656 Returns the number of samples written (which should be (r-l) *
664 i_psamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
665 const i_sample_t *samps, const int *chans, int chan_count) {
667 i_img_dim count, i, w;
669 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
673 offset = (l+y*im->xsize) * im->channels;
678 /* make sure we have good channel numbers */
679 /* and test if all channels specified are in the mask */
681 for (ch = 0; ch < chan_count; ++ch) {
682 if (chans[ch] < 0 || chans[ch] >= im->channels) {
683 i_push_errorf(0, "No channel %d in this image", chans[ch]);
686 if (!((1 << chans[ch]) & im->ch_mask))
690 for (i = 0; i < w; ++i) {
691 for (ch = 0; ch < chan_count; ++ch) {
692 STORE8as16(im->idata, offset + chans[ch], *samps);
696 offset += im->channels;
700 for (i = 0; i < w; ++i) {
701 for (ch = 0; ch < chan_count; ++ch) {
702 if (im->ch_mask & (1 << (chans[ch])))
703 STORE8as16(im->idata, offset + chans[ch], *samps);
707 offset += im->channels;
712 if (chan_count <= 0 || chan_count > im->channels) {
713 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
717 for (i = 0; i < w; ++i) {
719 for (ch = 0; ch < chan_count; ++ch) {
720 if (im->ch_mask & mask)
721 STORE8as16(im->idata, offset + ch, *samps);
726 offset += im->channels;
734 i_push_error(0, "Image position outside of image");
740 =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)
742 Writes sample values to im for the horizontal line (l, y) to (r-1,y)
743 for the channels specified by chans, an array of int with chan_count
746 Returns the number of samples written (which should be (r-l) *
754 i_psampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
755 const i_fsample_t *samps, const int *chans, int chan_count) {
757 i_img_dim count, i, w;
759 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
763 offset = (l+y*im->xsize) * im->channels;
768 /* make sure we have good channel numbers */
769 /* and test if all channels specified are in the mask */
771 for (ch = 0; ch < chan_count; ++ch) {
772 if (chans[ch] < 0 || chans[ch] >= im->channels) {
773 i_push_errorf(0, "No channel %d in this image", chans[ch]);
776 if (!((1 << chans[ch]) & im->ch_mask))
780 for (i = 0; i < w; ++i) {
781 for (ch = 0; ch < chan_count; ++ch) {
782 unsigned samp16 = SampleFTo16(*samps);
783 STORE16(im->idata, offset + chans[ch], samp16);
787 offset += im->channels;
791 for (i = 0; i < w; ++i) {
792 for (ch = 0; ch < chan_count; ++ch) {
793 if (im->ch_mask & (1 << (chans[ch]))) {
794 unsigned samp16 = SampleFTo16(*samps);
795 STORE16(im->idata, offset + chans[ch], samp16);
800 offset += im->channels;
805 if (chan_count <= 0 || chan_count > im->channels) {
806 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
810 for (i = 0; i < w; ++i) {
812 for (ch = 0; ch < chan_count; ++ch) {
813 if (im->ch_mask & mask) {
814 unsigned samp16 = SampleFTo16(*samps);
815 STORE16(im->idata, offset + ch, samp16);
821 offset += im->channels;
829 i_push_error(0, "Image position outside of image");
839 Tony Cook <tony@develop-help.com>