4 img16.c - implements 16-bit images
8 i_img *im = i_img_16_new(int x, int 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, int x, int y, i_color *val);
27 static int i_gpix_d16(i_img *im, int x, int y, i_color *val);
28 static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals);
29 static int i_plin_d16(i_img *im, int l, int r, int y, i_color *vals);
30 static int i_ppixf_d16(i_img *im, int x, int y, i_fcolor *val);
31 static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val);
32 static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals);
33 static int i_plinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals);
34 static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
35 int const *chans, int chan_count);
36 static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
37 int const *chans, int chan_count);
40 =item IIM_base_16bit_direct
42 Base structure used to initialize a 16-bit/sample image.
48 static i_img IIM_base_16bit_direct =
51 0, 0, 0, /* xsize, ysize, bytes */
54 i_direct_type, /* type */
57 { 0, 0, NULL }, /* tags */
60 i_ppix_d16, /* i_f_ppix */
61 i_ppixf_d16, /* i_f_ppixf */
62 i_plin_d16, /* i_f_plin */
63 i_plinf_d16, /* i_f_plinf */
64 i_gpix_d16, /* i_f_gpix */
65 i_gpixf_d16, /* i_f_gpixf */
66 i_glin_d16, /* i_f_glin */
67 i_glinf_d16, /* i_f_glinf */
68 i_gsamp_d16, /* i_f_gsamp */
69 i_gsampf_d16, /* i_f_gsampf */
73 NULL, /* i_f_addcolor */
74 NULL, /* i_f_getcolor */
75 NULL, /* i_f_colorcount */
76 NULL, /* i_f_findcolor */
78 NULL, /* i_f_destroy */
81 /* it's possible some platforms won't have a 16-bit integer type,
82 so we check for one otherwise we work by bytes directly
84 We do assume 8-bit char
86 "Compaq C V6.4-009 on Compaq Tru64 UNIX V5.1A (Rev. 1885)" says it
87 supports C99, but doesn't supply stdint.h, which is required for
88 both hosted and freestanding implementations. So guard against it.
90 #if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
91 /* C99 should define something useful */
94 typedef uint16_t i_sample16_t;
99 /* check out unsigned short */
102 #if USHRT_MAX == 65535
103 typedef unsigned short i_sample16_t;
110 /* we have a real 16-bit unsigned integer */
111 #define STORE16(bytes, offset, word) \
112 (((i_sample16_t *)(bytes))[offset] = (word))
113 #define STORE8as16(bytes, offset, byte) \
114 (((i_sample16_t *)(bytes))[offset] = (byte) * 256)
115 #define GET16(bytes, offset) \
116 (((i_sample16_t *)(bytes))[offset])
117 #define GET16as8(bytes, offset) \
118 (((i_sample16_t *)(bytes))[offset] / 256)
122 /* we have to do this the hard way */
123 #define STORE16(bytes, offset, word) \
124 ((((unsigned char *)(bytes))[(offset)*2] = (word) >> 8), \
125 (((unsigned char *)(bytes))[(offset)*2+1] = (word) & 0xFF))
126 #define STORE8as16(bytes, offset, byte) \
127 ((((unsigned char *)(bytes))[(offset)*2] = (byte)), \
128 (((unsigned char *)(bytes))[(offset)*2+1] = 0))
130 #define GET16(bytes, offset) \
131 (((unsigned char *)(bytes))[(offset)*2] * 256 \
132 + ((unsigned char *)(bytes))[(offset)*2+1])
133 #define GET16as8(bytes, offset) \
134 (((unsigned char *)(bytes))[(offset)*2] << 8)
139 =item i_img_16_new(int x, int y, int ch)
141 Creates a new 16-bit per sample image.
145 i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
146 int bytes, line_bytes;
147 mm_log((1,"i_img_16_new(x %d, y %d, ch %d)\n", x, y, ch));
149 if (x < 1 || y < 1) {
150 i_push_error(0, "Image sizes must be positive");
153 if (ch < 1 || ch > MAXCHANNELS) {
154 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
157 bytes = x * y * ch * 2;
158 if (bytes / y / ch / 2 != x) {
159 i_push_errorf(0, "integer overflow calculating image allocation");
163 /* basic assumption: we can always allocate a buffer representing a
164 line from the image, otherwise we're going to have trouble
165 working with the image */
166 line_bytes = sizeof(i_fcolor) * x;
167 if (line_bytes / x != sizeof(i_fcolor)) {
168 i_push_error(0, "integer overflow calculating scanline allocation");
172 *im = IIM_base_16bit_direct;
173 i_tags_new(&im->tags);
179 im->idata = mymalloc(im->bytes);
181 memset(im->idata, 0, im->bytes);
184 i_tags_destroy(&im->tags);
191 i_img *i_img_16_new(int x, int y, int ch) {
196 im = mymalloc(sizeof(i_img));
198 if (!i_img_16_new_low(im, x, y, ch)) {
204 mm_log((1, "(%p) <- i_img_16_new\n", im));
209 static int i_ppix_d16(i_img *im, int x, int y, i_color *val) {
212 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
215 off = (x + y * im->xsize) * im->channels;
216 if (I_ALL_CHANNELS_WRITABLE(im)) {
217 for (ch = 0; ch < im->channels; ++ch)
218 STORE8as16(im->idata, off+ch, val->channel[ch]);
221 for (ch = 0; ch < im->channels; ++ch)
222 if (im->ch_mask & (1 << ch))
223 STORE8as16(im->idata, off+ch, val->channel[ch]);
229 static int i_gpix_d16(i_img *im, int x, int y, i_color *val) {
232 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
235 off = (x + y * im->xsize) * im->channels;
236 for (ch = 0; ch < im->channels; ++ch)
237 val->channel[ch] = GET16as8(im->idata, off+ch);
242 static int i_ppixf_d16(i_img *im, int x, int y, i_fcolor *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 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
254 for (ch = 0; ch < im->channels; ++ch)
255 if (im->ch_mask & (1 << ch))
256 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
262 static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) {
265 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
268 off = (x + y * im->xsize) * im->channels;
269 for (ch = 0; ch < im->channels; ++ch)
270 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
275 static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) {
278 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
281 off = (l+y*im->xsize) * im->channels;
283 for (i = 0; i < count; ++i) {
284 for (ch = 0; ch < im->channels; ++ch) {
285 vals[i].channel[ch] = GET16as8(im->idata, off);
296 static int i_plin_d16(i_img *im, int l, int r, int y, i_color *vals) {
299 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
302 off = (l+y*im->xsize) * im->channels;
304 if (I_ALL_CHANNELS_WRITABLE(im)) {
305 for (i = 0; i < count; ++i) {
306 for (ch = 0; ch < im->channels; ++ch) {
307 STORE8as16(im->idata, off, vals[i].channel[ch]);
313 for (i = 0; i < count; ++i) {
314 for (ch = 0; ch < im->channels; ++ch) {
315 if (im->ch_mask & (1 << ch))
316 STORE8as16(im->idata, off, vals[i].channel[ch]);
328 static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
331 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
334 off = (l+y*im->xsize) * im->channels;
336 for (i = 0; i < count; ++i) {
337 for (ch = 0; ch < im->channels; ++ch) {
338 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
349 static int i_plinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
352 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
355 off = (l+y*im->xsize) * im->channels;
357 if (I_ALL_CHANNELS_WRITABLE(im)) {
358 for (i = 0; i < count; ++i) {
359 for (ch = 0; ch < im->channels; ++ch) {
360 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
366 for (i = 0; i < count; ++i) {
367 for (ch = 0; ch < im->channels; ++ch) {
368 if (im->ch_mask & (1 << ch))
369 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
381 static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
382 int const *chans, int chan_count) {
386 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
389 off = (l+y*im->xsize) * im->channels;
394 /* make sure we have good channel numbers */
395 for (ch = 0; ch < chan_count; ++ch) {
396 if (chans[ch] < 0 || chans[ch] >= im->channels) {
397 i_push_errorf(0, "No channel %d in this image", chans[ch]);
401 for (i = 0; i < w; ++i) {
402 for (ch = 0; ch < chan_count; ++ch) {
403 *samps++ = GET16as8(im->idata, off+chans[ch]);
410 for (i = 0; i < w; ++i) {
411 for (ch = 0; ch < chan_count; ++ch) {
412 *samps++ = GET16as8(im->idata, off+ch);
426 static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
427 int const *chans, int chan_count) {
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++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
455 for (i = 0; i < w; ++i) {
456 for (ch = 0; ch < chan_count; ++ch) {
457 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
476 Tony Cook <tony@develop-help.com>