]> git.imager.perl.org - imager.git/blame - img16.c
Modified i_line_aa to use a modified bresenham algorithm. This method
[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));
147
148 *im = IIM_base_16bit_direct;
149 i_tags_new(&im->tags);
150 im->xsize = x;
151 im->ysize = y;
152 im->channels = ch;
153 im->bytes = x * y * ch * 2;
154 im->ext_data = NULL;
155 im->idata = mymalloc(im->bytes);
156 if (im->idata) {
157 memset(im->idata, 0, im->bytes);
158 }
159 else {
160 i_tags_destroy(&im->tags);
161 im = NULL;
162 }
163
164 return im;
165}
166
167i_img *i_img_16_new(int x, int y, int ch) {
168 i_img *im;
169
170 im = mymalloc(sizeof(i_img));
171 if (im) {
172 if (!i_img_16_new_low(im, x, y, ch)) {
173 myfree(im);
174 im = NULL;
175 }
176 }
177
178 mm_log((1, "(%p) <- i_img_16_new\n", im));
179
180 return im;
181}
182
183static int i_ppix_d16(i_img *im, int x, int y, i_color *val) {
184 int off, ch;
185
186 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
187 return -1;
188
189 off = (x + y * im->xsize) * im->channels;
190 for (ch = 0; ch < im->channels; ++ch)
191 STORE8as16(im->idata, off+ch, val->channel[ch]);
192
193 return 0;
194}
195
196static int i_gpix_d16(i_img *im, int x, int y, i_color *val) {
197 int off, ch;
198
199 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
200 return -1;
201
202 off = (x + y * im->xsize) * im->channels;
203 for (ch = 0; ch < im->channels; ++ch)
204 val->channel[ch] = GET16as8(im->idata, off+ch);
205
206 return 0;
207}
208
209static int i_ppixf_d16(i_img *im, int x, int y, i_fcolor *val) {
210 int off, ch;
211
212 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
213 return -1;
214
215 off = (x + y * im->xsize) * im->channels;
216 for (ch = 0; ch < im->channels; ++ch)
217 STORE16(im->idata, off+ch, SampleFTo16(val->channel[ch]));
218
219 return 0;
220}
221
222static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) {
223 int off, ch;
224
225 if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize)
226 return -1;
227
228 off = (x + y * im->xsize) * im->channels;
229 for (ch = 0; ch < im->channels; ++ch)
230 val->channel[ch] = Sample16ToF(GET16(im->idata, off+ch));
231
232 return 0;
233}
234
235static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) {
236 int ch, count, i;
237 int off;
238 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
239 if (r > im->xsize)
240 r = im->xsize;
241 off = (l+y*im->xsize) * im->channels;
242 count = r - l;
243 for (i = 0; i < count; ++i) {
244 for (ch = 0; ch < im->channels; ++ch) {
245 vals[i].channel[ch] = GET16as8(im->idata, off);
246 ++off;
247 }
248 }
249 return count;
250 }
251 else {
252 return 0;
253 }
254}
255
256static int i_plin_d16(i_img *im, int l, int r, int y, i_color *vals) {
257 int ch, count, i;
258 int off;
259 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
260 if (r > im->xsize)
261 r = im->xsize;
262 off = (l+y*im->xsize) * im->channels;
263 count = r - l;
264 for (i = 0; i < count; ++i) {
265 for (ch = 0; ch < im->channels; ++ch) {
266 STORE8as16(im->idata, off, vals[i].channel[ch]);
267 ++off;
268 }
269 }
270 return count;
271 }
272 else {
273 return 0;
274 }
275}
276
277static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
278 int ch, count, i;
279 int off;
280 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
281 if (r > im->xsize)
282 r = im->xsize;
283 off = (l+y*im->xsize) * im->channels;
284 count = r - l;
285 for (i = 0; i < count; ++i) {
286 for (ch = 0; ch < im->channels; ++ch) {
287 vals[i].channel[ch] = Sample16ToF(GET16(im->idata, off));
288 ++off;
289 }
290 }
291 return count;
292 }
293 else {
294 return 0;
295 }
296}
297
298static int i_plinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) {
299 int ch, count, i;
300 int off;
301 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
302 if (r > im->xsize)
303 r = im->xsize;
304 off = (l+y*im->xsize) * im->channels;
305 count = r - l;
306 for (i = 0; i < count; ++i) {
307 for (ch = 0; ch < im->channels; ++ch) {
308 STORE16(im->idata, off, SampleFTo16(vals[i].channel[ch]));
309 ++off;
310 }
311 }
312 return count;
313 }
314 else {
315 return 0;
316 }
317}
318
319static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
18accb2a 320 int const *chans, int chan_count) {
faa9b3e7
TC
321 int ch, count, i, w;
322 int off;
323
324 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
325 if (r > im->xsize)
326 r = im->xsize;
327 off = (l+y*im->xsize) * im->channels;
328 w = r - l;
329 count = 0;
330
331 if (chans) {
332 /* make sure we have good channel numbers */
333 for (ch = 0; ch < chan_count; ++ch) {
334 if (chans[ch] < 0 || chans[ch] >= im->channels) {
335 i_push_errorf(0, "No channel %d in this image", chans[ch]);
336 return 0;
337 }
338 }
339 for (i = 0; i < w; ++i) {
340 for (ch = 0; ch < chan_count; ++ch) {
341 *samps++ = GET16as8(im->idata, off+chans[ch]);
342 ++count;
343 }
344 off += im->channels;
345 }
346 }
347 else {
348 for (i = 0; i < w; ++i) {
349 for (ch = 0; ch < chan_count; ++ch) {
350 *samps++ = GET16as8(im->idata, off+ch);
351 ++count;
352 }
353 off += im->channels;
354 }
355 }
356
357 return count;
358 }
359 else {
360 return 0;
361 }
362}
363
364static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps,
18accb2a 365 int const *chans, int chan_count) {
faa9b3e7
TC
366 int ch, count, i, w;
367 int off;
368
369 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
370 if (r > im->xsize)
371 r = im->xsize;
372 off = (l+y*im->xsize) * im->channels;
373 w = r - l;
374 count = 0;
375
376 if (chans) {
377 /* make sure we have good channel numbers */
378 for (ch = 0; ch < chan_count; ++ch) {
379 if (chans[ch] < 0 || chans[ch] >= im->channels) {
380 i_push_errorf(0, "No channel %d in this image", chans[ch]);
381 return 0;
382 }
383 }
384 for (i = 0; i < w; ++i) {
385 for (ch = 0; ch < chan_count; ++ch) {
386 *samps++ = Sample16ToF(GET16(im->idata, off+chans[ch]));
387 ++count;
388 }
389 off += im->channels;
390 }
391 }
392 else {
393 for (i = 0; i < w; ++i) {
394 for (ch = 0; ch < chan_count; ++ch) {
395 *samps++ = Sample16ToF(GET16(im->idata, off+ch));
396 ++count;
397 }
398 off += im->channels;
399 }
400 }
401
402 return count;
403 }
404 else {
405 return 0;
406 }
407}
408
b8c2033e
AMH
409/*
410=back
411
412=head1 AUTHOR
413
414Tony Cook <tony@develop-help.com>
415
416=head1 SEE ALSO
417
418Imager(3)
419
420=cut
421*/