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