planning too far ahead
[imager.git] / imgdouble.c
CommitLineData
2ce44e2a
TC
1/*
2=head1 NAME
3
4imgdouble.c - implements double per sample images
5
6=head1 SYNOPSIS
7
8 i_img *im = i_img_double_new(int x, int y, int channels);
9 # use like a normal image
10
11=head1 DESCRIPTION
12
13Implements double/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
92bda632
TC
23#include "imager.h"
24#include "imageri.h"
2ce44e2a 25
97ac0a96 26static int i_ppix_ddoub(i_img *im, int x, int y, const i_color *val);
2ce44e2a
TC
27static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val);
28static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals);
97ac0a96
TC
29static int i_plin_ddoub(i_img *im, int l, int r, int y, const i_color *vals);
30static int i_ppixf_ddoub(i_img *im, int x, int y, const i_fcolor *val);
2ce44e2a
TC
31static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val);
32static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals);
97ac0a96 33static int i_plinf_ddoub(i_img *im, int l, int r, int y, const i_fcolor *vals);
2ce44e2a 34static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps,
18accb2a 35 int const *chans, int chan_count);
2ce44e2a 36static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps,
18accb2a 37 int const *chans, int chan_count);
2ce44e2a
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_double_direct =
49{
50 0, /* channels set */
51 0, 0, 0, /* xsize, ysize, bytes */
9a88a5e6 52 ~0U, /* ch_mask */
2ce44e2a
TC
53 i_double_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_ddoub, /* i_f_ppix */
61 i_ppixf_ddoub, /* i_f_ppixf */
62 i_plin_ddoub, /* i_f_plin */
63 i_plinf_ddoub, /* i_f_plinf */
64 i_gpix_ddoub, /* i_f_gpix */
65 i_gpixf_ddoub, /* i_f_gpixf */
66 i_glin_ddoub, /* i_f_glin */
67 i_glinf_ddoub, /* i_f_glinf */
68 i_gsamp_ddoub, /* i_f_gsamp */
69 i_gsampf_ddoub, /* 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/*
82=item i_img_double_new(int x, int y, int ch)
83
9167a5c6
TC
84=category Image creation/destruction
85=synopsis i_img *img = i_img_double_new(width, height, channels);
92bda632 86
2ce44e2a
TC
87Creates a new double per sample image.
88
89=cut
90*/
91i_img *i_img_double_new_low(i_img *im, int x, int y, int ch) {
653ea321
TC
92 int bytes;
93
2ce44e2a 94 mm_log((1,"i_img_double_new(x %d, y %d, ch %d)\n", x, y, ch));
1501d9b3
TC
95
96 if (x < 1 || y < 1) {
97 i_push_error(0, "Image sizes must be positive");
98 return NULL;
99 }
100 if (ch < 1 || ch > MAXCHANNELS) {
101 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
102 return NULL;
103 }
653ea321
TC
104 bytes = x * y * ch * sizeof(double);
105 if (bytes / y / ch / sizeof(double) != x) {
106 i_push_errorf(0, "integer overflow calculating image allocation");
107 return NULL;
108 }
2ce44e2a
TC
109
110 *im = IIM_base_double_direct;
111 i_tags_new(&im->tags);
112 im->xsize = x;
113 im->ysize = y;
114 im->channels = ch;
653ea321 115 im->bytes = bytes;
2ce44e2a
TC
116 im->ext_data = NULL;
117 im->idata = mymalloc(im->bytes);
118 if (im->idata) {
119 memset(im->idata, 0, im->bytes);
120 }
121 else {
122 i_tags_destroy(&im->tags);
123 im = NULL;
124 }
125
126 return im;
127}
128
129i_img *i_img_double_new(int x, int y, int ch) {
130 i_img *im;
131
1501d9b3
TC
132 i_clear_error();
133
2ce44e2a
TC
134 im = mymalloc(sizeof(i_img));
135 if (im) {
136 if (!i_img_double_new_low(im, x, y, ch)) {
137 myfree(im);
138 im = NULL;
139 }
140 }
141
142 mm_log((1, "(%p) <- i_img_double_new\n", im));
143
144 return im;
145}
146
97ac0a96 147static int i_ppix_ddoub(i_img *im, int x, int y, const i_color *val) {
2ce44e2a
TC
148 int off, ch;
149
837a4b43 150 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
151 return -1;
152
153 off = (x + y * im->xsize) * im->channels;
35f40526
TC
154 if (I_ALL_CHANNELS_WRITABLE(im)) {
155 for (ch = 0; ch < im->channels; ++ch)
156 ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
157 }
158 else {
159 for (ch = 0; ch < im->channels; ++ch)
160 if (im->ch_mask & (1<<ch))
161 ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
162 }
2ce44e2a
TC
163
164 return 0;
165}
166
167static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val) {
168 int off, ch;
169
837a4b43 170 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
171 return -1;
172
173 off = (x + y * im->xsize) * im->channels;
174 for (ch = 0; ch < im->channels; ++ch)
175 val->channel[ch] = SampleFTo8(((double *)im->idata)[off+ch]);
176
177 return 0;
178}
179
97ac0a96 180static int i_ppixf_ddoub(i_img *im, int x, int y, const i_fcolor *val) {
2ce44e2a
TC
181 int off, ch;
182
837a4b43 183 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
184 return -1;
185
186 off = (x + y * im->xsize) * im->channels;
35f40526
TC
187 if (I_ALL_CHANNELS_WRITABLE(im)) {
188 for (ch = 0; ch < im->channels; ++ch)
189 ((double *)im->idata)[off+ch] = val->channel[ch];
190 }
191 else {
192 for (ch = 0; ch < im->channels; ++ch)
193 if (im->ch_mask & (1 << ch))
194 ((double *)im->idata)[off+ch] = val->channel[ch];
195 }
2ce44e2a
TC
196
197 return 0;
198}
199
200static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val) {
201 int off, ch;
202
837a4b43 203 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
204 return -1;
205
206 off = (x + y * im->xsize) * im->channels;
207 for (ch = 0; ch < im->channels; ++ch)
208 val->channel[ch] = ((double *)im->idata)[off+ch];
209
210 return 0;
211}
212
213static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals) {
214 int ch, count, i;
215 int off;
216 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
217 if (r > im->xsize)
218 r = im->xsize;
219 off = (l+y*im->xsize) * im->channels;
220 count = r - l;
221 for (i = 0; i < count; ++i) {
222 for (ch = 0; ch < im->channels; ++ch) {
223 vals[i].channel[ch] = SampleFTo8(((double *)im->idata)[off]);
224 ++off;
225 }
226 }
227 return count;
228 }
229 else {
230 return 0;
231 }
232}
233
97ac0a96 234static int i_plin_ddoub(i_img *im, int l, int r, int y, const i_color *vals) {
2ce44e2a
TC
235 int ch, count, i;
236 int off;
237 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
238 if (r > im->xsize)
239 r = im->xsize;
240 off = (l+y*im->xsize) * im->channels;
241 count = r - l;
35f40526
TC
242 if (I_ALL_CHANNELS_WRITABLE(im)) {
243 for (i = 0; i < count; ++i) {
244 for (ch = 0; ch < im->channels; ++ch) {
245 ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
246 ++off;
247 }
248 }
249 }
250 else {
251 for (i = 0; i < count; ++i) {
252 for (ch = 0; ch < im->channels; ++ch) {
253 if (im->ch_mask & (1 << ch))
254 ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
255 ++off;
256 }
2ce44e2a
TC
257 }
258 }
259 return count;
260 }
261 else {
262 return 0;
263 }
264}
265
266static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) {
267 int ch, count, i;
268 int off;
269 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
270 if (r > im->xsize)
271 r = im->xsize;
272 off = (l+y*im->xsize) * im->channels;
273 count = r - l;
274 for (i = 0; i < count; ++i) {
275 for (ch = 0; ch < im->channels; ++ch) {
276 vals[i].channel[ch] = ((double *)im->idata)[off];
277 ++off;
278 }
279 }
280 return count;
281 }
282 else {
283 return 0;
284 }
285}
286
97ac0a96 287static int i_plinf_ddoub(i_img *im, int l, int r, int y, const i_fcolor *vals) {
2ce44e2a
TC
288 int ch, count, i;
289 int off;
290 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
291 if (r > im->xsize)
292 r = im->xsize;
293 off = (l+y*im->xsize) * im->channels;
294 count = r - l;
35f40526
TC
295 if (I_ALL_CHANNELS_WRITABLE(im)) {
296 for (i = 0; i < count; ++i) {
297 for (ch = 0; ch < im->channels; ++ch) {
298 ((double *)im->idata)[off] = vals[i].channel[ch];
299 ++off;
300 }
301 }
302 }
303 else {
304 for (i = 0; i < count; ++i) {
305 for (ch = 0; ch < im->channels; ++ch) {
306 if (im->ch_mask & (1 << ch))
307 ((double *)im->idata)[off] = vals[i].channel[ch];
308 ++off;
309 }
2ce44e2a
TC
310 }
311 }
312 return count;
313 }
314 else {
315 return 0;
316 }
317}
318
319static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps,
18accb2a 320 int const *chans, int chan_count) {
2ce44e2a
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++ = SampleFTo8(((double *)im->idata)[off+chans[ch]]);
342 ++count;
343 }
344 off += im->channels;
345 }
346 }
347 else {
c7481ae1
TC
348 if (chan_count <= 0 || chan_count > im->channels) {
349 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
350 chan_count);
351 return 0;
352 }
2ce44e2a
TC
353 for (i = 0; i < w; ++i) {
354 for (ch = 0; ch < chan_count; ++ch) {
355 *samps++ = SampleFTo8(((double *)im->idata)[off+ch]);
356 ++count;
357 }
358 off += im->channels;
359 }
360 }
361
362 return count;
363 }
364 else {
365 return 0;
366 }
367}
368
369static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps,
18accb2a 370 int const *chans, int chan_count) {
2ce44e2a
TC
371 int ch, count, i, w;
372 int off;
373
374 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
375 if (r > im->xsize)
376 r = im->xsize;
377 off = (l+y*im->xsize) * im->channels;
378 w = r - l;
379 count = 0;
380
381 if (chans) {
382 /* make sure we have good channel numbers */
383 for (ch = 0; ch < chan_count; ++ch) {
384 if (chans[ch] < 0 || chans[ch] >= im->channels) {
385 i_push_errorf(0, "No channel %d in this image", chans[ch]);
386 return 0;
387 }
388 }
389 for (i = 0; i < w; ++i) {
390 for (ch = 0; ch < chan_count; ++ch) {
391 *samps++ = ((double *)im->idata)[off+chans[ch]];
392 ++count;
393 }
394 off += im->channels;
395 }
396 }
397 else {
c7481ae1
TC
398 if (chan_count <= 0 || chan_count > im->channels) {
399 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
400 chan_count);
401 return 0;
402 }
2ce44e2a
TC
403 for (i = 0; i < w; ++i) {
404 for (ch = 0; ch < chan_count; ++ch) {
405 *samps++ = ((double *)im->idata)[off+ch];
406 ++count;
407 }
408 off += im->channels;
409 }
410 }
411
412 return count;
413 }
414 else {
415 return 0;
416 }
417}
418
b8c2033e
AMH
419
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*/