]> git.imager.perl.org - imager.git/blame - imgdouble.c
merge circle outline branch
[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 */
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/*
87=item i_img_double_new(int x, int 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*/
bd8052a6 95i_img *i_img_double_new(int x, int y, int ch) {
653ea321 96 int bytes;
bd8052a6 97 i_img *im;
653ea321 98
2ce44e2a 99 mm_log((1,"i_img_double_new(x %d, y %d, ch %d)\n", x, y, ch));
1501d9b3
TC
100
101 if (x < 1 || y < 1) {
102 i_push_error(0, "Image sizes must be positive");
103 return NULL;
104 }
105 if (ch < 1 || ch > MAXCHANNELS) {
106 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
107 return NULL;
108 }
653ea321
TC
109 bytes = x * y * ch * sizeof(double);
110 if (bytes / y / ch / sizeof(double) != x) {
111 i_push_errorf(0, "integer overflow calculating image allocation");
112 return NULL;
113 }
2ce44e2a 114
bd8052a6 115 im = i_img_alloc();
2ce44e2a
TC
116 *im = IIM_base_double_direct;
117 i_tags_new(&im->tags);
118 im->xsize = x;
119 im->ysize = y;
120 im->channels = ch;
653ea321 121 im->bytes = bytes;
2ce44e2a
TC
122 im->ext_data = NULL;
123 im->idata = mymalloc(im->bytes);
bd8052a6
TC
124 memset(im->idata, 0, im->bytes);
125 i_img_init(im);
2ce44e2a
TC
126
127 return im;
128}
129
97ac0a96 130static int i_ppix_ddoub(i_img *im, int x, int y, const i_color *val) {
2ce44e2a
TC
131 int off, ch;
132
837a4b43 133 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
134 return -1;
135
136 off = (x + y * im->xsize) * im->channels;
35f40526
TC
137 if (I_ALL_CHANNELS_WRITABLE(im)) {
138 for (ch = 0; ch < im->channels; ++ch)
139 ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
140 }
141 else {
142 for (ch = 0; ch < im->channels; ++ch)
143 if (im->ch_mask & (1<<ch))
144 ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
145 }
2ce44e2a
TC
146
147 return 0;
148}
149
150static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val) {
151 int off, ch;
152
837a4b43 153 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
154 return -1;
155
156 off = (x + y * im->xsize) * im->channels;
157 for (ch = 0; ch < im->channels; ++ch)
158 val->channel[ch] = SampleFTo8(((double *)im->idata)[off+ch]);
159
160 return 0;
161}
162
97ac0a96 163static int i_ppixf_ddoub(i_img *im, int x, int y, const i_fcolor *val) {
2ce44e2a
TC
164 int off, ch;
165
837a4b43 166 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
167 return -1;
168
169 off = (x + y * im->xsize) * im->channels;
35f40526
TC
170 if (I_ALL_CHANNELS_WRITABLE(im)) {
171 for (ch = 0; ch < im->channels; ++ch)
172 ((double *)im->idata)[off+ch] = val->channel[ch];
173 }
174 else {
175 for (ch = 0; ch < im->channels; ++ch)
176 if (im->ch_mask & (1 << ch))
177 ((double *)im->idata)[off+ch] = val->channel[ch];
178 }
2ce44e2a
TC
179
180 return 0;
181}
182
183static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val) {
184 int off, ch;
185
837a4b43 186 if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
2ce44e2a
TC
187 return -1;
188
189 off = (x + y * im->xsize) * im->channels;
190 for (ch = 0; ch < im->channels; ++ch)
191 val->channel[ch] = ((double *)im->idata)[off+ch];
192
193 return 0;
194}
195
196static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals) {
197 int ch, count, i;
198 int off;
199 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
200 if (r > im->xsize)
201 r = im->xsize;
202 off = (l+y*im->xsize) * im->channels;
203 count = r - l;
204 for (i = 0; i < count; ++i) {
205 for (ch = 0; ch < im->channels; ++ch) {
206 vals[i].channel[ch] = SampleFTo8(((double *)im->idata)[off]);
207 ++off;
208 }
209 }
210 return count;
211 }
212 else {
213 return 0;
214 }
215}
216
97ac0a96 217static int i_plin_ddoub(i_img *im, int l, int r, int y, const i_color *vals) {
2ce44e2a
TC
218 int ch, count, i;
219 int off;
220 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
221 if (r > im->xsize)
222 r = im->xsize;
223 off = (l+y*im->xsize) * im->channels;
224 count = r - l;
35f40526
TC
225 if (I_ALL_CHANNELS_WRITABLE(im)) {
226 for (i = 0; i < count; ++i) {
227 for (ch = 0; ch < im->channels; ++ch) {
228 ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
229 ++off;
230 }
231 }
232 }
233 else {
234 for (i = 0; i < count; ++i) {
235 for (ch = 0; ch < im->channels; ++ch) {
236 if (im->ch_mask & (1 << ch))
237 ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
238 ++off;
239 }
2ce44e2a
TC
240 }
241 }
242 return count;
243 }
244 else {
245 return 0;
246 }
247}
248
249static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) {
250 int ch, count, i;
251 int off;
252 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
253 if (r > im->xsize)
254 r = im->xsize;
255 off = (l+y*im->xsize) * im->channels;
256 count = r - l;
257 for (i = 0; i < count; ++i) {
258 for (ch = 0; ch < im->channels; ++ch) {
259 vals[i].channel[ch] = ((double *)im->idata)[off];
260 ++off;
261 }
262 }
263 return count;
264 }
265 else {
266 return 0;
267 }
268}
269
97ac0a96 270static int i_plinf_ddoub(i_img *im, int l, int r, int y, const i_fcolor *vals) {
2ce44e2a
TC
271 int ch, count, i;
272 int off;
273 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
274 if (r > im->xsize)
275 r = im->xsize;
276 off = (l+y*im->xsize) * im->channels;
277 count = r - l;
35f40526
TC
278 if (I_ALL_CHANNELS_WRITABLE(im)) {
279 for (i = 0; i < count; ++i) {
280 for (ch = 0; ch < im->channels; ++ch) {
281 ((double *)im->idata)[off] = vals[i].channel[ch];
282 ++off;
283 }
284 }
285 }
286 else {
287 for (i = 0; i < count; ++i) {
288 for (ch = 0; ch < im->channels; ++ch) {
289 if (im->ch_mask & (1 << ch))
290 ((double *)im->idata)[off] = vals[i].channel[ch];
291 ++off;
292 }
2ce44e2a
TC
293 }
294 }
295 return count;
296 }
297 else {
298 return 0;
299 }
300}
301
302static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps,
18accb2a 303 int const *chans, int chan_count) {
2ce44e2a
TC
304 int ch, count, i, w;
305 int off;
306
307 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
308 if (r > im->xsize)
309 r = im->xsize;
310 off = (l+y*im->xsize) * im->channels;
311 w = r - l;
312 count = 0;
313
314 if (chans) {
315 /* make sure we have good channel numbers */
316 for (ch = 0; ch < chan_count; ++ch) {
317 if (chans[ch] < 0 || chans[ch] >= im->channels) {
318 i_push_errorf(0, "No channel %d in this image", chans[ch]);
319 return 0;
320 }
321 }
322 for (i = 0; i < w; ++i) {
323 for (ch = 0; ch < chan_count; ++ch) {
324 *samps++ = SampleFTo8(((double *)im->idata)[off+chans[ch]]);
325 ++count;
326 }
327 off += im->channels;
328 }
329 }
330 else {
c7481ae1
TC
331 if (chan_count <= 0 || chan_count > im->channels) {
332 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
333 chan_count);
334 return 0;
335 }
2ce44e2a
TC
336 for (i = 0; i < w; ++i) {
337 for (ch = 0; ch < chan_count; ++ch) {
338 *samps++ = SampleFTo8(((double *)im->idata)[off+ch]);
339 ++count;
340 }
341 off += im->channels;
342 }
343 }
344
345 return count;
346 }
347 else {
348 return 0;
349 }
350}
351
352static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps,
18accb2a 353 int const *chans, int chan_count) {
2ce44e2a
TC
354 int ch, count, i, w;
355 int off;
356
357 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
358 if (r > im->xsize)
359 r = im->xsize;
360 off = (l+y*im->xsize) * im->channels;
361 w = r - l;
362 count = 0;
363
364 if (chans) {
365 /* make sure we have good channel numbers */
366 for (ch = 0; ch < chan_count; ++ch) {
367 if (chans[ch] < 0 || chans[ch] >= im->channels) {
368 i_push_errorf(0, "No channel %d in this image", chans[ch]);
369 return 0;
370 }
371 }
372 for (i = 0; i < w; ++i) {
373 for (ch = 0; ch < chan_count; ++ch) {
374 *samps++ = ((double *)im->idata)[off+chans[ch]];
375 ++count;
376 }
377 off += im->channels;
378 }
379 }
380 else {
c7481ae1
TC
381 if (chan_count <= 0 || chan_count > im->channels) {
382 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
383 chan_count);
384 return 0;
385 }
2ce44e2a
TC
386 for (i = 0; i < w; ++i) {
387 for (ch = 0; ch < chan_count; ++ch) {
388 *samps++ = ((double *)im->idata)[off+ch];
389 ++count;
390 }
391 off += im->channels;
392 }
393 }
394
395 return count;
396 }
397 else {
398 return 0;
399 }
400}
401
b8c2033e
AMH
402
403/*
404=back
405
406=head1 AUTHOR
407
408Tony Cook <tony@develop-help.com>
409
410=head1 SEE ALSO
411
412Imager(3)
413
414=cut
415*/