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