Updated Changes file for recent diffs
[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,
35 int *chans, int chan_count);
36static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
37 int *chans, int chan_count);
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 */
52 ~0, /* ch_mask */
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
85*/
86#if __STDC_VERSION__ >= 199901L
87/* C99 should define something useful */
88#include <stdint.h>
89#ifdef UINT16_MAX
90typedef uint16_t i_sample16_t;
91#define GOT16
92#endif
93#endif
94
95/* check out unsigned short */
96#ifndef GOT16
97#include <limits.h>
98#if USHRT_MAX == 65535
99typedef unsigned short i_sample16_t;
100#define GOT16
101#endif
102#endif
103
104#ifdef GOT16
105
106/* we have a real 16-bit unsigned integer */
107#define STORE16(bytes, offset, word) \
108 (((i_sample16_t *)(bytes))[offset] = (word))
109#define STORE8as16(bytes, offset, byte) \
110 (((i_sample16_t *)(bytes))[offset] = (byte) * 256)
111#define GET16(bytes, offset) \
112 (((i_sample16_t *)(bytes))[offset])
113#define GET16as8(bytes, offset) \
114 (((i_sample16_t *)(bytes))[offset] / 256)
115
116#else
117
118/* we have to do this the hard way */
119#define STORE16(bytes, offset, word) \
120 ((((unsigned char *)(bytes))[(offset)*2] = (word) >> 8), \
121 (((unsigned char *)(bytes))[(offset)*2+1] = (word) & 0xFF))
122#define STORE8as16(bytes, offset, byte) \
123 ((((unsigned char *)(bytes))[(offset)*2] = (byte)), \
124 (((unsigned char *)(bytes))[(offset)*2+1] = 0))
125
126#define GET16(bytes, offset) \
127 (((unsigned char *)(bytes))[(offset)*2] * 256 \
128 + ((unsigned char *)(bytes))[(offset)*2+1])
129#define GET16as8(bytes, offset) \
130 (((unsigned char *)(bytes))[(offset)*2] << 8)
131
132#endif
133
134/*
135=item i_img_16_new(int x, int y, int ch)
136
137Creates a new 16-bit per sample image.
138*/
139i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
140 mm_log((1,"i_img_16_new(x %d, y %d, ch %d)\n", x, y, ch));
141
142 *im = IIM_base_16bit_direct;
143 i_tags_new(&im->tags);
144 im->xsize = x;
145 im->ysize = y;
146 im->channels = ch;
147 im->bytes = x * y * ch * 2;
148 im->ext_data = NULL;
149 im->idata = mymalloc(im->bytes);
150 if (im->idata) {
151 memset(im->idata, 0, im->bytes);
152 }
153 else {
154 i_tags_destroy(&im->tags);
155 im = NULL;
156 }
157
158 return im;
159}
160
161i_img *i_img_16_new(int x, int y, int ch) {
162 i_img *im;
163
164 im = mymalloc(sizeof(i_img));
165 if (im) {
166 if (!i_img_16_new_low(im, x, y, ch)) {
167 myfree(im);
168 im = NULL;
169 }
170 }
171
172 mm_log((1, "(%p) <- i_img_16_new\n", im));
173
174 return im;
175}
176
177static int i_ppix_d16(i_img *im, int x, int y, i_color *val) {
178 int off, ch;
179
180 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
181 return -1;
182
183 off = (x + y * im->xsize) * im->channels;
184 for (ch = 0; ch < im->channels; ++ch)
185 STORE8as16(im->idata, off+ch, val->channel[ch]);
186
187 return 0;
188}
189
190static int i_gpix_d16(i_img *im, int x, int y, i_color *val) {
191 int off, ch;
192
193 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
194 return -1;
195
196 off = (x + y * im->xsize) * im->channels;
197 for (ch = 0; ch < im->channels; ++ch)
198 val->channel[ch] = GET16as8(im->idata, off+ch);
199
200 return 0;
201}
202
203static int i_ppixf_d16(i_img *im, int x, int y, i_fcolor *val) {
204 int off, ch;
205
206 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
207 return -1;
208
209 off = (x + y * im->xsize) * im->channels;
210 for (ch = 0; ch < im->channels; ++ch)
211 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
212
213 return 0;
214}
215
216static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) {
217 int off, ch;
218
219 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
220 return -1;
221
222 off = (x + y * im->xsize) * im->channels;
223 for (ch = 0; ch < im->channels; ++ch)
224 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
225
226 return 0;
227}
228
229static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) {
230 int ch, count, i;
231 int off;
232 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
233 if (r > im->xsize)
234 r = im->xsize;
235 off = (l+y*im->xsize) * im->channels;
236 count = r - l;
237 for (i = 0; i < count; ++i) {
238 for (ch = 0; ch < im->channels; ++ch) {
239 vals[i].channel[ch] = GET16as8(im->idata, off);
240 ++off;
241 }
242 }
243 return count;
244 }
245 else {
246 return 0;
247 }
248}
249
250static int i_plin_d16(i_img *im, int l, int r, int y, i_color *vals) {
251 int ch, count, i;
252 int off;
253 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
254 if (r > im->xsize)
255 r = im->xsize;
256 off = (l+y*im->xsize) * im->channels;
257 count = r - l;
258 for (i = 0; i < count; ++i) {
259 for (ch = 0; ch < im->channels; ++ch) {
260 STORE8as16(im->idata, off, vals[i].channel[ch]);
261 ++off;
262 }
263 }
264 return count;
265 }
266 else {
267 return 0;
268 }
269}
270
271static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
272 int ch, count, i;
273 int off;
274 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
275 if (r > im->xsize)
276 r = im->xsize;
277 off = (l+y*im->xsize) * im->channels;
278 count = r - l;
279 for (i = 0; i < count; ++i) {
280 for (ch = 0; ch < im->channels; ++ch) {
281 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
282 ++off;
283 }
284 }
285 return count;
286 }
287 else {
288 return 0;
289 }
290}
291
292static int i_plinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
293 int ch, count, i;
294 int off;
295 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
296 if (r > im->xsize)
297 r = im->xsize;
298 off = (l+y*im->xsize) * im->channels;
299 count = r - l;
300 for (i = 0; i < count; ++i) {
301 for (ch = 0; ch < im->channels; ++ch) {
302 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
303 ++off;
304 }
305 }
306 return count;
307 }
308 else {
309 return 0;
310 }
311}
312
313static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
314 int *chans, int chan_count) {
315 int ch, count, i, w;
316 int off;
317
318 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
319 if (r > im->xsize)
320 r = im->xsize;
321 off = (l+y*im->xsize) * im->channels;
322 w = r - l;
323 count = 0;
324
325 if (chans) {
326 /* make sure we have good channel numbers */
327 for (ch = 0; ch < chan_count; ++ch) {
328 if (chans[ch] < 0 || chans[ch] >= im->channels) {
329 i_push_errorf(0, "No channel %d in this image", chans[ch]);
330 return 0;
331 }
332 }
333 for (i = 0; i < w; ++i) {
334 for (ch = 0; ch < chan_count; ++ch) {
335 *samps++ = GET16as8(im->idata, off+chans[ch]);
336 ++count;
337 }
338 off += im->channels;
339 }
340 }
341 else {
342 for (i = 0; i < w; ++i) {
343 for (ch = 0; ch < chan_count; ++ch) {
344 *samps++ = GET16as8(im->idata, off+ch);
345 ++count;
346 }
347 off += im->channels;
348 }
349 }
350
351 return count;
352 }
353 else {
354 return 0;
355 }
356}
357
358static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
359 int *chans, int chan_count) {
360 int ch, count, i, w;
361 int off;
362
363 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
364 if (r > im->xsize)
365 r = im->xsize;
366 off = (l+y*im->xsize) * im->channels;
367 w = r - l;
368 count = 0;
369
370 if (chans) {
371 /* make sure we have good channel numbers */
372 for (ch = 0; ch < chan_count; ++ch) {
373 if (chans[ch] < 0 || chans[ch] >= im->channels) {
374 i_push_errorf(0, "No channel %d in this image", chans[ch]);
375 return 0;
376 }
377 }
378 for (i = 0; i < w; ++i) {
379 for (ch = 0; ch < chan_count; ++ch) {
380 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
381 ++count;
382 }
383 off += im->channels;
384 }
385 }
386 else {
387 for (i = 0; i < w; ++i) {
388 for (ch = 0; ch < chan_count; ++ch) {
389 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
390 ++count;
391 }
392 off += im->channels;
393 }
394 }
395
396 return count;
397 }
398 else {
399 return 0;
400 }
401}
402