0.84 release
[imager.git] / compose.im
CommitLineData
9b1ec2b8
TC
1#include "imager.h"
2#include "imrender.h"
3#include "imageri.h"
4
5int
6i_compose_mask(i_img *out, i_img *src, i_img *mask,
7 int out_left, int out_top,
8 int src_left, int src_top,
9 int mask_left, int mask_top,
10 int width, int height,
11 int combine,
12 double opacity) {
13 i_render r;
14 int dy;
15 i_fill_combine_f combinef_8;
16 i_fill_combinef_f combinef_double;
17 int channel_zero = 0;
18
618a3282
TC
19 mm_log((1, "i_compose_mask(out %p, src %p, mask %p, out(%d, %d), src(%d, %d),"
20 " mask(%d,%d), size(%d,%d), combine %d opacity %f\n", out, src,
21 mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width,
22 height, combine, opacity));
23
9b1ec2b8
TC
24 i_clear_error();
25 if (out_left >= out->xsize
26 || out_top >= out->ysize
27 || src_left >= src->xsize
28 || src_top >= src->ysize
29 || width <= 0
30 || height <= 0
31 || out_left + width <= 0
32 || out_top + height <= 0
33 || src_left + width <= 0
34 || src_top + height <= 0
35 || mask_left >= mask->xsize
36 || mask_top >= mask->ysize
37 || mask_left + width <= 0
38 || mask_top + height <= 0)
39 return 0;
40
41 if (out_left < 0) {
42 width = out_left + width;
618a3282
TC
43 src_left -= out_left;
44 mask_left -= out_left;
9b1ec2b8
TC
45 out_left = 0;
46 }
47 if (out_left + width > out->xsize)
48 width = out->xsize - out_left;
49
50 if (out_top < 0) {
51 height = out_top + height;
618a3282
TC
52 mask_top -= out_top;
53 src_top -= out_top;
9b1ec2b8
TC
54 out_top = 0;
55 }
56 if (out_top + height > out->ysize)
57 height = out->ysize - out_top;
58
59 if (src_left < 0) {
60 width = src_left + width;
618a3282
TC
61 out_left -= src_left;
62 mask_left -= src_left;
9b1ec2b8
TC
63 src_left = 0;
64 }
65 if (src_left + width > src->xsize)
66 width = src->xsize - src_left;
67
68 if (src_top < 0) {
69 height = src_top + height;
618a3282
TC
70 out_top -= src_top;
71 mask_top -= src_top;
9b1ec2b8
TC
72 src_top = 0;
73 }
74 if (src_top + height > src->ysize)
618a3282 75 height = src->ysize - src_top;
9b1ec2b8
TC
76
77 if (mask_left < 0) {
78 width = mask_left + width;
618a3282
TC
79 out_left -= mask_left;
80 src_left -= mask_left;
9b1ec2b8
TC
81 mask_left = 0;
82 }
83 if (mask_left + width > mask->xsize)
84 width = mask->xsize - mask_left;
85
86 if (mask_top < 0) {
618a3282
TC
87 height = mask_top + height;
88 src_top -= mask_top;
89 out_top -= mask_top;
9b1ec2b8
TC
90 mask_top = 0;
91 }
92 if (mask_top + height > mask->ysize)
618a3282 93 height = mask->ysize - mask_top;
9b1ec2b8
TC
94
95 if (opacity > 1.0)
96 opacity = 1.0;
618a3282
TC
97 else if (opacity <= 0) {
98 i_push_error(0, "opacity must be positive");
9b1ec2b8 99 return 0;
618a3282
TC
100 }
101
102 mm_log((1, "after adjustments: (out(%d, %d), src(%d, %d),"
103 " mask(%d,%d), size(%d,%d)\n",
104 out_left, out_top, src_left, src_top, mask_left, mask_top, width,
105 height));
9b1ec2b8
TC
106
107 i_get_combine(combine, &combinef_8, &combinef_double);
108
109 i_render_init(&r, out, width);
110#code out->bits <= 8 && src->bits<= 8 && mask->bits <= 8
111 IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
112 IM_SAMPLE_T *mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
113 int adapt_channels = out->channels;
114
115 if (adapt_channels == 1 || adapt_channels == 3)
116 ++adapt_channels;
117
118 for (dy = 0; dy < height; ++dy) {
119 IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
120 IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
121 IM_GSAMP(mask, mask_left, mask_left + width, mask_top + dy,
122 mask_line, &channel_zero, 1);
123 if (opacity < 1.0) {
124 int i;
125 IM_SAMPLE_T *maskp = mask_line;
126 for (i = 0; i < width; ++i) {
127 *maskp = IM_ROUND(*maskp * opacity);
128 ++maskp;
129 }
130 }
131 IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
132 IM_SUFFIX(combinef));
133 }
134 myfree(src_line);
135 myfree(mask_line);
136
137#/code
138 i_render_done(&r);
139
140 return 1;
141}
142
143int
144i_compose(i_img *out, i_img *src,
145 int out_left, int out_top,
146 int src_left, int src_top,
147 int width, int height,
148 int combine,
149 double opacity) {
150 i_render r;
151 int dy;
152 i_fill_combine_f combinef_8;
153 i_fill_combinef_f combinef_double;
154
618a3282
TC
155 mm_log((1, "i_compose(out %p, src %p, out(%d, %d), src(%d, %d), size(%d,%d),"
156 " combine %d opacity %f\n", out, src, out_left, out_top,
157 src_left, src_top, width, height, combine, opacity));
158
9b1ec2b8
TC
159 i_clear_error();
160 if (out_left >= out->xsize
161 || out_top >= out->ysize
162 || src_left >= src->xsize
163 || src_top >= src->ysize
164 || width <= 0
165 || height <= 0
166 || out_left + width <= 0
167 || out_top + height <= 0
168 || src_left + width <= 0
169 || src_top + height <= 0)
170 return 0;
171
172 if (out_left < 0) {
173 width = out_left + width;
618a3282 174 src_left -= out_left;
9b1ec2b8
TC
175 out_left = 0;
176 }
177 if (out_left + width > out->xsize)
178 width = out->xsize - out_left;
179
180 if (out_top < 0) {
181 height = out_top + height;
618a3282 182 src_top -= out_top;
9b1ec2b8
TC
183 out_top = 0;
184 }
185 if (out_top + height > out->ysize)
186 height = out->ysize - out_top;
187
188 if (src_left < 0) {
189 width = src_left + width;
618a3282 190 out_left -= src_left;
9b1ec2b8
TC
191 src_left = 0;
192 }
193 if (src_left + width > src->xsize)
194 width = src->xsize - src_left;
195
196 if (src_top < 0) {
197 height = src_top + height;
618a3282 198 out_top -= src_top;
9b1ec2b8
TC
199 src_top = 0;
200 }
201 if (src_top + height > src->ysize)
618a3282 202 height = src->ysize - src_top;
9b1ec2b8
TC
203
204 if (opacity > 1.0)
205 opacity = 1.0;
618a3282
TC
206 else if (opacity <= 0) {
207 i_push_error(0, "opacity must be positive");
9b1ec2b8 208 return 0;
618a3282 209 }
9b1ec2b8
TC
210
211 i_get_combine(combine, &combinef_8, &combinef_double);
212
213 i_render_init(&r, out, width);
214#code out->bits <= 8 && src->bits <= 8
215 IM_COLOR *src_line = mymalloc(sizeof(IM_COLOR) * width);
216 IM_SAMPLE_T *mask_line = NULL;
217 int adapt_channels = out->channels;
218
219 if (opacity != 1.0) {
220 int i;
221 IM_SAMPLE_T mask_value = IM_ROUND(opacity * IM_SAMPLE_MAX);
222 mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
223
224 for (i = 0; i < width; ++i)
225 mask_line[i] = mask_value;
226 }
227
228 if (adapt_channels == 1 || adapt_channels == 3)
229 ++adapt_channels;
230
231 for (dy = 0; dy < height; ++dy) {
232 IM_GLIN(src, src_left, src_left + width, src_top + dy, src_line);
233 IM_ADAPT_COLORS(adapt_channels, src->channels, src_line, width);
234 IM_RENDER_LINE(&r, out_left, out_top+dy, width, mask_line, src_line,
235 IM_SUFFIX(combinef));
236 }
237 myfree(src_line);
238 if (mask_line)
239 myfree(mask_line);
240
241#/code
242 i_render_done(&r);
243
244 return 1;
245}