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, const 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, const i_color *vals);
30 static int i_ppixf_d16(i_img *im, int x, int y, const 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, const 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_low(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);
192 =item i_img_16_new(x, y, ch)
194 =category Image creation/destruction
195 =synopsis i_img *img = i_img_16_new(width, height, channels);
197 Create a new 16-bit/sample image.
199 Returns the image on success, or NULL on failure.
204 i_img *i_img_16_new(int x, int y, int ch) {
209 im = mymalloc(sizeof(i_img));
211 if (!i_img_16_new_low(im, x, y, ch)) {
217 mm_log((1, "(%p) <- i_img_16_new\n", im));
223 =item i_img_to_rgb16(im)
225 =category Image creation
227 Returns a 16-bit/sample version of the supplied image.
229 Returns the image on success, or NULL on failure.
235 i_img_to_rgb16(i_img *im) {
240 targ = i_img_16_new(im->xsize, im->ysize, im->channels);
243 line = mymalloc(sizeof(i_fcolor) * im->xsize);
244 for (y = 0; y < im->ysize; ++y) {
245 i_glinf(im, 0, im->xsize, y, line);
246 i_plinf(targ, 0, im->xsize, y, line);
254 static int i_ppix_d16(i_img *im, int x, int y, const i_color *val) {
257 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
260 off = (x + y * im->xsize) * im->channels;
261 if (I_ALL_CHANNELS_WRITABLE(im)) {
262 for (ch = 0; ch < im->channels; ++ch)
263 STORE8as16(im->idata, off+ch, val->channel[ch]);
266 for (ch = 0; ch < im->channels; ++ch)
267 if (im->ch_mask & (1 << ch))
268 STORE8as16(im->idata, off+ch, val->channel[ch]);
274 static int i_gpix_d16(i_img *im, int x, int y, i_color *val) {
277 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
280 off = (x + y * im->xsize) * im->channels;
281 for (ch = 0; ch < im->channels; ++ch)
282 val->channel[ch] = GET16as8(im->idata, off+ch);
287 static int i_ppixf_d16(i_img *im, int x, int y, const i_fcolor *val) {
290 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
293 off = (x + y * im->xsize) * im->channels;
294 if (I_ALL_CHANNELS_WRITABLE(im)) {
295 for (ch = 0; ch < im->channels; ++ch)
296 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
299 for (ch = 0; ch < im->channels; ++ch)
300 if (im->ch_mask & (1 << ch))
301 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
307 static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) {
310 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
313 off = (x + y * im->xsize) * im->channels;
314 for (ch = 0; ch < im->channels; ++ch)
315 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
320 static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) {
323 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
326 off = (l+y*im->xsize) * im->channels;
328 for (i = 0; i < count; ++i) {
329 for (ch = 0; ch < im->channels; ++ch) {
330 vals[i].channel[ch] = GET16as8(im->idata, off);
341 static int i_plin_d16(i_img *im, int l, int r, int y, const i_color *vals) {
344 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
347 off = (l+y*im->xsize) * im->channels;
349 if (I_ALL_CHANNELS_WRITABLE(im)) {
350 for (i = 0; i < count; ++i) {
351 for (ch = 0; ch < im->channels; ++ch) {
352 STORE8as16(im->idata, off, vals[i].channel[ch]);
358 for (i = 0; i < count; ++i) {
359 for (ch = 0; ch < im->channels; ++ch) {
360 if (im->ch_mask & (1 << ch))
361 STORE8as16(im->idata, off, vals[i].channel[ch]);
373 static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
376 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
379 off = (l+y*im->xsize) * im->channels;
381 for (i = 0; i < count; ++i) {
382 for (ch = 0; ch < im->channels; ++ch) {
383 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
394 static int i_plinf_d16(i_img *im, int l, int r, int y, const i_fcolor *vals) {
397 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
400 off = (l+y*im->xsize) * im->channels;
402 if (I_ALL_CHANNELS_WRITABLE(im)) {
403 for (i = 0; i < count; ++i) {
404 for (ch = 0; ch < im->channels; ++ch) {
405 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
411 for (i = 0; i < count; ++i) {
412 for (ch = 0; ch < im->channels; ++ch) {
413 if (im->ch_mask & (1 << ch))
414 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
426 static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_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++ = 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 int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
477 int const *chans, int chan_count) {
481 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
484 off = (l+y*im->xsize) * im->channels;
489 /* make sure we have good channel numbers */
490 for (ch = 0; ch < chan_count; ++ch) {
491 if (chans[ch] < 0 || chans[ch] >= im->channels) {
492 i_push_errorf(0, "No channel %d in this image", chans[ch]);
496 for (i = 0; i < w; ++i) {
497 for (ch = 0; ch < chan_count; ++ch) {
498 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
505 if (chan_count <= 0 || chan_count > im->channels) {
506 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
510 for (i = 0; i < w; ++i) {
511 for (ch = 0; ch < chan_count; ++ch) {
512 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
531 Tony Cook <tony@develop-help.com>