combine() - was leaking malloc()ed row buffers
[imager.git] / combine.im
1 /*
2 =head1 NAME
3
4 combine.im - combining channels into an image
5
6 =head1 SYNOPSIS
7
8   out = i_combine(imgs, channels, count);
9
10 =head1 DESCRIPTION
11
12 Combines channels from the input images into an output image.
13
14 =over
15
16 =cut
17 */
18
19 #include "imager.h"
20
21 i_img *
22 i_combine(i_img **imgs, const int *channels, int in_count) {
23   i_img *out = NULL;
24   int maxbits = 0;
25   i_img *maximg = NULL;
26   int i;
27   i_img_dim width, height;
28   i_img_dim x, y;
29
30   i_clear_error();
31   if (in_count <= 0) {
32     i_push_error(0, "At least one image must be supplied");
33     return NULL;
34   }
35   if (in_count > MAXCHANNELS) {
36     i_push_errorf(0, "Maximum of %d channels, you supplied %d",
37                   MAXCHANNELS, in_count);
38     return NULL;
39   }
40
41   width = imgs[0]->xsize;
42   height = imgs[0]->ysize;
43   for (i = 0; i < in_count; ++i) {
44     if (imgs[i]->bits > maxbits) {
45       maximg = imgs[i];
46       maxbits = maximg->bits;
47     }
48     if (imgs[i]->xsize < width)
49       width = imgs[i]->xsize;
50     if (imgs[i]->ysize < height)
51       height = imgs[i]->ysize;
52     if (channels[i] < 0) {
53       i_push_error(0, "Channel numbers must be zero or positive");
54       return NULL;
55     }
56     if (channels[i] >= imgs[i]->channels) {
57       i_push_errorf(0, "Channel %d for image %d is too high (%d channels)",
58                     channels[i], i, imgs[i]->channels);
59       return NULL;
60     }
61   }
62
63   out = i_sametype_chans(maximg, width, height, in_count);
64   if (!out)
65     return NULL;
66 #code maxbits <= i_8_bits
67   IM_SAMPLE_T *in_row = mymalloc(sizeof(IM_SAMPLE_T) * width);
68   IM_COLOR *out_row = mymalloc(sizeof(IM_COLOR) * width);
69
70   for (y = 0; y < height; ++y) {
71     for (i = 0; i < in_count; ++i) {
72       IM_GSAMP(imgs[i], 0, width, y, in_row, channels + i, 1);
73       for (x = 0; x < width; ++x)
74         out_row[x].channel[i] = in_row[x];
75     }
76     IM_PLIN(out, 0, width, y, out_row);
77   }
78   myfree(out_row);
79   myfree(in_row);
80 #/code
81
82   return out;
83 }