re-work XS handling of channel lists
[imager.git] / imgdouble.c
CommitLineData
2ce44e2a
TC
1/*
2=head1 NAME
3
4imgdouble.c - implements double per sample images
5
6=head1 SYNOPSIS
7
8d14daab 8 i_img *im = i_img_double_new(width, height, channels);
2ce44e2a
TC
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
8d14daab
TC
26static int i_ppix_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_color *val);
27static int i_gpix_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_color *val);
28static i_img_dim i_glin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
29static i_img_dim i_plin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
30static int i_ppixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val);
31static int i_gpixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val);
32static i_img_dim i_glinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
33static i_img_dim i_plinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
34static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
18accb2a 35 int const *chans, int chan_count);
8d14daab 36static i_img_dim i_gsampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim 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 */
bd8052a6
TC
73 NULL, /* i_f_addcolors */
74 NULL, /* i_f_getcolors */
2ce44e2a 75 NULL, /* i_f_colorcount */
bd8052a6 76 NULL, /* i_f_maxcolors */
2ce44e2a 77 NULL, /* i_f_findcolor */
bd8052a6 78 NULL, /* i_f_setcolors */
2ce44e2a
TC
79
80 NULL, /* i_f_destroy */
bd8052a6
TC
81
82 i_gsamp_bits_fb,
83 NULL, /* i_f_psamp_bits */
2ce44e2a
TC
84};
85
86/*
8d14daab 87=item i_img_double_new(i_img_dim x, i_img_dim y, int ch)
9167a5c6
TC
88=category Image creation/destruction
89=synopsis i_img *img = i_img_double_new(width, height, channels);
92bda632 90
2ce44e2a
TC
91Creates a new double per sample image.
92
93=cut
94*/
8d14daab
TC
95i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch) {
96 size_t bytes;
bd8052a6 97 i_img *im;
653ea321 98
8d14daab
TC
99 mm_log((1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
100 i_DFc(x), i_DFc(y), ch));
1501d9b3
TC
101
102 if (x < 1 || y < 1) {
103 i_push_error(0, "Image sizes must be positive");
104 return NULL;
105 }
106 if (ch < 1 || ch > MAXCHANNELS) {
107 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
108 return NULL;
109 }
653ea321
TC
110 bytes = x * y * ch * sizeof(double);
111 if (bytes / y / ch / sizeof(double) != x) {
112 i_push_errorf(0, "integer overflow calculating image allocation");
113 return NULL;
114 }
2ce44e2a 115
bd8052a6 116 im = i_img_alloc();
2ce44e2a
TC
117 *im = IIM_base_double_direct;
118 i_tags_new(&im->tags);
119 im->xsize = x;
120 im->ysize = y;
121 im->channels = ch;
653ea321 122 im->bytes = bytes;
2ce44e2a
TC
123 im->ext_data = NULL;
124 im->idata = mymalloc(im->bytes);
bd8052a6
TC
125 memset(im->idata, 0, im->bytes);
126 i_img_init(im);
2ce44e2a
TC
127
128 return im;
129}
130
8d14daab
TC
131static int i_ppix_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
132 i_img_dim off;
133 int ch;
2ce44e2a 134
837a4b43 135 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
136 return -1;
137
138 off = (x + y * im->xsize) * im->channels;
35f40526
TC
139 if (I_ALL_CHANNELS_WRITABLE(im)) {
140 for (ch = 0; ch < im->channels; ++ch)
141 ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
142 }
143 else {
144 for (ch = 0; ch < im->channels; ++ch)
145 if (im->ch_mask & (1<<ch))
146 ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
147 }
2ce44e2a
TC
148
149 return 0;
150}
151
8d14daab
TC
152static int i_gpix_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
153 i_img_dim off;
154 int ch;
2ce44e2a 155
837a4b43 156 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
157 return -1;
158
159 off = (x + y * im->xsize) * im->channels;
160 for (ch = 0; ch < im->channels; ++ch)
161 val->channel[ch] = SampleFTo8(((double *)im->idata)[off+ch]);
162
163 return 0;
164}
165
8d14daab
TC
166static int i_ppixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
167 i_img_dim off;
168 int ch;
2ce44e2a 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;
35f40526
TC
174 if (I_ALL_CHANNELS_WRITABLE(im)) {
175 for (ch = 0; ch < im->channels; ++ch)
176 ((double *)im->idata)[off+ch] = val->channel[ch];
177 }
178 else {
179 for (ch = 0; ch < im->channels; ++ch)
180 if (im->ch_mask & (1 << ch))
181 ((double *)im->idata)[off+ch] = val->channel[ch];
182 }
2ce44e2a
TC
183
184 return 0;
185}
186
8d14daab
TC
187static int i_gpixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
188 i_img_dim off;
189 int ch;
2ce44e2a 190
837a4b43 191 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
192 return -1;
193
194 off = (x + y * im->xsize) * im->channels;
195 for (ch = 0; ch < im->channels; ++ch)
196 val->channel[ch] = ((double *)im->idata)[off+ch];
197
198 return 0;
199}
200
8d14daab
TC
201static i_img_dim i_glin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) {
202 int ch;
203 i_img_dim count, i;
204 i_img_dim off;
2ce44e2a
TC
205 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
206 if (r > im->xsize)
207 r = im->xsize;
208 off = (l+y*im->xsize) * im->channels;
209 count = r - l;
210 for (i = 0; i < count; ++i) {
211 for (ch = 0; ch < im->channels; ++ch) {
212 vals[i].channel[ch] = SampleFTo8(((double *)im->idata)[off]);
213 ++off;
214 }
215 }
216 return count;
217 }
218 else {
219 return 0;
220 }
221}
222
8d14daab
TC
223static i_img_dim i_plin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) {
224 int ch;
225 i_img_dim count, i;
226 i_img_dim off;
2ce44e2a
TC
227 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
228 if (r > im->xsize)
229 r = im->xsize;
230 off = (l+y*im->xsize) * im->channels;
231 count = r - l;
35f40526
TC
232 if (I_ALL_CHANNELS_WRITABLE(im)) {
233 for (i = 0; i < count; ++i) {
234 for (ch = 0; ch < im->channels; ++ch) {
235 ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
236 ++off;
237 }
238 }
239 }
240 else {
241 for (i = 0; i < count; ++i) {
242 for (ch = 0; ch < im->channels; ++ch) {
243 if (im->ch_mask & (1 << ch))
244 ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
245 ++off;
246 }
2ce44e2a
TC
247 }
248 }
249 return count;
250 }
251 else {
252 return 0;
253 }
254}
255
8d14daab
TC
256static i_img_dim i_glinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) {
257 int ch;
258 i_img_dim count, i;
259 i_img_dim off;
2ce44e2a
TC
260 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
261 if (r > im->xsize)
262 r = im->xsize;
263 off = (l+y*im->xsize) * im->channels;
264 count = r - l;
265 for (i = 0; i < count; ++i) {
266 for (ch = 0; ch < im->channels; ++ch) {
267 vals[i].channel[ch] = ((double *)im->idata)[off];
268 ++off;
269 }
270 }
271 return count;
272 }
273 else {
274 return 0;
275 }
276}
277
8d14daab
TC
278static i_img_dim i_plinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) {
279 int ch;
280 i_img_dim count, i;
281 i_img_dim off;
2ce44e2a
TC
282 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
283 if (r > im->xsize)
284 r = im->xsize;
285 off = (l+y*im->xsize) * im->channels;
286 count = r - l;
35f40526
TC
287 if (I_ALL_CHANNELS_WRITABLE(im)) {
288 for (i = 0; i < count; ++i) {
289 for (ch = 0; ch < im->channels; ++ch) {
290 ((double *)im->idata)[off] = vals[i].channel[ch];
291 ++off;
292 }
293 }
294 }
295 else {
296 for (i = 0; i < count; ++i) {
297 for (ch = 0; ch < im->channels; ++ch) {
298 if (im->ch_mask & (1 << ch))
299 ((double *)im->idata)[off] = vals[i].channel[ch];
300 ++off;
301 }
2ce44e2a
TC
302 }
303 }
304 return count;
305 }
306 else {
307 return 0;
308 }
309}
310
8d14daab 311static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
18accb2a 312 int const *chans, int chan_count) {
8d14daab
TC
313 int ch;
314 i_img_dim count, i, w;
315 i_img_dim off;
2ce44e2a
TC
316
317 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
318 if (r > im->xsize)
319 r = im->xsize;
320 off = (l+y*im->xsize) * im->channels;
321 w = r - l;
322 count = 0;
323
324 if (chans) {
325 /* make sure we have good channel numbers */
326 for (ch = 0; ch < chan_count; ++ch) {
327 if (chans[ch] < 0 || chans[ch] >= im->channels) {
328 i_push_errorf(0, "No channel %d in this image", chans[ch]);
329 return 0;
330 }
331 }
332 for (i = 0; i < w; ++i) {
333 for (ch = 0; ch < chan_count; ++ch) {
334 *samps++ = SampleFTo8(((double *)im->idata)[off+chans[ch]]);
335 ++count;
336 }
337 off += im->channels;
338 }
339 }
340 else {
c7481ae1
TC
341 if (chan_count <= 0 || chan_count > im->channels) {
342 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
343 chan_count);
344 return 0;
345 }
2ce44e2a
TC
346 for (i = 0; i < w; ++i) {
347 for (ch = 0; ch < chan_count; ++ch) {
348 *samps++ = SampleFTo8(((double *)im->idata)[off+ch]);
349 ++count;
350 }
351 off += im->channels;
352 }
353 }
354
355 return count;
356 }
357 else {
358 return 0;
359 }
360}
361
8d14daab 362static i_img_dim i_gsampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
18accb2a 363 int const *chans, int chan_count) {
8d14daab
TC
364 int ch;
365 i_img_dim count, i, w;
366 i_img_dim off;
2ce44e2a
TC
367
368 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
369 if (r > im->xsize)
370 r = im->xsize;
371 off = (l+y*im->xsize) * im->channels;
372 w = r - l;
373 count = 0;
374
375 if (chans) {
376 /* make sure we have good channel numbers */
377 for (ch = 0; ch < chan_count; ++ch) {
378 if (chans[ch] < 0 || chans[ch] >= im->channels) {
379 i_push_errorf(0, "No channel %d in this image", chans[ch]);
380 return 0;
381 }
382 }
383 for (i = 0; i < w; ++i) {
384 for (ch = 0; ch < chan_count; ++ch) {
385 *samps++ = ((double *)im->idata)[off+chans[ch]];
386 ++count;
387 }
388 off += im->channels;
389 }
390 }
391 else {
c7481ae1
TC
392 if (chan_count <= 0 || chan_count > im->channels) {
393 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
394 chan_count);
395 return 0;
396 }
2ce44e2a
TC
397 for (i = 0; i < w; ++i) {
398 for (ch = 0; ch < chan_count; ++ch) {
399 *samps++ = ((double *)im->idata)[off+ch];
400 ++count;
401 }
402 off += im->channels;
403 }
404 }
405
406 return count;
407 }
408 else {
409 return 0;
410 }
411}
412
bfe6ba3f
TC
413/*
414=item i_img_to_drgb(im)
415
416=category Image creation
417
418Returns a double/sample version of the supplied image.
419
420Returns the image on success, or NULL on failure.
421
422=cut
423*/
424
425i_img *
426i_img_to_drgb(i_img *im) {
427 i_img *targ;
428 i_fcolor *line;
8d14daab 429 i_img_dim y;
bfe6ba3f
TC
430
431 targ = i_img_double_new(im->xsize, im->ysize, im->channels);
432 if (!targ)
433 return NULL;
434 line = mymalloc(sizeof(i_fcolor) * im->xsize);
435 for (y = 0; y < im->ysize; ++y) {
436 i_glinf(im, 0, im->xsize, y, line);
437 i_plinf(targ, 0, im->xsize, y, line);
438 }
439
440 myfree(line);
441
442 return targ;
443}
b8c2033e
AMH
444
445/*
446=back
447
448=head1 AUTHOR
449
450Tony Cook <tony@develop-help.com>
451
452=head1 SEE ALSO
453
454Imager(3)
455
456=cut
457*/