Commit | Line | Data |
---|---|---|
9b1ec2b8 TC |
1 | #include "imager.h" |
2 | ||
3 | /* | |
4 | =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty) | |
5 | ||
6 | =category Image | |
7 | ||
8 | Copies image data from the area (x1,y1)-[x2,y2] in the source image to | |
9 | a rectangle the same size with it's top-left corner at (tx,ty) in the | |
10 | destination image. | |
11 | ||
12 | If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped. | |
13 | ||
14 | =cut | |
15 | */ | |
16 | ||
17 | void | |
18 | i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) { | |
a827f5b4 | 19 | int y, t, ttx, tty; |
9b1ec2b8 TC |
20 | |
21 | if (x2<x1) { t=x1; x1=x2; x2=t; } | |
22 | if (y2<y1) { t=y1; y1=y2; y2=t; } | |
23 | if (tx < 0) { | |
24 | /* adjust everything equally */ | |
25 | x1 += -tx; | |
26 | x2 += -tx; | |
27 | tx = 0; | |
28 | } | |
29 | if (ty < 0) { | |
30 | y1 += -ty; | |
31 | y2 += -ty; | |
32 | ty = 0; | |
33 | } | |
34 | if (x1 >= src->xsize || y1 >= src->ysize) | |
35 | return; /* nothing to do */ | |
36 | if (x2 > src->xsize) | |
37 | x2 = src->xsize; | |
38 | if (y2 > src->ysize) | |
39 | y2 = src->ysize; | |
40 | if (x1 == x2 || y1 == y2) | |
41 | return; /* nothing to do */ | |
42 | ||
43 | mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n", | |
44 | im, src, x1, y1, x2, y2, tx, ty)); | |
45 | ||
46 | #code im->bits == i_8_bits | |
47 | IM_COLOR *row = mymalloc(sizeof(IM_COLOR) * (x2-x1)); | |
48 | tty = ty; | |
49 | for(y=y1; y<y2; y++) { | |
50 | ttx = tx; | |
51 | IM_GLIN(src, x1, x2, y, row); | |
52 | if (src->channels != im->channels) | |
53 | IM_ADAPT_COLORS(im->channels, src->channels, row, x2-x1); | |
54 | IM_PLIN(im, tx, tx+x2-x1, tty, row); | |
55 | tty++; | |
56 | } | |
57 | myfree(row); | |
58 | #/code | |
59 | } | |
60 | ||
61 | #define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071) | |
62 | ||
63 | #code | |
64 | void | |
65 | #ifdef IM_EIGHT_BIT | |
66 | i_adapt_colors | |
67 | #else | |
68 | i_adapt_fcolors | |
69 | #endif | |
70 | (int out_channels, int in_channels, IM_COLOR *colors, | |
71 | size_t count) { | |
9b1ec2b8 TC |
72 | if (out_channels == in_channels) |
73 | return; | |
74 | if (count == 0) | |
75 | return; | |
76 | ||
77 | switch (out_channels) { | |
78 | case 1: | |
79 | { | |
80 | switch (in_channels) { | |
81 | case 2: | |
82 | /* apply alpha against a black background */ | |
83 | while (count) { | |
84 | colors->channel[0] = colors->channel[0] * colors->channel[1] / IM_SAMPLE_MAX; | |
85 | ++colors; | |
86 | --count; | |
87 | } | |
88 | return; | |
89 | ||
90 | case 3: | |
91 | /* convert to grey */ | |
92 | while (count) { | |
93 | colors->channel[0] = IM_ROUND(color_to_grey(colors)); | |
94 | ++colors; | |
95 | --count; | |
96 | } | |
97 | return; | |
98 | ||
99 | case 4: | |
100 | while (count) { | |
101 | colors->channel[0] = IM_ROUND(color_to_grey(colors) * colors->channel[3] / IM_SAMPLE_MAX); | |
102 | ++colors; | |
103 | --count; | |
104 | } | |
105 | return; | |
106 | ||
107 | default: | |
108 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
109 | return; /* avoid warnings */ | |
110 | } | |
111 | } | |
112 | ||
113 | case 2: | |
114 | { | |
115 | switch (in_channels) { | |
116 | case 1: | |
117 | while (count) { | |
118 | colors->channel[1] = IM_SAMPLE_MAX; | |
119 | ++colors; | |
120 | --count; | |
121 | } | |
122 | return; | |
123 | ||
124 | case 3: | |
125 | while (count) { | |
126 | colors->channel[0] = IM_ROUND(color_to_grey(colors)); | |
127 | colors->channel[1] = IM_SAMPLE_MAX; | |
128 | ++colors; | |
129 | --count; | |
130 | } | |
131 | return; | |
132 | ||
133 | case 4: | |
134 | while (count) { | |
135 | colors->channel[0] = IM_ROUND(color_to_grey(colors)); | |
136 | colors->channel[1] = colors->channel[3]; | |
137 | ++colors; | |
138 | --count; | |
139 | } | |
140 | return; | |
141 | ||
142 | default: | |
143 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
144 | return; /* avoid warnings */ | |
145 | } | |
146 | } | |
147 | ||
148 | case 3: | |
149 | { | |
150 | switch (in_channels) { | |
151 | case 1: | |
152 | while (count) { | |
153 | colors->channel[1] = colors->channel[2] = colors->channel[0]; | |
154 | ++colors; | |
155 | --count; | |
156 | } | |
157 | return; | |
158 | ||
159 | case 2: | |
160 | while (count) { | |
161 | int alpha = colors->channel[1]; | |
162 | colors->channel[0] = colors->channel[1] = colors->channel[2] = | |
163 | IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX); | |
164 | ++colors; | |
165 | --count; | |
166 | } | |
167 | return; | |
168 | ||
169 | case 4: | |
170 | while (count) { | |
171 | int alpha = colors->channel[3]; | |
172 | colors->channel[0] = | |
173 | IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX); | |
174 | colors->channel[1] = | |
175 | IM_ROUND(colors->channel[1] * alpha / IM_SAMPLE_MAX); | |
176 | colors->channel[2] = | |
177 | IM_ROUND(colors->channel[2] * alpha / IM_SAMPLE_MAX); | |
178 | ++colors; | |
179 | --count; | |
180 | } | |
181 | return; | |
182 | ||
183 | default: | |
184 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
185 | return; /* avoid warnings */ | |
186 | } | |
187 | } | |
188 | ||
189 | case 4: | |
190 | { | |
191 | switch (in_channels) { | |
192 | case 1: | |
193 | while (count) { | |
194 | colors->channel[1] = colors->channel[2] = colors->channel[0]; | |
195 | colors->channel[3] = IM_SAMPLE_MAX; | |
196 | ++colors; | |
197 | --count; | |
198 | } | |
199 | return; | |
200 | ||
201 | case 2: | |
202 | while (count) { | |
203 | colors->channel[3] = colors->channel[1]; | |
204 | colors->channel[1] = colors->channel[2] = colors->channel[0]; | |
205 | ++colors; | |
206 | --count; | |
207 | } | |
208 | return; | |
209 | ||
210 | case 3: | |
211 | while (count) { | |
212 | colors->channel[3] = IM_SAMPLE_MAX; | |
213 | ++colors; | |
214 | --count; | |
215 | } | |
216 | return; | |
217 | ||
218 | default: | |
219 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
220 | return; /* avoid warnings */ | |
221 | } | |
222 | } | |
223 | ||
224 | default: | |
225 | i_fatal(3, "i_adapt_colors: out_channels of %d invalid\n", out_channels); | |
226 | return; /* avoid warnings */ | |
227 | } | |
228 | } | |
229 | ||
6e4af7d4 TC |
230 | void |
231 | #ifdef IM_EIGHT_BIT | |
232 | i_adapt_colors_bg | |
233 | #else | |
234 | i_adapt_fcolors_bg | |
235 | #endif | |
236 | (int out_channels, int in_channels, IM_COLOR *colors, | |
237 | size_t count, IM_COLOR const *bg) { | |
238 | if (out_channels == in_channels) | |
239 | return; | |
240 | if (count == 0) | |
241 | return; | |
242 | ||
243 | switch (out_channels) { | |
244 | case 2: | |
245 | case 4: | |
246 | IM_ADAPT_COLORS(out_channels, in_channels, colors, count); | |
247 | return; | |
248 | ||
249 | case 1: | |
250 | switch (in_channels) { | |
251 | case 3: | |
252 | IM_ADAPT_COLORS(out_channels, in_channels, colors, count); | |
253 | return; | |
254 | ||
255 | case 2: | |
256 | { | |
257 | /* apply alpha against our given background */ | |
258 | IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); | |
259 | while (count) { | |
260 | colors->channel[0] = | |
261 | (colors->channel[0] * colors->channel[1] + | |
262 | grey_bg * (IM_SAMPLE_MAX - colors->channel[1])) / IM_SAMPLE_MAX; | |
263 | ++colors; | |
264 | --count; | |
265 | } | |
266 | } | |
267 | break; | |
268 | ||
269 | case 4: | |
270 | { | |
271 | IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); | |
272 | while (count) { | |
273 | IM_WORK_T src_grey = IM_ROUND(color_to_grey(colors)); | |
274 | colors->channel[0] = | |
275 | (src_grey * colors->channel[3] | |
276 | + grey_bg * (IM_SAMPLE_MAX - colors->channel[3])) / IM_SAMPLE_MAX; | |
277 | ++colors; | |
278 | --count; | |
279 | } | |
280 | } | |
281 | break; | |
282 | } | |
283 | break; | |
284 | ||
285 | case 3: | |
286 | switch (in_channels) { | |
287 | case 1: | |
288 | IM_ADAPT_COLORS(out_channels, in_channels, colors, count); | |
289 | return; | |
290 | ||
291 | case 2: | |
292 | { | |
293 | while (count) { | |
294 | int ch; | |
295 | IM_WORK_T src_grey = colors->channel[0]; | |
296 | IM_WORK_T src_alpha = colors->channel[1]; | |
297 | for (ch = 0; ch < 3; ++ch) { | |
298 | colors->channel[ch] = | |
299 | (src_grey * src_alpha | |
300 | + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha)) | |
301 | / IM_SAMPLE_MAX; | |
302 | } | |
303 | ++colors; | |
304 | --count; | |
305 | } | |
306 | } | |
307 | break; | |
308 | ||
309 | case 4: | |
310 | { | |
311 | while (count) { | |
312 | int ch; | |
313 | IM_WORK_T src_alpha = colors->channel[3]; | |
314 | for (ch = 0; ch < 3; ++ch) { | |
315 | colors->channel[ch] = | |
316 | (colors->channel[ch] * src_alpha | |
317 | + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha)) | |
318 | / IM_SAMPLE_MAX; | |
319 | } | |
320 | ++colors; | |
321 | --count; | |
322 | } | |
323 | } | |
324 | break; | |
325 | } | |
326 | break; | |
327 | } | |
328 | ||
329 | } | |
330 | ||
9b1ec2b8 TC |
331 | #/code |
332 |