- more information on gif library versions in README and Makefile.PL
[imager.git] / img16.c
CommitLineData
faa9b3e7
TC
1/*
2=head1 NAME
3
4img16.c - implements 16-bit images
5
6=head1 SYNOPSIS
7
8 i_img *im = i_img_16_new(int x, int y, int channels);
9 # use like a normal image
10
11=head1 DESCRIPTION
12
13Implements 16-bit/sample images.
14
15This basic implementation is required so that we have some larger
16sample image type to work with.
17
18=over
19
20=cut
21*/
22
23#include "image.h"
24#include "imagei.h"
25
26static int i_ppix_d16(i_img *im, int x, int y, i_color *val);
27static int i_gpix_d16(i_img *im, int x, int y, i_color *val);
28static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals);
29static int i_plin_d16(i_img *im, int l, int r, int y, i_color *vals);
30static int i_ppixf_d16(i_img *im, int x, int y, i_fcolor *val);
31static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val);
32static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals);
33static int i_plinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals);
34static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
18accb2a 35 int const *chans, int chan_count);
faa9b3e7 36static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
18accb2a 37 int const *chans, int chan_count);
faa9b3e7
TC
38
39/*
40=item IIM_base_16bit_direct
41
42Base structure used to initialize a 16-bit/sample image.
43
44Internal.
45
46=cut
47*/
48static i_img IIM_base_16bit_direct =
49{
50 0, /* channels set */
51 0, 0, 0, /* xsize, ysize, bytes */
9a88a5e6 52 ~0U, /* ch_mask */
faa9b3e7
TC
53 i_16_bits, /* bits */
54 i_direct_type, /* type */
55 0, /* virtual */
56 NULL, /* idata */
57 { 0, 0, NULL }, /* tags */
58 NULL, /* ext_data */
59
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 */
70
71 NULL, /* i_f_gpal */
72 NULL, /* i_f_ppal */
73 NULL, /* i_f_addcolor */
74 NULL, /* i_f_getcolor */
75 NULL, /* i_f_colorcount */
76 NULL, /* i_f_findcolor */
77
78 NULL, /* i_f_destroy */
79};
80
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
83
84 We do assume 8-bit char
26fd367b
TC
85
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.
faa9b3e7 89*/
26fd367b 90#if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
faa9b3e7
TC
91/* C99 should define something useful */
92#include <stdint.h>
93#ifdef UINT16_MAX
94typedef uint16_t i_sample16_t;
95#define GOT16
96#endif
97#endif
98
99/* check out unsigned short */
100#ifndef GOT16
101#include <limits.h>
102#if USHRT_MAX == 65535
103typedef unsigned short i_sample16_t;
104#define GOT16
105#endif
106#endif
107
108#ifdef GOT16
109
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)
119
120#else
121
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))
129
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)
135
136#endif
137
138/*
139=item i_img_16_new(int x, int y, int ch)
140
141Creates a new 16-bit per sample image.
365ea842
TC
142
143=cut
faa9b3e7
TC
144*/
145i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
146 mm_log((1,"i_img_16_new(x %d, y %d, ch %d)\n", x, y, ch));
1501d9b3
TC
147
148 if (x < 1 || y < 1) {
149 i_push_error(0, "Image sizes must be positive");
150 return NULL;
151 }
152 if (ch < 1 || ch > MAXCHANNELS) {
153 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
154 return NULL;
155 }
faa9b3e7
TC
156
157 *im = IIM_base_16bit_direct;
158 i_tags_new(&im->tags);
159 im->xsize = x;
160 im->ysize = y;
161 im->channels = ch;
162 im->bytes = x * y * ch * 2;
163 im->ext_data = NULL;
164 im->idata = mymalloc(im->bytes);
165 if (im->idata) {
166 memset(im->idata, 0, im->bytes);
167 }
168 else {
169 i_tags_destroy(&im->tags);
170 im = NULL;
171 }
172
173 return im;
174}
175
176i_img *i_img_16_new(int x, int y, int ch) {
177 i_img *im;
1501d9b3
TC
178
179 i_clear_error();
faa9b3e7
TC
180
181 im = mymalloc(sizeof(i_img));
182 if (im) {
183 if (!i_img_16_new_low(im, x, y, ch)) {
184 myfree(im);
185 im = NULL;
186 }
187 }
188
189 mm_log((1, "(%p) <- i_img_16_new\n", im));
190
191 return im;
192}
193
194static int i_ppix_d16(i_img *im, int x, int y, i_color *val) {
195 int off, ch;
196
197 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
198 return -1;
199
200 off = (x + y * im->xsize) * im->channels;
201 for (ch = 0; ch < im->channels; ++ch)
202 STORE8as16(im->idata, off+ch, val->channel[ch]);
203
204 return 0;
205}
206
207static int i_gpix_d16(i_img *im, int x, int y, i_color *val) {
208 int off, ch;
209
210 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
211 return -1;
212
213 off = (x + y * im->xsize) * im->channels;
214 for (ch = 0; ch < im->channels; ++ch)
215 val->channel[ch] = GET16as8(im->idata, off+ch);
216
217 return 0;
218}
219
220static int i_ppixf_d16(i_img *im, int x, int y, i_fcolor *val) {
221 int off, ch;
222
223 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
224 return -1;
225
226 off = (x + y * im->xsize) * im->channels;
227 for (ch = 0; ch < im->channels; ++ch)
228 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
229
230 return 0;
231}
232
233static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) {
234 int off, ch;
235
236 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
237 return -1;
238
239 off = (x + y * im->xsize) * im->channels;
240 for (ch = 0; ch < im->channels; ++ch)
241 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
242
243 return 0;
244}
245
246static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) {
247 int ch, count, i;
248 int off;
249 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
250 if (r > im->xsize)
251 r = im->xsize;
252 off = (l+y*im->xsize) * im->channels;
253 count = r - l;
254 for (i = 0; i < count; ++i) {
255 for (ch = 0; ch < im->channels; ++ch) {
256 vals[i].channel[ch] = GET16as8(im->idata, off);
257 ++off;
258 }
259 }
260 return count;
261 }
262 else {
263 return 0;
264 }
265}
266
267static int i_plin_d16(i_img *im, int l, int r, int y, i_color *vals) {
268 int ch, count, i;
269 int off;
270 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
271 if (r > im->xsize)
272 r = im->xsize;
273 off = (l+y*im->xsize) * im->channels;
274 count = r - l;
275 for (i = 0; i < count; ++i) {
276 for (ch = 0; ch < im->channels; ++ch) {
277 STORE8as16(im->idata, off, vals[i].channel[ch]);
278 ++off;
279 }
280 }
281 return count;
282 }
283 else {
284 return 0;
285 }
286}
287
288static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
289 int ch, count, i;
290 int off;
291 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
292 if (r > im->xsize)
293 r = im->xsize;
294 off = (l+y*im->xsize) * im->channels;
295 count = r - l;
296 for (i = 0; i < count; ++i) {
297 for (ch = 0; ch < im->channels; ++ch) {
298 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
299 ++off;
300 }
301 }
302 return count;
303 }
304 else {
305 return 0;
306 }
307}
308
309static int i_plinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
310 int ch, count, i;
311 int off;
312 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
313 if (r > im->xsize)
314 r = im->xsize;
315 off = (l+y*im->xsize) * im->channels;
316 count = r - l;
317 for (i = 0; i < count; ++i) {
318 for (ch = 0; ch < im->channels; ++ch) {
319 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
320 ++off;
321 }
322 }
323 return count;
324 }
325 else {
326 return 0;
327 }
328}
329
330static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
18accb2a 331 int const *chans, int chan_count) {
faa9b3e7
TC
332 int ch, count, i, w;
333 int off;
334
335 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
336 if (r > im->xsize)
337 r = im->xsize;
338 off = (l+y*im->xsize) * im->channels;
339 w = r - l;
340 count = 0;
341
342 if (chans) {
343 /* make sure we have good channel numbers */
344 for (ch = 0; ch < chan_count; ++ch) {
345 if (chans[ch] < 0 || chans[ch] >= im->channels) {
346 i_push_errorf(0, "No channel %d in this image", chans[ch]);
347 return 0;
348 }
349 }
350 for (i = 0; i < w; ++i) {
351 for (ch = 0; ch < chan_count; ++ch) {
352 *samps++ = GET16as8(im->idata, off+chans[ch]);
353 ++count;
354 }
355 off += im->channels;
356 }
357 }
358 else {
359 for (i = 0; i < w; ++i) {
360 for (ch = 0; ch < chan_count; ++ch) {
361 *samps++ = GET16as8(im->idata, off+ch);
362 ++count;
363 }
364 off += im->channels;
365 }
366 }
367
368 return count;
369 }
370 else {
371 return 0;
372 }
373}
374
375static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
18accb2a 376 int const *chans, int chan_count) {
faa9b3e7
TC
377 int ch, count, i, w;
378 int off;
379
380 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
381 if (r > im->xsize)
382 r = im->xsize;
383 off = (l+y*im->xsize) * im->channels;
384 w = r - l;
385 count = 0;
386
387 if (chans) {
388 /* make sure we have good channel numbers */
389 for (ch = 0; ch < chan_count; ++ch) {
390 if (chans[ch] < 0 || chans[ch] >= im->channels) {
391 i_push_errorf(0, "No channel %d in this image", chans[ch]);
392 return 0;
393 }
394 }
395 for (i = 0; i < w; ++i) {
396 for (ch = 0; ch < chan_count; ++ch) {
397 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
398 ++count;
399 }
400 off += im->channels;
401 }
402 }
403 else {
404 for (i = 0; i < w; ++i) {
405 for (ch = 0; ch < chan_count; ++ch) {
406 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
407 ++count;
408 }
409 off += im->channels;
410 }
411 }
412
413 return count;
414 }
415 else {
416 return 0;
417 }
418}
419
b8c2033e
AMH
420/*
421=back
422
423=head1 AUTHOR
424
425Tony Cook <tony@develop-help.com>
426
427=head1 SEE ALSO
428
429Imager(3)
430
431=cut
432*/