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, | |
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 | ||
143 | int | |
144 | i_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 | } |