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) { | |
19 | int x, y, t, ttx, tty; | |
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) { | |
72 | int i; | |
73 | if (out_channels == in_channels) | |
74 | return; | |
75 | if (count == 0) | |
76 | return; | |
77 | ||
78 | switch (out_channels) { | |
79 | case 1: | |
80 | { | |
81 | switch (in_channels) { | |
82 | case 2: | |
83 | /* apply alpha against a black background */ | |
84 | while (count) { | |
85 | colors->channel[0] = colors->channel[0] * colors->channel[1] / IM_SAMPLE_MAX; | |
86 | ++colors; | |
87 | --count; | |
88 | } | |
89 | return; | |
90 | ||
91 | case 3: | |
92 | /* convert to grey */ | |
93 | while (count) { | |
94 | colors->channel[0] = IM_ROUND(color_to_grey(colors)); | |
95 | ++colors; | |
96 | --count; | |
97 | } | |
98 | return; | |
99 | ||
100 | case 4: | |
101 | while (count) { | |
102 | colors->channel[0] = IM_ROUND(color_to_grey(colors) * colors->channel[3] / IM_SAMPLE_MAX); | |
103 | ++colors; | |
104 | --count; | |
105 | } | |
106 | return; | |
107 | ||
108 | default: | |
109 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
110 | return; /* avoid warnings */ | |
111 | } | |
112 | } | |
113 | ||
114 | case 2: | |
115 | { | |
116 | switch (in_channels) { | |
117 | case 1: | |
118 | while (count) { | |
119 | colors->channel[1] = IM_SAMPLE_MAX; | |
120 | ++colors; | |
121 | --count; | |
122 | } | |
123 | return; | |
124 | ||
125 | case 3: | |
126 | while (count) { | |
127 | colors->channel[0] = IM_ROUND(color_to_grey(colors)); | |
128 | colors->channel[1] = IM_SAMPLE_MAX; | |
129 | ++colors; | |
130 | --count; | |
131 | } | |
132 | return; | |
133 | ||
134 | case 4: | |
135 | while (count) { | |
136 | colors->channel[0] = IM_ROUND(color_to_grey(colors)); | |
137 | colors->channel[1] = colors->channel[3]; | |
138 | ++colors; | |
139 | --count; | |
140 | } | |
141 | return; | |
142 | ||
143 | default: | |
144 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
145 | return; /* avoid warnings */ | |
146 | } | |
147 | } | |
148 | ||
149 | case 3: | |
150 | { | |
151 | switch (in_channels) { | |
152 | case 1: | |
153 | while (count) { | |
154 | colors->channel[1] = colors->channel[2] = colors->channel[0]; | |
155 | ++colors; | |
156 | --count; | |
157 | } | |
158 | return; | |
159 | ||
160 | case 2: | |
161 | while (count) { | |
162 | int alpha = colors->channel[1]; | |
163 | colors->channel[0] = colors->channel[1] = colors->channel[2] = | |
164 | IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX); | |
165 | ++colors; | |
166 | --count; | |
167 | } | |
168 | return; | |
169 | ||
170 | case 4: | |
171 | while (count) { | |
172 | int alpha = colors->channel[3]; | |
173 | colors->channel[0] = | |
174 | IM_ROUND(colors->channel[0] * alpha / IM_SAMPLE_MAX); | |
175 | colors->channel[1] = | |
176 | IM_ROUND(colors->channel[1] * alpha / IM_SAMPLE_MAX); | |
177 | colors->channel[2] = | |
178 | IM_ROUND(colors->channel[2] * alpha / IM_SAMPLE_MAX); | |
179 | ++colors; | |
180 | --count; | |
181 | } | |
182 | return; | |
183 | ||
184 | default: | |
185 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
186 | return; /* avoid warnings */ | |
187 | } | |
188 | } | |
189 | ||
190 | case 4: | |
191 | { | |
192 | switch (in_channels) { | |
193 | case 1: | |
194 | while (count) { | |
195 | colors->channel[1] = colors->channel[2] = colors->channel[0]; | |
196 | colors->channel[3] = IM_SAMPLE_MAX; | |
197 | ++colors; | |
198 | --count; | |
199 | } | |
200 | return; | |
201 | ||
202 | case 2: | |
203 | while (count) { | |
204 | colors->channel[3] = colors->channel[1]; | |
205 | colors->channel[1] = colors->channel[2] = colors->channel[0]; | |
206 | ++colors; | |
207 | --count; | |
208 | } | |
209 | return; | |
210 | ||
211 | case 3: | |
212 | while (count) { | |
213 | colors->channel[3] = IM_SAMPLE_MAX; | |
214 | ++colors; | |
215 | --count; | |
216 | } | |
217 | return; | |
218 | ||
219 | default: | |
220 | i_fatal(3, "i_adapt_colors: in_channels of %d invalid\n", in_channels); | |
221 | return; /* avoid warnings */ | |
222 | } | |
223 | } | |
224 | ||
225 | default: | |
226 | i_fatal(3, "i_adapt_colors: out_channels of %d invalid\n", out_channels); | |
227 | return; /* avoid warnings */ | |
228 | } | |
229 | } | |
230 | ||
6e4af7d4 TC |
231 | void |
232 | #ifdef IM_EIGHT_BIT | |
233 | i_adapt_colors_bg | |
234 | #else | |
235 | i_adapt_fcolors_bg | |
236 | #endif | |
237 | (int out_channels, int in_channels, IM_COLOR *colors, | |
238 | size_t count, IM_COLOR const *bg) { | |
239 | if (out_channels == in_channels) | |
240 | return; | |
241 | if (count == 0) | |
242 | return; | |
243 | ||
244 | switch (out_channels) { | |
245 | case 2: | |
246 | case 4: | |
247 | IM_ADAPT_COLORS(out_channels, in_channels, colors, count); | |
248 | return; | |
249 | ||
250 | case 1: | |
251 | switch (in_channels) { | |
252 | case 3: | |
253 | IM_ADAPT_COLORS(out_channels, in_channels, colors, count); | |
254 | return; | |
255 | ||
256 | case 2: | |
257 | { | |
258 | /* apply alpha against our given background */ | |
259 | IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); | |
260 | while (count) { | |
261 | colors->channel[0] = | |
262 | (colors->channel[0] * colors->channel[1] + | |
263 | grey_bg * (IM_SAMPLE_MAX - colors->channel[1])) / IM_SAMPLE_MAX; | |
264 | ++colors; | |
265 | --count; | |
266 | } | |
267 | } | |
268 | break; | |
269 | ||
270 | case 4: | |
271 | { | |
272 | IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); | |
273 | while (count) { | |
274 | IM_WORK_T src_grey = IM_ROUND(color_to_grey(colors)); | |
275 | colors->channel[0] = | |
276 | (src_grey * colors->channel[3] | |
277 | + grey_bg * (IM_SAMPLE_MAX - colors->channel[3])) / IM_SAMPLE_MAX; | |
278 | ++colors; | |
279 | --count; | |
280 | } | |
281 | } | |
282 | break; | |
283 | } | |
284 | break; | |
285 | ||
286 | case 3: | |
287 | switch (in_channels) { | |
288 | case 1: | |
289 | IM_ADAPT_COLORS(out_channels, in_channels, colors, count); | |
290 | return; | |
291 | ||
292 | case 2: | |
293 | { | |
294 | while (count) { | |
295 | int ch; | |
296 | IM_WORK_T src_grey = colors->channel[0]; | |
297 | IM_WORK_T src_alpha = colors->channel[1]; | |
298 | for (ch = 0; ch < 3; ++ch) { | |
299 | colors->channel[ch] = | |
300 | (src_grey * src_alpha | |
301 | + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha)) | |
302 | / IM_SAMPLE_MAX; | |
303 | } | |
304 | ++colors; | |
305 | --count; | |
306 | } | |
307 | } | |
308 | break; | |
309 | ||
310 | case 4: | |
311 | { | |
312 | while (count) { | |
313 | int ch; | |
314 | IM_WORK_T src_alpha = colors->channel[3]; | |
315 | for (ch = 0; ch < 3; ++ch) { | |
316 | colors->channel[ch] = | |
317 | (colors->channel[ch] * src_alpha | |
318 | + bg->channel[ch] * (IM_SAMPLE_MAX - src_alpha)) | |
319 | / IM_SAMPLE_MAX; | |
320 | } | |
321 | ++colors; | |
322 | --count; | |
323 | } | |
324 | } | |
325 | break; | |
326 | } | |
327 | break; | |
328 | } | |
329 | ||
330 | } | |
331 | ||
9b1ec2b8 TC |
332 | #/code |
333 |