]> git.imager.perl.org - imager.git/blob - img16.c
63df6f99d8b1a156d585d2a422b2df165a39efc4
[imager.git] / img16.c
1 /*
2 =head1 NAME
3
4 img16.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
13 Implements 16-bit/sample images.
14
15 This basic implementation is required so that we have some larger 
16 sample image type to work with.
17
18 =over
19
20 =cut
21 */
22
23 #include "image.h"
24 #include "imagei.h"
25
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);
38
39 /*
40 =item IIM_base_16bit_direct
41
42 Base structure used to initialize a 16-bit/sample image.
43
44 Internal.
45
46 =cut
47 */
48 static i_img IIM_base_16bit_direct =
49 {
50   0, /* channels set */
51   0, 0, 0, /* xsize, ysize, bytes */
52   ~0U, /* 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    "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.
89 */
90 #if __STDC_VERSION__ >= 199901L && !defined(OS_dec_osf)
91 /* C99 should define something useful */
92 #include <stdint.h>
93 #ifdef UINT16_MAX
94 typedef 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
103 typedef 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
141 Creates a new 16-bit per sample image.
142
143 =cut
144 */
145 i_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
167 i_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
183 static 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
196 static 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
209 static 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
222 static 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
235 static 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
256 static 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
277 static 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
298 static 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
319 static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps, 
320                        int const *chans, int chan_count) {
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
364 static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps, 
365                         int const *chans, int chan_count) {
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
409 /*
410 =back
411
412 =head1 AUTHOR
413
414 Tony Cook <tony@develop-help.com>
415
416 =head1 SEE ALSO
417
418 Imager(3)
419
420 =cut
421 */