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);
42 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);
43 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);
46 =item IIM_base_16bit_direct
48 Base structure used to initialize a 16-bit/sample image.
54 static i_img IIM_base_16bit_direct =
57 0, 0, 0, /* xsize, ysize, bytes */
60 i_direct_type, /* type */
63 { 0, 0, NULL }, /* tags */
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 */
79 NULL, /* i_f_addcolors */
80 NULL, /* i_f_getcolors */
81 NULL, /* i_f_colorcount */
82 NULL, /* i_f_maxcolors */
83 NULL, /* i_f_findcolor */
84 NULL, /* i_f_setcolors */
86 NULL, /* i_f_destroy */
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
98 We do assume 8-bit char
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.
104 #if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
105 /* C99 should define something useful */
108 typedef uint16_t i_sample16_t;
113 /* check out unsigned short */
116 #if USHRT_MAX == 65535
117 typedef unsigned short i_sample16_t;
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) \
128 (((i_sample16_t *)(bytes))[offset] = (byte) * 256 + (byte))
129 #define GET16(bytes, offset) \
130 (((i_sample16_t *)(bytes))[offset])
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)), \
139 (((unsigned char *)(bytes))[(offset)*2+1] = (byte)))
141 #define GET16(bytes, offset) \
142 (((unsigned char *)(bytes))[(offset)*2] * 256 \
143 + ((unsigned char *)(bytes))[(offset)*2+1])
147 #define GET16as8(bytes, offset) \
148 ((((i_sample16_t *)(bytes))[offset]+127) / 257)
151 =item i_img_16_new(x, y, ch)
153 =category Image creation/destruction
154 =synopsis i_img *img = i_img_16_new(width, height, channels);
156 Create a new 16-bit/sample image.
158 Returns the image on success, or NULL on failure.
163 i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch) {
165 size_t bytes, line_bytes;
167 mm_log((1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
168 i_DFc(x), i_DFc(y), ch));
170 if (x < 1 || y < 1) {
171 i_push_error(0, "Image sizes must be positive");
174 if (ch < 1 || ch > MAXCHANNELS) {
175 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
178 bytes = x * y * ch * 2;
179 if (bytes / y / ch / 2 != x) {
180 i_push_errorf(0, "integer overflow calculating image allocation");
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)) {
189 i_push_error(0, "integer overflow calculating scanline allocation");
194 *im = IIM_base_16bit_direct;
195 i_tags_new(&im->tags);
201 im->idata = mymalloc(im->bytes);
202 memset(im->idata, 0, im->bytes);
210 =item i_img_to_rgb16(im)
212 =category Image creation
214 Returns a 16-bit/sample version of the supplied image.
216 Returns the image on success, or NULL on failure.
222 i_img_to_rgb16(i_img *im) {
227 targ = i_img_16_new(im->xsize, im->ysize, im->channels);
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);
241 static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
245 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
248 off = (x + y * im->xsize) * im->channels;
249 if (I_ALL_CHANNELS_WRITABLE(im)) {
250 for (ch = 0; ch < im->channels; ++ch)
251 STORE8as16(im->idata, off+ch, val->channel[ch]);
254 for (ch = 0; ch < im->channels; ++ch)
255 if (im->ch_mask & (1 << ch))
256 STORE8as16(im->idata, off+ch, val->channel[ch]);
262 static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
266 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
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);
276 static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
280 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
283 off = (x + y * im->xsize) * im->channels;
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]));
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]));
297 static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
301 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
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));
311 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) {
315 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
318 off = (l+y*im->xsize) * im->channels;
320 for (i = 0; i < count; ++i) {
321 for (ch = 0; ch < im->channels; ++ch) {
322 vals[i].channel[ch] = GET16as8(im->idata, off);
333 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) {
337 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
340 off = (l+y*im->xsize) * im->channels;
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]);
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]);
366 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) {
370 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
373 off = (l+y*im->xsize) * im->channels;
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));
388 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) {
392 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
395 off = (l+y*im->xsize) * im->channels;
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]));
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]));
421 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,
422 int const *chans, int chan_count) {
424 i_img_dim count, i, w;
427 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
430 off = (l+y*im->xsize) * im->channels;
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) {
438 i_push_errorf(0, "No channel %d in this image", chans[ch]);
442 for (i = 0; i < w; ++i) {
443 for (ch = 0; ch < chan_count; ++ch) {
444 *samps++ = GET16as8(im->idata, off+chans[ch]);
451 if (chan_count <= 0 || chan_count > im->channels) {
452 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
456 for (i = 0; i < w; ++i) {
457 for (ch = 0; ch < chan_count; ++ch) {
458 *samps++ = GET16as8(im->idata, off+ch);
472 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,
473 int const *chans, int chan_count) {
475 i_img_dim count, i, w;
478 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
481 off = (l+y*im->xsize) * im->channels;
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) {
489 i_push_errorf(0, "No channel %d in this image", chans[ch]);
493 for (i = 0; i < w; ++i) {
494 for (ch = 0; ch < chan_count; ++ch) {
495 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
502 if (chan_count <= 0 || chan_count > im->channels) {
503 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
507 for (i = 0; i < w; ++i) {
508 for (ch = 0; ch < chan_count; ++ch) {
509 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
524 i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
525 int const *chans, int chan_count, int bits) {
527 i_img_dim count, i, w;
531 return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits);
534 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
537 off = (l+y*im->xsize) * im->channels;
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) {
545 i_push_errorf(0, "No channel %d in this image", chans[ch]);
549 for (i = 0; i < w; ++i) {
550 for (ch = 0; ch < chan_count; ++ch) {
551 *samps++ = GET16(im->idata, off+chans[ch]);
558 if (chan_count <= 0 || chan_count > im->channels) {
559 i_push_error(0, "Invalid channel count");
562 for (i = 0; i < w; ++i) {
563 for (ch = 0; ch < chan_count; ++ch) {
564 *samps++ = GET16(im->idata, off+ch);
574 i_push_error(0, "Image position outside of image");
580 i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps,
581 int const *chans, int chan_count, int bits) {
583 i_img_dim count, i, w;
587 i_push_error(0, "Invalid bits for 16-bit image");
591 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
594 off = (l+y*im->xsize) * im->channels;
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) {
602 i_push_errorf(0, "No channel %d in this image", chans[ch]);
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);
617 if (chan_count <= 0 || chan_count > im->channels) {
618 i_push_error(0, "Invalid channel count");
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);
635 i_push_error(0, "Image position outside of image");
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)
643 Writes sample values to im for the horizontal line (l, y) to (r-1,y)
644 for the channels specified by chans, an array of int with chan_count
647 Returns the number of samples written (which should be (r-l) *
655 i_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) {
658 i_img_dim count, i, w;
660 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
664 offset = (l+y*im->xsize) * im->channels;
669 /* make sure we have good channel numbers */
670 /* and test if all channels specified are in the mask */
672 for (ch = 0; ch < chan_count; ++ch) {
673 if (chans[ch] < 0 || chans[ch] >= im->channels) {
674 i_push_errorf(0, "No channel %d in this image", chans[ch]);
677 if (!((1 << chans[ch]) & im->ch_mask))
681 for (i = 0; i < w; ++i) {
682 for (ch = 0; ch < chan_count; ++ch) {
683 STORE8as16(im->idata, offset + chans[ch], *samps);
687 offset += im->channels;
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);
698 offset += im->channels;
703 if (chan_count <= 0 || chan_count > im->channels) {
704 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
708 for (i = 0; i < w; ++i) {
710 for (ch = 0; ch < chan_count; ++ch) {
711 if (im->ch_mask & mask)
712 STORE8as16(im->idata, offset + ch, *samps);
717 offset += im->channels;
724 i_push_error(0, "Image position outside of image");
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)
732 Writes sample values to im for the horizontal line (l, y) to (r-1,y)
733 for the channels specified by chans, an array of int with chan_count
736 Returns the number of samples written (which should be (r-l) *
744 i_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) {
747 i_img_dim count, i, w;
749 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
753 offset = (l+y*im->xsize) * im->channels;
758 /* make sure we have good channel numbers */
759 /* and test if all channels specified are in the mask */
761 for (ch = 0; ch < chan_count; ++ch) {
762 if (chans[ch] < 0 || chans[ch] >= im->channels) {
763 i_push_errorf(0, "No channel %d in this image", chans[ch]);
766 if (!((1 << chans[ch]) & im->ch_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);
777 offset += im->channels;
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);
790 offset += im->channels;
795 if (chan_count <= 0 || chan_count > im->channels) {
796 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
800 for (i = 0; i < w; ++i) {
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);
811 offset += im->channels;
818 i_push_error(0, "Image position outside of image");
828 Tony Cook <tony@develop-help.com>