File Coverage

imgdouble.c
Criterion Covered Total %
statement 250 283 88.3
branch 235 282 83.3
condition n/a
subroutine n/a
pod n/a
total 485 565 85.8


line stmt bran cond sub pod time code
1             /*
2             =head1 NAME
3              
4             imgdouble.c - implements double per sample images
5              
6             =head1 SYNOPSIS
7              
8             i_img *im = i_img_double_new(width, height, channels);
9             # use like a normal image
10              
11             =head1 DESCRIPTION
12              
13             Implements double/sample images.
14              
15             This basic implementation is required so that we have some larger
16             sample image type to work with.
17              
18             =over
19              
20             =cut
21             */
22              
23             #define IMAGER_NO_CONTEXT
24             #include "imager.h"
25             #include "imageri.h"
26              
27             static int i_ppix_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_color *val);
28             static int i_gpix_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_color *val);
29             static i_img_dim i_glin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
30             static i_img_dim i_plin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
31             static int i_ppixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val);
32             static int i_gpixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val);
33             static i_img_dim i_glinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
34             static i_img_dim i_plinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
35             static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
36             int const *chans, int chan_count);
37             static i_img_dim i_gsampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
38             int const *chans, int chan_count);
39             static i_img_dim
40             i_psamp_ddoub(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);
41             static i_img_dim
42             i_psampf_ddoub(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);
43              
44             /*
45             =item IIM_base_16bit_direct
46              
47             Base structure used to initialize a 16-bit/sample image.
48              
49             Internal.
50              
51             =cut
52             */
53             static i_img IIM_base_double_direct =
54             {
55             0, /* channels set */
56             0, 0, 0, /* xsize, ysize, bytes */
57             ~0U, /* ch_mask */
58             i_double_bits, /* bits */
59             i_direct_type, /* type */
60             0, /* virtual */
61             NULL, /* idata */
62             { 0, 0, NULL }, /* tags */
63             NULL, /* ext_data */
64              
65             i_ppix_ddoub, /* i_f_ppix */
66             i_ppixf_ddoub, /* i_f_ppixf */
67             i_plin_ddoub, /* i_f_plin */
68             i_plinf_ddoub, /* i_f_plinf */
69             i_gpix_ddoub, /* i_f_gpix */
70             i_gpixf_ddoub, /* i_f_gpixf */
71             i_glin_ddoub, /* i_f_glin */
72             i_glinf_ddoub, /* i_f_glinf */
73             i_gsamp_ddoub, /* i_f_gsamp */
74             i_gsampf_ddoub, /* i_f_gsampf */
75              
76             NULL, /* i_f_gpal */
77             NULL, /* i_f_ppal */
78             NULL, /* i_f_addcolors */
79             NULL, /* i_f_getcolors */
80             NULL, /* i_f_colorcount */
81             NULL, /* i_f_maxcolors */
82             NULL, /* i_f_findcolor */
83             NULL, /* i_f_setcolors */
84              
85             NULL, /* i_f_destroy */
86              
87             i_gsamp_bits_fb,
88             NULL, /* i_f_psamp_bits */
89              
90             i_psamp_ddoub, /* i_f_psamp */
91             i_psampf_ddoub /* i_f_psampf */
92             };
93              
94             /*
95             =item im_img_double_new(ctx, x, y, ch)
96             XX
97             =category Image creation/destruction
98             =synopsis i_img *img = im_img_double_new(aIMCTX, width, height, channels);
99             =synopsis i_img *img = i_img_double_new(width, height, channels);
100              
101             Creates a new double per sample image.
102              
103             Also callable as C.
104              
105             =cut
106             */
107             i_img *
108 136           im_img_double_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
109             size_t bytes;
110             i_img *im;
111              
112 136           im_log((aIMCTX, 1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
113             i_DFc(x), i_DFc(y), ch));
114              
115 136 100         if (x < 1 || y < 1) {
    100          
116 4           im_push_error(aIMCTX, 0, "Image sizes must be positive");
117 4           return NULL;
118             }
119 132 100         if (ch < 1 || ch > MAXCHANNELS) {
    100          
120 2           im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
121 2           return NULL;
122             }
123 130           bytes = x * y * ch * sizeof(double);
124 130 50         if (bytes / y / ch / sizeof(double) != x) {
125 0           im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
126 0           return NULL;
127             }
128            
129 130           im = im_img_alloc(aIMCTX);
130 130           *im = IIM_base_double_direct;
131 130           i_tags_new(&im->tags);
132 130           im->xsize = x;
133 130           im->ysize = y;
134 130           im->channels = ch;
135 130           im->bytes = bytes;
136 130           im->ext_data = NULL;
137 130           im->idata = mymalloc(im->bytes);
138 130           memset(im->idata, 0, im->bytes);
139 130           im_img_init(aIMCTX, im);
140            
141 130           return im;
142             }
143              
144 11818           static int i_ppix_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) {
145             i_img_dim off;
146             int ch;
147              
148 11818 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
149 4           return -1;
150              
151 11814           off = (x + y * im->xsize) * im->channels;
152 11814 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
153 47252 100         for (ch = 0; ch < im->channels; ++ch)
154 35439           ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
155             }
156             else {
157 4 100         for (ch = 0; ch < im->channels; ++ch)
158 3 100         if (im->ch_mask & (1<
159 2           ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
160             }
161              
162 11814           return 0;
163             }
164              
165 90278           static int i_gpix_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_color *val) {
166             i_img_dim off;
167             int ch;
168              
169 90278 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
170 8           return -1;
171              
172 90270           off = (x + y * im->xsize) * im->channels;
173 361118 100         for (ch = 0; ch < im->channels; ++ch)
174 270848           val->channel[ch] = SampleFTo8(((double *)im->idata)[off+ch]);
175              
176 90270           return 0;
177             }
178              
179 180019           static int i_ppixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) {
180             i_img_dim off;
181             int ch;
182              
183 180019 100         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    100          
    100          
    100          
184 4           return -1;
185              
186 180015           off = (x + y * im->xsize) * im->channels;
187 180015 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
188 720057 100         for (ch = 0; ch < im->channels; ++ch)
189 540043           ((double *)im->idata)[off+ch] = val->channel[ch];
190             }
191             else {
192 4 100         for (ch = 0; ch < im->channels; ++ch)
193 3 100         if (im->ch_mask & (1 << ch))
194 2           ((double *)im->idata)[off+ch] = val->channel[ch];
195             }
196              
197 180015           return 0;
198             }
199              
200 1581816           static int i_gpixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) {
201             i_img_dim off;
202             int ch;
203              
204 1581816 50         if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize)
    50          
    50          
    50          
205 0           return -1;
206              
207 1581816           off = (x + y * im->xsize) * im->channels;
208 6325871 100         for (ch = 0; ch < im->channels; ++ch)
209 4744055           val->channel[ch] = ((double *)im->idata)[off+ch];
210              
211 1581816           return 0;
212             }
213              
214 12           static i_img_dim i_glin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) {
215             int ch;
216             i_img_dim count, i;
217             i_img_dim off;
218 12 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
219 12 50         if (r > im->xsize)
220 0           r = im->xsize;
221 12           off = (l+y*im->xsize) * im->channels;
222 12           count = r - l;
223 136 100         for (i = 0; i < count; ++i) {
224 496 100         for (ch = 0; ch < im->channels; ++ch) {
225 372           vals[i].channel[ch] = SampleFTo8(((double *)im->idata)[off]);
226 372           ++off;
227             }
228             }
229 12           return count;
230             }
231             else {
232 0           return 0;
233             }
234             }
235              
236 2122           static i_img_dim i_plin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) {
237             int ch;
238             i_img_dim count, i;
239             i_img_dim off;
240 2122 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
241 2122 50         if (r > im->xsize)
242 0           r = im->xsize;
243 2122           off = (l+y*im->xsize) * im->channels;
244 2122           count = r - l;
245 2122 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
246 155688 100         for (i = 0; i < count; ++i) {
247 609784 100         for (ch = 0; ch < im->channels; ++ch) {
248 456217           ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
249 456217           ++off;
250             }
251             }
252             }
253             else {
254 2 100         for (i = 0; i < count; ++i) {
255 4 100         for (ch = 0; ch < im->channels; ++ch) {
256 3 100         if (im->ch_mask & (1 << ch))
257 2           ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
258 3           ++off;
259             }
260             }
261             }
262 2122           return count;
263             }
264             else {
265 0           return 0;
266             }
267             }
268              
269 7010           static i_img_dim i_glinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) {
270             int ch;
271             i_img_dim count, i;
272             i_img_dim off;
273 7010 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
274 7010 50         if (r > im->xsize)
275 0           r = im->xsize;
276 7010           off = (l+y*im->xsize) * im->channels;
277 7010           count = r - l;
278 691105 100         for (i = 0; i < count; ++i) {
279 2756903 100         for (ch = 0; ch < im->channels; ++ch) {
280 2072808           vals[i].channel[ch] = ((double *)im->idata)[off];
281 2072808           ++off;
282             }
283             }
284 7010           return count;
285             }
286             else {
287 0           return 0;
288             }
289             }
290              
291 8424           static i_img_dim i_plinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) {
292             int ch;
293             i_img_dim count, i;
294             i_img_dim off;
295 8424 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    50          
    50          
296 8423 50         if (r > im->xsize)
297 0           r = im->xsize;
298 8423           off = (l+y*im->xsize) * im->channels;
299 8423           count = r - l;
300 8423 100         if (I_ALL_CHANNELS_WRITABLE(im)) {
301 824879 100         for (i = 0; i < count; ++i) {
302 3105517 100         for (ch = 0; ch < im->channels; ++ch) {
303 2289060           ((double *)im->idata)[off] = vals[i].channel[ch];
304 2289060           ++off;
305             }
306             }
307             }
308             else {
309 2 100         for (i = 0; i < count; ++i) {
310 4 100         for (ch = 0; ch < im->channels; ++ch) {
311 3 100         if (im->ch_mask & (1 << ch))
312 2           ((double *)im->idata)[off] = vals[i].channel[ch];
313 3           ++off;
314             }
315             }
316             }
317 8423           return count;
318             }
319             else {
320 1           return 0;
321             }
322             }
323              
324 342           static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps,
325             int const *chans, int chan_count) {
326             int ch;
327             i_img_dim count, i, w;
328             i_img_dim off;
329              
330 342 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
331 342 50         if (r > im->xsize)
332 0           r = im->xsize;
333 342           off = (l+y*im->xsize) * im->channels;
334 342           w = r - l;
335 342           count = 0;
336              
337 342 100         if (chans) {
338             /* make sure we have good channel numbers */
339 8 100         for (ch = 0; ch < chan_count; ++ch) {
340 6 50         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    50          
341 0           dIMCTXim(im);
342 0           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
343 0           return 0;
344             }
345             }
346 22 100         for (i = 0; i < w; ++i) {
347 80 100         for (ch = 0; ch < chan_count; ++ch) {
348 60           *samps++ = SampleFTo8(((double *)im->idata)[off+chans[ch]]);
349 60           ++count;
350             }
351 20           off += im->channels;
352             }
353             }
354             else {
355 340 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
356 0           dIMCTXim(im);
357 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
358             chan_count);
359 0           return 0;
360             }
361 27781 100         for (i = 0; i < w; ++i) {
362 109764 100         for (ch = 0; ch < chan_count; ++ch) {
363 82323           *samps++ = SampleFTo8(((double *)im->idata)[off+ch]);
364 82323           ++count;
365             }
366 27441           off += im->channels;
367             }
368             }
369              
370 342           return count;
371             }
372             else {
373 0           return 0;
374             }
375             }
376              
377 1738           static i_img_dim i_gsampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps,
378             int const *chans, int chan_count) {
379             int ch;
380             i_img_dim count, i, w;
381             i_img_dim off;
382              
383 1738 50         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    50          
    50          
    50          
384 1738 50         if (r > im->xsize)
385 0           r = im->xsize;
386 1738           off = (l+y*im->xsize) * im->channels;
387 1738           w = r - l;
388 1738           count = 0;
389              
390 1738 100         if (chans) {
391             /* make sure we have good channel numbers */
392 2542 100         for (ch = 0; ch < chan_count; ++ch) {
393 1271 50         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    50          
394 0           dIMCTXim(im);
395 0           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
396 0           return 0;
397             }
398             }
399 150207 100         for (i = 0; i < w; ++i) {
400 297872 100         for (ch = 0; ch < chan_count; ++ch) {
401 148936           *samps++ = ((double *)im->idata)[off+chans[ch]];
402 148936           ++count;
403             }
404 148936           off += im->channels;
405             }
406             }
407             else {
408 467 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
409 0           dIMCTXim(im);
410 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
411             chan_count);
412 0           return 0;
413             }
414 42462 100         for (i = 0; i < w; ++i) {
415 169580 100         for (ch = 0; ch < chan_count; ++ch) {
416 127585           *samps++ = ((double *)im->idata)[off+ch];
417 127585           ++count;
418             }
419 41995           off += im->channels;
420             }
421             }
422              
423 1738           return count;
424             }
425             else {
426 0           return 0;
427             }
428             }
429              
430             /*
431             =item i_psamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_sample_t *samps, int *chans, int chan_count)
432              
433             Writes sample values to im for the horizontal line (l, y) to (r-1,y)
434             for the channels specified by chans, an array of int with chan_count
435             elements.
436              
437             Returns the number of samples written (which should be (r-l) *
438             bits_set(chan_mask)
439              
440             =cut
441             */
442              
443             static
444             i_img_dim
445 12           i_psamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
446             const i_sample_t *samps, const int *chans, int chan_count) {
447             int ch;
448             i_img_dim count, i, w;
449              
450 12 100         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
451             i_img_dim offset;
452 8 100         if (r > im->xsize)
453 1           r = im->xsize;
454 8           offset = (l+y*im->xsize) * im->channels;
455 8           w = r - l;
456 8           count = 0;
457              
458 8 100         if (chans) {
459             /* make sure we have good channel numbers */
460             /* and test if all channels specified are in the mask */
461 6           int all_in_mask = 1;
462 21 100         for (ch = 0; ch < chan_count; ++ch) {
463 17 100         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    100          
464 2           dIMCTXim(im);
465 2           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
466 2           return -1;
467             }
468 15 100         if (!((1 << chans[ch]) & im->ch_mask))
469 1           all_in_mask = 0;
470             }
471 4 100         if (all_in_mask) {
472 17 100         for (i = 0; i < w; ++i) {
473 54 100         for (ch = 0; ch < chan_count; ++ch) {
474 40           ((double*)im->idata)[offset + chans[ch]] = Sample8ToF(*samps);
475 40           ++samps;
476 40           ++count;
477             }
478 14           offset += im->channels;
479             }
480             }
481             else {
482 5 100         for (i = 0; i < w; ++i) {
483 4 100         for (ch = 0; ch < chan_count; ++ch) {
484 3 100         if (im->ch_mask & (1 << (chans[ch])))
485 2           ((double*)im->idata)[offset + chans[ch]] = Sample8ToF(*samps);
486            
487 3           ++samps;
488 3           ++count;
489             }
490 1           offset += im->channels;
491             }
492             }
493             }
494             else {
495 2 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
496 0           dIMCTXim(im);
497 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
498             chan_count);
499 0           return -1;
500             }
501 4 100         for (i = 0; i < w; ++i) {
502 2           unsigned mask = 1;
503 8 100         for (ch = 0; ch < chan_count; ++ch) {
504 6 100         if (im->ch_mask & mask)
505 5           ((double*)im->idata)[offset + ch] = Sample8ToF(*samps);
506              
507 6           ++samps;
508 6           ++count;
509 6           mask <<= 1;
510             }
511 2           offset += im->channels;
512             }
513             }
514              
515 6           return count;
516             }
517             else {
518 4           dIMCTXim(im);
519 4           i_push_error(0, "Image position outside of image");
520 4           return -1;
521             }
522             }
523              
524             /*
525             =item i_psampf_ddoub(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)
526              
527             Writes sample values to im for the horizontal line (l, y) to (r-1,y)
528             for the channels specified by chans, an array of int with chan_count
529             elements.
530              
531             Returns the number of samples written (which should be (r-l) *
532             bits_set(chan_mask)
533              
534             =cut
535             */
536              
537             static
538             i_img_dim
539 22           i_psampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
540             const i_fsample_t *samps, const int *chans, int chan_count) {
541             int ch;
542             i_img_dim count, i, w;
543              
544 22 100         if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
    100          
    100          
    100          
545             i_img_dim offset;
546 18 100         if (r > im->xsize)
547 1           r = im->xsize;
548 18           offset = (l+y*im->xsize) * im->channels;
549 18           w = r - l;
550 18           count = 0;
551              
552 18 100         if (chans) {
553             /* make sure we have good channel numbers */
554             /* and test if all channels specified are in the mask */
555 6           int all_in_mask = 1;
556 21 100         for (ch = 0; ch < chan_count; ++ch) {
557 17 100         if (chans[ch] < 0 || chans[ch] >= im->channels) {
    100          
558 2           dIMCTXim(im);
559 2           im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
560 2           return -1;
561             }
562 15 100         if (!((1 << chans[ch]) & im->ch_mask))
563 1           all_in_mask = 0;
564             }
565 4 100         if (all_in_mask) {
566 17 100         for (i = 0; i < w; ++i) {
567 54 100         for (ch = 0; ch < chan_count; ++ch) {
568 40           ((double*)im->idata)[offset + chans[ch]] = *samps;
569 40           ++samps;
570 40           ++count;
571             }
572 14           offset += im->channels;
573             }
574             }
575             else {
576 5 100         for (i = 0; i < w; ++i) {
577 4 100         for (ch = 0; ch < chan_count; ++ch) {
578 3 100         if (im->ch_mask & (1 << (chans[ch])))
579 2           ((double*)im->idata)[offset + chans[ch]] = *samps;
580            
581 3           ++samps;
582 3           ++count;
583             }
584 1           offset += im->channels;
585             }
586             }
587             }
588             else {
589 12 50         if (chan_count <= 0 || chan_count > im->channels) {
    50          
590 0           dIMCTXim(im);
591 0           im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
592             chan_count);
593 0           return -1;
594             }
595 114 100         for (i = 0; i < w; ++i) {
596 102           unsigned mask = 1;
597 408 100         for (ch = 0; ch < chan_count; ++ch) {
598 306 100         if (im->ch_mask & mask)
599 305           ((double*)im->idata)[offset + ch] = *samps;
600              
601 306           ++samps;
602 306           ++count;
603 306           mask <<= 1;
604             }
605 102           offset += im->channels;
606             }
607             }
608              
609 16           return count;
610             }
611             else {
612 4           dIMCTXim(im);
613 4           i_push_error(0, "Image position outside of image");
614 4           return -1;
615             }
616             }
617              
618             /*
619             =item i_img_to_drgb(im)
620              
621             =category Image creation
622              
623             Returns a double/sample version of the supplied image.
624              
625             Returns the image on success, or NULL on failure.
626              
627             =cut
628             */
629              
630             i_img *
631 2           i_img_to_drgb(i_img *im) {
632             i_img *targ;
633             i_fcolor *line;
634             i_img_dim y;
635 2           dIMCTXim(im);
636              
637 2           targ = im_img_double_new(aIMCTX, im->xsize, im->ysize, im->channels);
638 2 50         if (!targ)
639 0           return NULL;
640 2           line = mymalloc(sizeof(i_fcolor) * im->xsize);
641 162 100         for (y = 0; y < im->ysize; ++y) {
642 160           i_glinf(im, 0, im->xsize, y, line);
643 160           i_plinf(targ, 0, im->xsize, y, line);
644             }
645              
646 2           myfree(line);
647              
648 2           return targ;
649             }
650              
651             /*
652             =back
653              
654             =head1 AUTHOR
655              
656             Tony Cook
657              
658             =head1 SEE ALSO
659              
660             Imager(3)
661              
662             =cut
663             */