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