avoid an unneeded check in the FT1 has_chars() method implementation
[imager.git] / img8.c
CommitLineData
696cb85d
TC
1#define IMAGER_NO_CONTEXT
2
a2f9a61c
TC
3#include "imager.h"
4#include "imageri.h"
5
8d14daab
TC
6static int i_ppix_d(i_img *im, i_img_dim x, i_img_dim y, const i_color *val);
7static int i_gpix_d(i_img *im, i_img_dim x, i_img_dim y, i_color *val);
8static i_img_dim i_glin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
9static i_img_dim i_plin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
10static int i_ppixf_d(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val);
11static int i_gpixf_d(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val);
12static i_img_dim i_glinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
13static i_img_dim i_plinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
14static i_img_dim i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, const int *chans, int chan_count);
15static i_img_dim i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, const int *chans, int chan_count);
836d9f54
TC
16static i_img_dim i_psamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_sample_t *samps, const int *chans, int chan_count);
17static i_img_dim i_psampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fsample_t *samps, const int *chans, int chan_count);
a2f9a61c
TC
18
19/*
20=item IIM_base_8bit_direct (static)
21
22A static i_img object used to initialize direct 8-bit per sample images.
23
24=cut
25*/
26static i_img IIM_base_8bit_direct =
27{
28 0, /* channels set */
29 0, 0, 0, /* xsize, ysize, bytes */
30 ~0U, /* ch_mask */
31 i_8_bits, /* bits */
32 i_direct_type, /* type */
33 0, /* virtual */
34 NULL, /* idata */
35 { 0, 0, NULL }, /* tags */
36 NULL, /* ext_data */
37
38 i_ppix_d, /* i_f_ppix */
39 i_ppixf_d, /* i_f_ppixf */
40 i_plin_d, /* i_f_plin */
41 i_plinf_d, /* i_f_plinf */
42 i_gpix_d, /* i_f_gpix */
43 i_gpixf_d, /* i_f_gpixf */
44 i_glin_d, /* i_f_glin */
45 i_glinf_d, /* i_f_glinf */
46 i_gsamp_d, /* i_f_gsamp */
47 i_gsampf_d, /* i_f_gsampf */
48
49 NULL, /* i_f_gpal */
50 NULL, /* i_f_ppal */
51 NULL, /* i_f_addcolors */
52 NULL, /* i_f_getcolors */
53 NULL, /* i_f_colorcount */
54 NULL, /* i_f_maxcolors */
55 NULL, /* i_f_findcolor */
56 NULL, /* i_f_setcolors */
57
58 NULL, /* i_f_destroy */
59
60 i_gsamp_bits_fb,
61 NULL, /* i_f_psamp_bits */
836d9f54
TC
62
63 i_psamp_d,
64 i_psampf_d
a2f9a61c
TC
65};
66
67/*static void set_8bit_direct(i_img *im) {
68 im->i_f_ppix = i_ppix_d;
69 im->i_f_ppixf = i_ppixf_d;
70 im->i_f_plin = i_plin_d;
71 im->i_f_plinf = i_plinf_d;
72 im->i_f_gpix = i_gpix_d;
73 im->i_f_gpixf = i_gpixf_d;
74 im->i_f_glin = i_glin_d;
75 im->i_f_glinf = i_glinf_d;
76 im->i_f_gpal = NULL;
77 im->i_f_ppal = NULL;
78 im->i_f_addcolor = NULL;
79 im->i_f_getcolor = NULL;
80 im->i_f_colorcount = NULL;
81 im->i_f_findcolor = NULL;
82 }*/
83
84/*
abffffed
TC
85=item im_img_8_new(ctx, x, y, ch)
86X<im_img_8_new API>X<i_img_8_new API>
a2f9a61c 87=category Image creation/destruction
abffffed 88=synopsis i_img *img = im_img_8_new(aIMCTX, width, height, channels);
a2f9a61c
TC
89=synopsis i_img *img = i_img_8_new(width, height, channels);
90
91Creates a new image object I<x> pixels wide, and I<y> pixels high with
92I<ch> channels.
93
94=cut
95*/
96
a2f9a61c 97i_img *
696cb85d 98im_img_8_new(pIMCTX, i_img_dim x,i_img_dim y,int ch) {
a2f9a61c 99 i_img *im;
8d14daab 100
ddffecae 101 im_log((aIMCTX, 1,"im_img_8_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
8d14daab 102 i_DFc(x), i_DFc(y), ch));
a2f9a61c 103
696cb85d 104 im = im_img_empty_ch(aIMCTX, NULL,x,y,ch);
d03fd5a4 105
ddffecae 106 im_log((aIMCTX, 1,"(%p) <- IIM_new\n",im));
d03fd5a4
TC
107 return im;
108}
109
a2f9a61c
TC
110/*
111=item i_img_empty(im, x, y)
112
113Re-new image reference (assumes 3 channels)
114
115 im - Image pointer
116 x - xsize of destination image
117 y - ysize of destination image
118
119**FIXME** what happens if a live image is passed in here?
120
121Should this just call i_img_empty_ch()?
122
123=cut
124*/
125
126i_img *
696cb85d 127im_img_empty(pIMCTX, i_img *im,i_img_dim x,i_img_dim y) {
ddffecae 128 im_log((aIMCTX, 1,"i_img_empty(*im %p, x %" i_DF ", y %" i_DF ")\n",
8d14daab 129 im, i_DFc(x), i_DFc(y)));
696cb85d 130 return im_img_empty_ch(aIMCTX, im, x, y, 3);
a2f9a61c
TC
131}
132
133/*
134=item i_img_empty_ch(im, x, y, ch)
135
136Re-new image reference
137
138 im - Image pointer
139 x - xsize of destination image
140 y - ysize of destination image
141 ch - number of channels
142
143=cut
144*/
145
146i_img *
696cb85d 147im_img_empty_ch(pIMCTX, i_img *im,i_img_dim x,i_img_dim y,int ch) {
8d14daab 148 size_t bytes;
a2f9a61c 149
ddffecae 150 im_log((aIMCTX, 1,"i_img_empty_ch(*im %p, x %" i_DF ", y %" i_DF ", ch %d)\n",
8d14daab 151 im, i_DFc(x), i_DFc(y), ch));
a2f9a61c
TC
152
153 if (x < 1 || y < 1) {
696cb85d 154 im_push_error(aIMCTX, 0, "Image sizes must be positive");
a2f9a61c
TC
155 return NULL;
156 }
157 if (ch < 1 || ch > MAXCHANNELS) {
696cb85d 158 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
a2f9a61c
TC
159 return NULL;
160 }
161 /* check this multiplication doesn't overflow */
162 bytes = x*y*ch;
163 if (bytes / y / ch != x) {
696cb85d 164 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
a2f9a61c
TC
165 return NULL;
166 }
167
168 if (im == NULL)
696cb85d 169 im = im_img_alloc(aIMCTX);
a2f9a61c
TC
170
171 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
172 i_tags_new(&im->tags);
173 im->xsize = x;
174 im->ysize = y;
175 im->channels = ch;
498a7bc2 176 im->ch_mask = ~0U;
a2f9a61c
TC
177 im->bytes=bytes;
178 if ( (im->idata=mymalloc(im->bytes)) == NULL)
8ebac85f 179 im_fatal(aIMCTX, 2,"malloc() error\n");
a2f9a61c
TC
180 memset(im->idata,0,(size_t)im->bytes);
181
182 im->ext_data = NULL;
183
696cb85d 184 im_img_init(aIMCTX, im);
a2f9a61c 185
ddffecae 186 im_log((aIMCTX, 1,"(%p) <- i_img_empty_ch\n",im));
a2f9a61c
TC
187 return im;
188}
189
190/*
191=head2 8-bit per sample image internal functions
192
193These are the functions installed in an 8-bit per sample image.
194
195=over
196
197=item i_ppix_d(im, x, y, col)
198
199Internal function.
200
201This is the function kept in the i_f_ppix member of an i_img object.
202It does a normal store of a pixel into the image with range checking.
203
204Returns 0 if the pixel could be set, -1 otherwise.
205
206=cut
207*/
208static
209int
8d14daab 210i_ppix_d(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
a2f9a61c
TC
211 int ch;
212
213 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
214 for(ch=0;ch<im->channels;ch++)
215 if (im->ch_mask&(1<<ch))
216 im->idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
217 return 0;
218 }
219 return -1; /* error was clipped */
220}
221
222/*
223=item i_gpix_d(im, x, y, &col)
224
225Internal function.
226
227This is the function kept in the i_f_gpix member of an i_img object.
228It does normal retrieval of a pixel from the image with range checking.
229
bfb2c635 230Returns 0 if the pixel could be retrieved, -1 otherwise.
a2f9a61c
TC
231
232=cut
233*/
234static
235int
8d14daab 236i_gpix_d(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
a2f9a61c
TC
237 int ch;
238 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
239 for(ch=0;ch<im->channels;ch++)
240 val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
241 return 0;
242 }
243 for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
244 return -1; /* error was cliped */
245}
246
247/*
248=item i_glin_d(im, l, r, y, vals)
249
250Reads a line of data from the image, storing the pixels at vals.
251
252The line runs from (l,y) inclusive to (r,y) non-inclusive
253
254vals should point at space for (r-l) pixels.
255
256l should never be less than zero (to avoid confusion about where to
257put the pixels in vals).
258
259Returns the number of pixels copied (eg. if r, l or y is out of range)
260
261=cut
262*/
263static
8d14daab
TC
264i_img_dim
265i_glin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) {
266 int ch;
267 i_img_dim count, i;
a2f9a61c
TC
268 unsigned char *data;
269 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
270 if (r > im->xsize)
271 r = im->xsize;
272 data = im->idata + (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] = *data++;
277 }
278 return count;
279 }
280 else {
281 return 0;
282 }
283}
284
285/*
286=item i_plin_d(im, l, r, y, vals)
287
288Writes a line of data into the image, using the pixels at vals.
289
290The line runs from (l,y) inclusive to (r,y) non-inclusive
291
292vals should point at (r-l) pixels.
293
294l should never be less than zero (to avoid confusion about where to
295get the pixels in vals).
296
297Returns the number of pixels copied (eg. if r, l or y is out of range)
298
299=cut
300*/
301static
8d14daab
TC
302i_img_dim
303i_plin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) {
304 int ch;
305 i_img_dim count, i;
a2f9a61c
TC
306 unsigned char *data;
307 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
308 if (r > im->xsize)
309 r = im->xsize;
310 data = im->idata + (l+y*im->xsize) * im->channels;
311 count = r - l;
312 for (i = 0; i < count; ++i) {
313 for (ch = 0; ch < im->channels; ++ch) {
314 if (im->ch_mask & (1 << ch))
315 *data = vals[i].channel[ch];
316 ++data;
317 }
318 }
319 return count;
320 }
321 else {
322 return 0;
323 }
324}
325
326/*
327=item i_ppixf_d(im, x, y, val)
328
329=cut
330*/
331static
332int
8d14daab 333i_ppixf_d(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
a2f9a61c
TC
334 int ch;
335
336 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
337 for(ch=0;ch<im->channels;ch++)
338 if (im->ch_mask&(1<<ch)) {
339 im->idata[(x+y*im->xsize)*im->channels+ch] =
340 SampleFTo8(val->channel[ch]);
341 }
342 return 0;
343 }
344 return -1; /* error was clipped */
345}
346
347/*
348=item i_gpixf_d(im, x, y, val)
349
350=cut
351*/
352static
353int
8d14daab 354i_gpixf_d(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
a2f9a61c
TC
355 int ch;
356 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
357 for(ch=0;ch<im->channels;ch++) {
358 val->channel[ch] =
359 Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]);
360 }
361 return 0;
362 }
363 return -1; /* error was cliped */
364}
365
366/*
367=item i_glinf_d(im, l, r, y, vals)
368
369Reads a line of data from the image, storing the pixels at vals.
370
371The line runs from (l,y) inclusive to (r,y) non-inclusive
372
373vals should point at space for (r-l) pixels.
374
375l should never be less than zero (to avoid confusion about where to
376put the pixels in vals).
377
378Returns the number of pixels copied (eg. if r, l or y is out of range)
379
380=cut
381*/
382static
8d14daab
TC
383i_img_dim
384i_glinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) {
385 int ch;
386 i_img_dim count, i;
a2f9a61c
TC
387 unsigned char *data;
388 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
389 if (r > im->xsize)
390 r = im->xsize;
391 data = im->idata + (l+y*im->xsize) * im->channels;
392 count = r - l;
393 for (i = 0; i < count; ++i) {
394 for (ch = 0; ch < im->channels; ++ch)
395 vals[i].channel[ch] = Sample8ToF(*data++);
396 }
397 return count;
398 }
399 else {
400 return 0;
401 }
402}
403
404/*
405=item i_plinf_d(im, l, r, y, vals)
406
407Writes a line of data into the image, using the pixels at vals.
408
409The line runs from (l,y) inclusive to (r,y) non-inclusive
410
411vals should point at (r-l) pixels.
412
413l should never be less than zero (to avoid confusion about where to
414get the pixels in vals).
415
416Returns the number of pixels copied (eg. if r, l or y is out of range)
417
418=cut
419*/
420static
8d14daab
TC
421i_img_dim
422i_plinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) {
423 int ch;
424 i_img_dim count, i;
a2f9a61c
TC
425 unsigned char *data;
426 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
427 if (r > im->xsize)
428 r = im->xsize;
429 data = im->idata + (l+y*im->xsize) * im->channels;
430 count = r - l;
431 for (i = 0; i < count; ++i) {
432 for (ch = 0; ch < im->channels; ++ch) {
433 if (im->ch_mask & (1 << ch))
434 *data = SampleFTo8(vals[i].channel[ch]);
435 ++data;
436 }
437 }
438 return count;
439 }
440 else {
441 return 0;
442 }
443}
444
445/*
8d14daab 446=item i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int *chans, int chan_count)
a2f9a61c
TC
447
448Reads sample values from im for the horizontal line (l, y) to (r-1,y)
449for the channels specified by chans, an array of int with chan_count
450elements.
451
452Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
453
454=cut
455*/
456static
8d14daab
TC
457i_img_dim
458i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
a2f9a61c 459 const int *chans, int chan_count) {
8d14daab
TC
460 int ch;
461 i_img_dim count, i, w;
a2f9a61c
TC
462 unsigned char *data;
463
464 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
465 if (r > im->xsize)
466 r = im->xsize;
467 data = im->idata + (l+y*im->xsize) * im->channels;
468 w = r - l;
469 count = 0;
470
471 if (chans) {
472 /* make sure we have good channel numbers */
473 for (ch = 0; ch < chan_count; ++ch) {
474 if (chans[ch] < 0 || chans[ch] >= im->channels) {
ddffecae
TC
475 dIMCTXim(im);
476 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
a2f9a61c
TC
477 return 0;
478 }
479 }
480 for (i = 0; i < w; ++i) {
481 for (ch = 0; ch < chan_count; ++ch) {
482 *samps++ = data[chans[ch]];
483 ++count;
484 }
485 data += im->channels;
486 }
487 }
488 else {
489 if (chan_count <= 0 || chan_count > im->channels) {
ddffecae
TC
490 dIMCTXim(im);
491 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
a2f9a61c
TC
492 chan_count);
493 return 0;
494 }
495 for (i = 0; i < w; ++i) {
496 for (ch = 0; ch < chan_count; ++ch) {
497 *samps++ = data[ch];
498 ++count;
499 }
500 data += im->channels;
501 }
502 }
503
504 return count;
505 }
506 else {
507 return 0;
508 }
509}
510
511/*
8d14daab 512=item i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, int *chans, int chan_count)
a2f9a61c
TC
513
514Reads sample values from im for the horizontal line (l, y) to (r-1,y)
515for the channels specified by chan_mask, where bit 0 is the first
516channel.
517
518Returns the number of samples read (which should be (r-l) * bits_set(chan_mask)
519
520=cut
521*/
522static
8d14daab
TC
523i_img_dim
524i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
a2f9a61c 525 const int *chans, int chan_count) {
8d14daab
TC
526 int ch;
527 i_img_dim count, i, w;
a2f9a61c
TC
528 unsigned char *data;
529 for (ch = 0; ch < chan_count; ++ch) {
530 if (chans[ch] < 0 || chans[ch] >= im->channels) {
ddffecae
TC
531 dIMCTXim(im);
532 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
a2f9a61c
TC
533 }
534 }
535 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
536 if (r > im->xsize)
537 r = im->xsize;
538 data = im->idata + (l+y*im->xsize) * im->channels;
539 w = r - l;
540 count = 0;
541
542 if (chans) {
543 /* make sure we have good channel numbers */
544 for (ch = 0; ch < chan_count; ++ch) {
545 if (chans[ch] < 0 || chans[ch] >= im->channels) {
ddffecae
TC
546 dIMCTXim(im);
547 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
a2f9a61c
TC
548 return 0;
549 }
550 }
551 for (i = 0; i < w; ++i) {
552 for (ch = 0; ch < chan_count; ++ch) {
553 *samps++ = Sample8ToF(data[chans[ch]]);
554 ++count;
555 }
556 data += im->channels;
557 }
558 }
559 else {
560 if (chan_count <= 0 || chan_count > im->channels) {
ddffecae
TC
561 dIMCTXim(im);
562 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
a2f9a61c
TC
563 chan_count);
564 return 0;
565 }
566 for (i = 0; i < w; ++i) {
567 for (ch = 0; ch < chan_count; ++ch) {
568 *samps++ = Sample8ToF(data[ch]);
569 ++count;
570 }
571 data += im->channels;
572 }
573 }
574 return count;
575 }
576 else {
577 return 0;
578 }
579}
580
836d9f54
TC
581/*
582=item i_psamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int *chans, int chan_count)
583
584Writes sample values to im for the horizontal line (l, y) to (r-1,y)
585for the channels specified by chans, an array of int with chan_count
586elements.
587
588Returns the number of samples written (which should be (r-l) *
589bits_set(chan_mask)
590
591=cut
592*/
593
594static
595i_img_dim
596i_psamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
597 const i_sample_t *samps, const int *chans, int chan_count) {
598 int ch;
599 i_img_dim count, i, w;
600 unsigned char *data;
601
602 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
836d9f54
TC
603 if (r > im->xsize)
604 r = im->xsize;
605 data = im->idata + (l+y*im->xsize) * im->channels;
606 w = r - l;
607 count = 0;
608
609 if (chans) {
610 /* make sure we have good channel numbers */
611 /* and test if all channels specified are in the mask */
612 int all_in_mask = 1;
613 for (ch = 0; ch < chan_count; ++ch) {
614 if (chans[ch] < 0 || chans[ch] >= im->channels) {
ddffecae
TC
615 dIMCTXim(im);
616 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
836d9f54
TC
617 return -1;
618 }
619 if (!((1 << chans[ch]) & im->ch_mask))
620 all_in_mask = 0;
621 }
622 if (all_in_mask) {
623 for (i = 0; i < w; ++i) {
624 for (ch = 0; ch < chan_count; ++ch) {
625 data[chans[ch]] = *samps++;
626 ++count;
627 }
628 data += im->channels;
629 }
630 }
631 else {
632 for (i = 0; i < w; ++i) {
633 for (ch = 0; ch < chan_count; ++ch) {
634 if (im->ch_mask & (1 << (chans[ch])))
635 data[chans[ch]] = *samps;
636 ++samps;
637 ++count;
638 }
639 data += im->channels;
640 }
641 }
642 }
643 else {
644 if (chan_count <= 0 || chan_count > im->channels) {
ddffecae
TC
645 dIMCTXim(im);
646 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
836d9f54
TC
647 chan_count);
648 return -1;
649 }
650 for (i = 0; i < w; ++i) {
651 unsigned mask = 1;
652 for (ch = 0; ch < chan_count; ++ch) {
653 if (im->ch_mask & mask)
654 data[ch] = *samps;
655 ++samps;
656 ++count;
657 mask <<= 1;
658 }
659 data += im->channels;
660 }
661 }
662
663 return count;
664 }
665 else {
696cb85d 666 dIMCTXim(im);
836d9f54
TC
667 i_push_error(0, "Image position outside of image");
668 return -1;
669 }
670}
671
672/*
673=item i_psampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fsample_t *samps, int *chans, int chan_count)
674
675Writes sample values to im for the horizontal line (l, y) to (r-1,y)
676for the channels specified by chans, an array of int with chan_count
677elements.
678
679Returns the number of samples written (which should be (r-l) *
680bits_set(chan_mask)
681
682=cut
683*/
684
685static
686i_img_dim
687i_psampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
688 const i_fsample_t *samps, const int *chans, int chan_count) {
689 int ch;
690 i_img_dim count, i, w;
691 unsigned char *data;
692
693 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
836d9f54
TC
694 if (r > im->xsize)
695 r = im->xsize;
696 data = im->idata + (l+y*im->xsize) * im->channels;
697 w = r - l;
698 count = 0;
699
700 if (chans) {
701 /* make sure we have good channel numbers */
702 /* and test if all channels specified are in the mask */
703 int all_in_mask = 1;
704 for (ch = 0; ch < chan_count; ++ch) {
705 if (chans[ch] < 0 || chans[ch] >= im->channels) {
ddffecae
TC
706 dIMCTXim(im);
707 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
836d9f54
TC
708 return -1;
709 }
710 if (!((1 << chans[ch]) & im->ch_mask))
711 all_in_mask = 0;
712 }
713 if (all_in_mask) {
714 for (i = 0; i < w; ++i) {
715 for (ch = 0; ch < chan_count; ++ch) {
716 data[chans[ch]] = SampleFTo8(*samps);
717 ++samps;
718 ++count;
719 }
720 data += im->channels;
721 }
722 }
723 else {
724 for (i = 0; i < w; ++i) {
725 for (ch = 0; ch < chan_count; ++ch) {
726 if (im->ch_mask & (1 << (chans[ch])))
727 data[chans[ch]] = SampleFTo8(*samps);
728 ++samps;
729 ++count;
730 }
731 data += im->channels;
732 }
733 }
734 }
735 else {
736 if (chan_count <= 0 || chan_count > im->channels) {
ddffecae
TC
737 dIMCTXim(im);
738 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
836d9f54
TC
739 chan_count);
740 return -1;
741 }
742 for (i = 0; i < w; ++i) {
743 unsigned mask = 1;
744 for (ch = 0; ch < chan_count; ++ch) {
745 if (im->ch_mask & mask)
746 data[ch] = SampleFTo8(*samps);
747 ++samps;
748 ++count;
749 mask <<= 1;
750 }
751 data += im->channels;
752 }
753 }
754
755 return count;
756 }
757 else {
696cb85d 758 dIMCTXim(im);
836d9f54
TC
759 i_push_error(0, "Image position outside of image");
760 return -1;
761 }
762}
763
a2f9a61c
TC
764/*
765=back
766
767=head1 AUTHOR
768
769Arnar M. Hrafnkelsson <addi@umich.edu>
770
771Tony Cook <tony@develop-help.com>
772
773=head1 SEE ALSO
774
775L<Imager>
776
777=cut
778*/