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