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.
26 static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val);
27 static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val);
28 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);
29 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);
30 static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val);
31 static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val);
32 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);
33 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);
34 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,
35 int const *chans, int chan_count);
36 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,
37 int const *chans, int chan_count);
38 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,
39 int const *chans, int chan_count, int bits);
40 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,
41 int const *chans, int chan_count, int bits);
44 =item IIM_base_16bit_direct
46 Base structure used to initialize a 16-bit/sample image.
52 static i_img IIM_base_16bit_direct =
55 0, 0, 0, /* xsize, ysize, bytes */
58 i_direct_type, /* type */
61 { 0, 0, NULL }, /* tags */
64 i_ppix_d16, /* i_f_ppix */
65 i_ppixf_d16, /* i_f_ppixf */
66 i_plin_d16, /* i_f_plin */
67 i_plinf_d16, /* i_f_plinf */
68 i_gpix_d16, /* i_f_gpix */
69 i_gpixf_d16, /* i_f_gpixf */
70 i_glin_d16, /* i_f_glin */
71 i_glinf_d16, /* i_f_glinf */
72 i_gsamp_d16, /* i_f_gsamp */
73 i_gsampf_d16, /* i_f_gsampf */
77 NULL, /* i_f_addcolors */
78 NULL, /* i_f_getcolors */
79 NULL, /* i_f_colorcount */
80 NULL, /* i_f_maxcolors */
81 NULL, /* i_f_findcolor */
82 NULL, /* i_f_setcolors */
84 NULL, /* i_f_destroy */
90 /* it's possible some platforms won't have a 16-bit integer type,
91 so we check for one otherwise we work by bytes directly
93 We do assume 8-bit char
95 "Compaq C V6.4-009 on Compaq Tru64 UNIX V5.1A (Rev. 1885)" says it
96 supports C99, but doesn't supply stdint.h, which is required for
97 both hosted and freestanding implementations. So guard against it.
99 #if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
100 /* C99 should define something useful */
103 typedef uint16_t i_sample16_t;
108 /* check out unsigned short */
111 #if USHRT_MAX == 65535
112 typedef unsigned short i_sample16_t;
119 /* we have a real 16-bit unsigned integer */
120 #define STORE16(bytes, offset, word) \
121 (((i_sample16_t *)(bytes))[offset] = (word))
122 #define STORE8as16(bytes, offset, byte) \
123 (((i_sample16_t *)(bytes))[offset] = (byte) * 256 + (byte))
124 #define GET16(bytes, offset) \
125 (((i_sample16_t *)(bytes))[offset])
128 /* we have to do this the hard way */
129 #define STORE16(bytes, offset, word) \
130 ((((unsigned char *)(bytes))[(offset)*2] = (word) >> 8), \
131 (((unsigned char *)(bytes))[(offset)*2+1] = (word) & 0xFF))
132 #define STORE8as16(bytes, offset, byte) \
133 ((((unsigned char *)(bytes))[(offset)*2] = (byte)), \
134 (((unsigned char *)(bytes))[(offset)*2+1] = (byte)))
136 #define GET16(bytes, offset) \
137 (((unsigned char *)(bytes))[(offset)*2] * 256 \
138 + ((unsigned char *)(bytes))[(offset)*2+1])
142 #define GET16as8(bytes, offset) \
143 ((((i_sample16_t *)(bytes))[offset]+127) / 257)
146 =item i_img_16_new(x, y, ch)
148 =category Image creation/destruction
149 =synopsis i_img *img = i_img_16_new(width, height, channels);
151 Create a new 16-bit/sample image.
153 Returns the image on success, or NULL on failure.
158 i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch) {
160 size_t bytes, line_bytes;
162 mm_log((1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
163 i_DFc(x), i_DFc(y), ch));
165 if (x < 1 || y < 1) {
166 i_push_error(0, "Image sizes must be positive");
169 if (ch < 1 || ch > MAXCHANNELS) {
170 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
173 bytes = x * y * ch * 2;
174 if (bytes / y / ch / 2 != x) {
175 i_push_errorf(0, "integer overflow calculating image allocation");
179 /* basic assumption: we can always allocate a buffer representing a
180 line from the image, otherwise we're going to have trouble
181 working with the image */
182 line_bytes = sizeof(i_fcolor) * x;
183 if (line_bytes / x != sizeof(i_fcolor)) {
184 i_push_error(0, "integer overflow calculating scanline allocation");
189 *im = IIM_base_16bit_direct;
190 i_tags_new(&im->tags);
196 im->idata = mymalloc(im->bytes);
197 memset(im->idata, 0, im->bytes);
205 =item i_img_to_rgb16(im)
207 =category Image creation
209 Returns a 16-bit/sample version of the supplied image.
211 Returns the image on success, or NULL on failure.
217 i_img_to_rgb16(i_img *im) {
222 targ = i_img_16_new(im->xsize, im->ysize, im->channels);
225 line = mymalloc(sizeof(i_fcolor) * im->xsize);
226 for (y = 0; y < im->ysize; ++y) {
227 i_glinf(im, 0, im->xsize, y, line);
228 i_plinf(targ, 0, im->xsize, y, line);
236 static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
240 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
243 off = (x + y * im->xsize) * im->channels;
244 if (I_ALL_CHANNELS_WRITABLE(im)) {
245 for (ch = 0; ch < im->channels; ++ch)
246 STORE8as16(im->idata, off+ch, val->channel[ch]);
249 for (ch = 0; ch < im->channels; ++ch)
250 if (im->ch_mask & (1 << ch))
251 STORE8as16(im->idata, off+ch, val->channel[ch]);
257 static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
261 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
264 off = (x + y * im->xsize) * im->channels;
265 for (ch = 0; ch < im->channels; ++ch)
266 val->channel[ch] = GET16as8(im->idata, off+ch);
271 static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
275 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
278 off = (x + y * im->xsize) * im->channels;
279 if (I_ALL_CHANNELS_WRITABLE(im)) {
280 for (ch = 0; ch < im->channels; ++ch)
281 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
284 for (ch = 0; ch < im->channels; ++ch)
285 if (im->ch_mask & (1 << ch))
286 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
292 static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
296 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
299 off = (x + y * im->xsize) * im->channels;
300 for (ch = 0; ch < im->channels; ++ch)
301 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
306 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) {
310 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
313 off = (l+y*im->xsize) * im->channels;
315 for (i = 0; i < count; ++i) {
316 for (ch = 0; ch < im->channels; ++ch) {
317 vals[i].channel[ch] = GET16as8(im->idata, off);
328 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) {
332 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
335 off = (l+y*im->xsize) * im->channels;
337 if (I_ALL_CHANNELS_WRITABLE(im)) {
338 for (i = 0; i < count; ++i) {
339 for (ch = 0; ch < im->channels; ++ch) {
340 STORE8as16(im->idata, off, vals[i].channel[ch]);
346 for (i = 0; i < count; ++i) {
347 for (ch = 0; ch < im->channels; ++ch) {
348 if (im->ch_mask & (1 << ch))
349 STORE8as16(im->idata, off, vals[i].channel[ch]);
361 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) {
365 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
368 off = (l+y*im->xsize) * im->channels;
370 for (i = 0; i < count; ++i) {
371 for (ch = 0; ch < im->channels; ++ch) {
372 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
383 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) {
387 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
390 off = (l+y*im->xsize) * im->channels;
392 if (I_ALL_CHANNELS_WRITABLE(im)) {
393 for (i = 0; i < count; ++i) {
394 for (ch = 0; ch < im->channels; ++ch) {
395 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
401 for (i = 0; i < count; ++i) {
402 for (ch = 0; ch < im->channels; ++ch) {
403 if (im->ch_mask & (1 << ch))
404 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
416 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,
417 int const *chans, int chan_count) {
419 i_img_dim count, i, w;
422 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
425 off = (l+y*im->xsize) * im->channels;
430 /* make sure we have good channel numbers */
431 for (ch = 0; ch < chan_count; ++ch) {
432 if (chans[ch] < 0 || chans[ch] >= im->channels) {
433 i_push_errorf(0, "No channel %d in this image", chans[ch]);
437 for (i = 0; i < w; ++i) {
438 for (ch = 0; ch < chan_count; ++ch) {
439 *samps++ = GET16as8(im->idata, off+chans[ch]);
446 if (chan_count <= 0 || chan_count > im->channels) {
447 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
451 for (i = 0; i < w; ++i) {
452 for (ch = 0; ch < chan_count; ++ch) {
453 *samps++ = GET16as8(im->idata, off+ch);
467 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,
468 int const *chans, int chan_count) {
470 i_img_dim count, i, w;
473 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
476 off = (l+y*im->xsize) * im->channels;
481 /* make sure we have good channel numbers */
482 for (ch = 0; ch < chan_count; ++ch) {
483 if (chans[ch] < 0 || chans[ch] >= im->channels) {
484 i_push_errorf(0, "No channel %d in this image", chans[ch]);
488 for (i = 0; i < w; ++i) {
489 for (ch = 0; ch < chan_count; ++ch) {
490 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
497 if (chan_count <= 0 || chan_count > im->channels) {
498 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
502 for (i = 0; i < w; ++i) {
503 for (ch = 0; ch < chan_count; ++ch) {
504 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
519 i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
520 int const *chans, int chan_count, int bits) {
522 i_img_dim count, i, w;
526 return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits);
529 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
532 off = (l+y*im->xsize) * im->channels;
537 /* make sure we have good channel numbers */
538 for (ch = 0; ch < chan_count; ++ch) {
539 if (chans[ch] < 0 || chans[ch] >= im->channels) {
540 i_push_errorf(0, "No channel %d in this image", chans[ch]);
544 for (i = 0; i < w; ++i) {
545 for (ch = 0; ch < chan_count; ++ch) {
546 *samps++ = GET16(im->idata, off+chans[ch]);
553 if (chan_count <= 0 || chan_count > im->channels) {
554 i_push_error(0, "Invalid channel count");
557 for (i = 0; i < w; ++i) {
558 for (ch = 0; ch < chan_count; ++ch) {
559 *samps++ = GET16(im->idata, off+ch);
569 i_push_error(0, "Image position outside of image");
575 i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
576 int const *chans, int chan_count, int bits) {
578 i_img_dim count, i, w;
582 i_push_error(0, "Invalid bits for 16-bit image");
586 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
589 off = (l+y*im->xsize) * im->channels;
594 /* make sure we have good channel numbers */
595 for (ch = 0; ch < chan_count; ++ch) {
596 if (chans[ch] < 0 || chans[ch] >= im->channels) {
597 i_push_errorf(0, "No channel %d in this image", chans[ch]);
601 for (i = 0; i < w; ++i) {
602 for (ch = 0; ch < chan_count; ++ch) {
603 if (im->ch_mask & (1 << ch))
604 STORE16(im->idata, off+chans[ch], *samps);
612 if (chan_count <= 0 || chan_count > im->channels) {
613 i_push_error(0, "Invalid channel count");
616 for (i = 0; i < w; ++i) {
617 for (ch = 0; ch < chan_count; ++ch) {
618 if (im->ch_mask & (1 << ch))
619 STORE16(im->idata, off+ch, *samps);
630 i_push_error(0, "Image position outside of image");
640 Tony Cook <tony@develop-help.com>