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