Mercurial > vba-linux
comparison src/filters/bilinear.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 /** Code adapted from Exult source code by Forgotten | |
2 ** Scale.cc - Trying to scale with bilinear interpolation. | |
3 ** | |
4 ** Written: 6/14/00 - JSF | |
5 **/ | |
6 | |
7 #include "../common/System.h" | |
8 | |
9 static u8 row_cur[3 * 322]; | |
10 static u8 row_next[3 * 322]; | |
11 | |
12 static u8 *rgb_row_cur = row_cur; | |
13 static u8 *rgb_row_next = row_next; | |
14 | |
15 #ifdef RGB | |
16 #undef RGB // wingdi.h has it | |
17 #endif | |
18 #define RGB(r, g, b) \ | |
19 ((r) >> 3) << systemRedShift | \ | |
20 ((g) >> 3) << systemGreenShift | \ | |
21 ((b) >> 3) << systemBlueShift \ | |
22 | |
23 static void fill_rgb_row_16(u16 *from, int src_width, u8 *row, int width) | |
24 { | |
25 u8 *copy_start = row + src_width * 3; | |
26 u8 *all_stop = row + width * 3; | |
27 while (row < copy_start) | |
28 { | |
29 u16 color = *from++; | |
30 *row++ = ((color >> systemRedShift) & 0x1f) << 3; | |
31 *row++ = ((color >> systemGreenShift) & 0x1f) << 3; | |
32 *row++ = ((color >> systemBlueShift) & 0x1f) << 3; | |
33 } | |
34 // any remaining elements to be written to 'row' are a replica of the | |
35 // preceding pixel | |
36 u8 *p = row - 3; | |
37 while (row < all_stop) | |
38 { | |
39 // we're guaranteed three elements per pixel; could unroll the loop | |
40 // further, especially with a Duff's Device, but the gains would be | |
41 // probably limited (judging by profiler output) | |
42 *row++ = *p++; | |
43 *row++ = *p++; | |
44 *row++ = *p++; | |
45 } | |
46 } | |
47 | |
48 static void fill_rgb_row_32(u32 *from, int src_width, u8 *row, int width) | |
49 { | |
50 u8 *copy_start = row + src_width * 3; | |
51 u8 *all_stop = row + width * 3; | |
52 while (row < copy_start) | |
53 { | |
54 u32 color = *from++; | |
55 *row++ = ((color >> systemRedShift) & 0x1f) << 3; | |
56 *row++ = ((color >> systemGreenShift) & 0x1f) << 3; | |
57 *row++ = ((color >> systemBlueShift) & 0x1f) << 3; | |
58 } | |
59 // any remaining elements to be written to 'row' are a replica of the | |
60 // preceding pixel | |
61 u8 *p = row - 3; | |
62 while (row < all_stop) | |
63 { | |
64 // we're guaranteed three elements per pixel; could unroll the loop | |
65 // further, especially with a Duff's Device, but the gains would be | |
66 // probably limited (judging by profiler output) | |
67 *row++ = *p++; | |
68 *row++ = *p++; | |
69 *row++ = *p++; | |
70 } | |
71 } | |
72 | |
73 void Bilinear(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, | |
74 u8 *dstPtr, u32 dstPitch, int width, int height) | |
75 { | |
76 u16 *to = (u16 *)dstPtr; | |
77 u16 *to_odd = (u16 *)(dstPtr + dstPitch); | |
78 | |
79 int from_width = width; | |
80 u16 *from = (u16 *)srcPtr; | |
81 fill_rgb_row_16(from, from_width, rgb_row_cur, width + 1); | |
82 | |
83 for (int y = 0; y < height; y++) | |
84 { | |
85 u16 *from_orig = from; | |
86 u16 *to_orig = to; | |
87 | |
88 if (y + 1 < height) | |
89 fill_rgb_row_16(from + width + 2, from_width, rgb_row_next, | |
90 width + 1); | |
91 else | |
92 fill_rgb_row_16(from, from_width, rgb_row_next, width + 1); | |
93 | |
94 // every pixel in the src region, is extended to 4 pixels in the | |
95 // destination, arranged in a square 'quad'; if the current src | |
96 // pixel is 'a', then in what follows 'b' is the src pixel to the | |
97 // right, 'c' is the src pixel below, and 'd' is the src pixel to | |
98 // the right and down | |
99 u8 *cur_row = rgb_row_cur; | |
100 u8 *next_row = rgb_row_next; | |
101 u8 *ar = cur_row++; | |
102 u8 *ag = cur_row++; | |
103 u8 *ab = cur_row++; | |
104 u8 *cr = next_row++; | |
105 u8 *cg = next_row++; | |
106 u8 *cb = next_row++; | |
107 for (int x = 0; x < width; x++) | |
108 { | |
109 u8 *br = cur_row++; | |
110 u8 *bg = cur_row++; | |
111 u8 *bb = cur_row++; | |
112 u8 *dr = next_row++; | |
113 u8 *dg = next_row++; | |
114 u8 *db = next_row++; | |
115 | |
116 // upper left pixel in quad: just copy it in | |
117 *to++ = RGB(*ar, *ag, *ab); | |
118 | |
119 // upper right | |
120 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); | |
121 | |
122 // lower left | |
123 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); | |
124 | |
125 // lower right | |
126 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, | |
127 (*ag + *bg + *cg + *dg) >> 2, | |
128 (*ab + *bb + *cb + *db) >> 2); | |
129 | |
130 // 'b' becomes 'a', 'd' becomes 'c' | |
131 ar = br; | |
132 ag = bg; | |
133 ab = bb; | |
134 cr = dr; | |
135 cg = dg; | |
136 cb = db; | |
137 } | |
138 | |
139 // the "next" rgb row becomes the current; the old current rgb row is | |
140 // recycled and serves as the new "next" row | |
141 u8 *temp; | |
142 temp = rgb_row_cur; | |
143 rgb_row_cur = rgb_row_next; | |
144 rgb_row_next = temp; | |
145 | |
146 // update the pointers for start of next pair of lines | |
147 from = (u16 *)((u8 *)from_orig + srcPitch); | |
148 to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); | |
149 to_odd = (u16 *)((u8 *)to + dstPitch); | |
150 } | |
151 } | |
152 | |
153 void BilinearPlus(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, | |
154 u8 *dstPtr, u32 dstPitch, int width, int height) | |
155 { | |
156 u16 *to = (u16 *)dstPtr; | |
157 u16 *to_odd = (u16 *)(dstPtr + dstPitch); | |
158 | |
159 int from_width = width; | |
160 u16 *from = (u16 *)srcPtr; | |
161 fill_rgb_row_16(from, from_width, rgb_row_cur, width + 1); | |
162 | |
163 for (int y = 0; y < height; y++) | |
164 { | |
165 u16 *from_orig = from; | |
166 u16 *to_orig = to; | |
167 | |
168 if (y + 1 < height) | |
169 fill_rgb_row_16(from + width + 2, from_width, rgb_row_next, | |
170 width + 1); | |
171 else | |
172 fill_rgb_row_16(from, from_width, rgb_row_next, width + 1); | |
173 | |
174 // every pixel in the src region, is extended to 4 pixels in the | |
175 // destination, arranged in a square 'quad'; if the current src | |
176 // pixel is 'a', then in what follows 'b' is the src pixel to the | |
177 // right, 'c' is the src pixel below, and 'd' is the src pixel to | |
178 // the right and down | |
179 u8 *cur_row = rgb_row_cur; | |
180 u8 *next_row = rgb_row_next; | |
181 u8 *ar = cur_row++; | |
182 u8 *ag = cur_row++; | |
183 u8 *ab = cur_row++; | |
184 u8 *cr = next_row++; | |
185 u8 *cg = next_row++; | |
186 u8 *cb = next_row++; | |
187 for (int x = 0; x < width; x++) | |
188 { | |
189 u8 *br = cur_row++; | |
190 u8 *bg = cur_row++; | |
191 u8 *bb = cur_row++; | |
192 u8 *dr = next_row++; | |
193 u8 *dg = next_row++; | |
194 u8 *db = next_row++; | |
195 | |
196 // upper left pixel in quad: just copy it in | |
197 //*to++ = manip.rgb(*ar, *ag, *ab); | |
198 #ifdef USE_ORIGINAL_BILINEAR_PLUS | |
199 *to++ = RGB( | |
200 (((*ar) << 2) + ((*ar)) + (*cr + *br + *br)) >> 3, | |
201 (((*ag) << 2) + ((*ag)) + (*cg + *bg + *bg)) >> 3, | |
202 (((*ab) << 2) + ((*ab)) + (*cb + *bb + *bb)) >> 3); | |
203 #else | |
204 *to++ = RGB( | |
205 (((*ar) << 3) + ((*ar) << 1) + (*cr + *br + *br + *cr)) >> 4, | |
206 (((*ag) << 3) + ((*ag) << 1) + (*cg + *bg + *bg + *cg)) >> 4, | |
207 (((*ab) << 3) + ((*ab) << 1) + (*cb + *bb + *bb + *cb)) >> 4); | |
208 #endif | |
209 | |
210 // upper right | |
211 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); | |
212 | |
213 // lower left | |
214 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); | |
215 | |
216 // lower right | |
217 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, | |
218 (*ag + *bg + *cg + *dg) >> 2, | |
219 (*ab + *bb + *cb + *db) >> 2); | |
220 | |
221 // 'b' becomes 'a', 'd' becomes 'c' | |
222 ar = br; | |
223 ag = bg; | |
224 ab = bb; | |
225 cr = dr; | |
226 cg = dg; | |
227 cb = db; | |
228 } | |
229 | |
230 // the "next" rgb row becomes the current; the old current rgb row is | |
231 // recycled and serves as the new "next" row | |
232 u8 *temp; | |
233 temp = rgb_row_cur; | |
234 rgb_row_cur = rgb_row_next; | |
235 rgb_row_next = temp; | |
236 | |
237 // update the pointers for start of next pair of lines | |
238 from = (u16 *)((u8 *)from_orig + srcPitch); | |
239 to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); | |
240 to_odd = (u16 *)((u8 *)to + dstPitch); | |
241 } | |
242 } | |
243 | |
244 void Bilinear32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, | |
245 u8 *dstPtr, u32 dstPitch, int width, int height) | |
246 { | |
247 u32 *to = (u32 *)dstPtr; | |
248 u32 *to_odd = (u32 *)(dstPtr + dstPitch); | |
249 | |
250 int from_width = width; | |
251 if (width + 1 < from_width) | |
252 from_width = width + 1; | |
253 u32 *from = (u32 *)srcPtr; | |
254 fill_rgb_row_32(from, from_width, rgb_row_cur, width + 1); | |
255 | |
256 for (int y = 0; y < height; y++) | |
257 { | |
258 u32 *from_orig = from; | |
259 u32 *to_orig = to; | |
260 | |
261 if (y + 1 < height) | |
262 fill_rgb_row_32(from + width + 1, from_width, rgb_row_next, | |
263 width + 1); | |
264 else | |
265 fill_rgb_row_32(from, from_width, rgb_row_next, width + 1); | |
266 | |
267 // every pixel in the src region, is extended to 4 pixels in the | |
268 // destination, arranged in a square 'quad'; if the current src | |
269 // pixel is 'a', then in what follows 'b' is the src pixel to the | |
270 // right, 'c' is the src pixel below, and 'd' is the src pixel to | |
271 // the right and down | |
272 u8 *cur_row = rgb_row_cur; | |
273 u8 *next_row = rgb_row_next; | |
274 u8 *ar = cur_row++; | |
275 u8 *ag = cur_row++; | |
276 u8 *ab = cur_row++; | |
277 u8 *cr = next_row++; | |
278 u8 *cg = next_row++; | |
279 u8 *cb = next_row++; | |
280 for (int x = 0; x < width; x++) | |
281 { | |
282 u8 *br = cur_row++; | |
283 u8 *bg = cur_row++; | |
284 u8 *bb = cur_row++; | |
285 u8 *dr = next_row++; | |
286 u8 *dg = next_row++; | |
287 u8 *db = next_row++; | |
288 | |
289 // upper left pixel in quad: just copy it in | |
290 *to++ = RGB(*ar, *ag, *ab); | |
291 | |
292 // upper right | |
293 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); | |
294 | |
295 // lower left | |
296 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); | |
297 | |
298 // lower right | |
299 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, | |
300 (*ag + *bg + *cg + *dg) >> 2, | |
301 (*ab + *bb + *cb + *db) >> 2); | |
302 | |
303 // 'b' becomes 'a', 'd' becomes 'c' | |
304 ar = br; | |
305 ag = bg; | |
306 ab = bb; | |
307 cr = dr; | |
308 cg = dg; | |
309 cb = db; | |
310 } | |
311 | |
312 // the "next" rgb row becomes the current; the old current rgb row is | |
313 // recycled and serves as the new "next" row | |
314 u8 *temp; | |
315 temp = rgb_row_cur; | |
316 rgb_row_cur = rgb_row_next; | |
317 rgb_row_next = temp; | |
318 | |
319 // update the pointers for start of next pair of lines | |
320 from = (u32 *)((u8 *)from_orig + srcPitch); | |
321 to = (u32 *)((u8 *)to_orig + (dstPitch << 1)); | |
322 to_odd = (u32 *)((u8 *)to + dstPitch); | |
323 } | |
324 } | |
325 | |
326 void BilinearPlus32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, | |
327 u8 *dstPtr, u32 dstPitch, int width, int height) | |
328 { | |
329 u32 *to = (u32 *)dstPtr; | |
330 u32 *to_odd = (u32 *)(dstPtr + dstPitch); | |
331 | |
332 int from_width = width; | |
333 if (width + 1 < from_width) | |
334 from_width = width + 1; | |
335 u32 *from = (u32 *)srcPtr; | |
336 fill_rgb_row_32(from, from_width, rgb_row_cur, width + 1); | |
337 | |
338 for (int y = 0; y < height; y++) | |
339 { | |
340 u32 *from_orig = from; | |
341 u32 *to_orig = to; | |
342 | |
343 if (y + 1 < height) | |
344 fill_rgb_row_32(from + width + 1, from_width, rgb_row_next, | |
345 width + 1); | |
346 else | |
347 fill_rgb_row_32(from, from_width, rgb_row_next, width + 1); | |
348 | |
349 // every pixel in the src region, is extended to 4 pixels in the | |
350 // destination, arranged in a square 'quad'; if the current src | |
351 // pixel is 'a', then in what follows 'b' is the src pixel to the | |
352 // right, 'c' is the src pixel below, and 'd' is the src pixel to | |
353 // the right and down | |
354 u8 *cur_row = rgb_row_cur; | |
355 u8 *next_row = rgb_row_next; | |
356 u8 *ar = cur_row++; | |
357 u8 *ag = cur_row++; | |
358 u8 *ab = cur_row++; | |
359 u8 *cr = next_row++; | |
360 u8 *cg = next_row++; | |
361 u8 *cb = next_row++; | |
362 for (int x = 0; x < width; x++) | |
363 { | |
364 u8 *br = cur_row++; | |
365 u8 *bg = cur_row++; | |
366 u8 *bb = cur_row++; | |
367 u8 *dr = next_row++; | |
368 u8 *dg = next_row++; | |
369 u8 *db = next_row++; | |
370 | |
371 // upper left pixel in quad: just copy it in | |
372 //*to++ = manip.rgb(*ar, *ag, *ab); | |
373 #ifdef USE_ORIGINAL_BILINEAR_PLUS | |
374 *to++ = RGB( | |
375 (((*ar) << 2) + ((*ar)) + (*cr + *br + *br)) >> 3, | |
376 (((*ag) << 2) + ((*ag)) + (*cg + *bg + *bg)) >> 3, | |
377 (((*ab) << 2) + ((*ab)) + (*cb + *bb + *bb)) >> 3); | |
378 #else | |
379 *to++ = RGB( | |
380 (((*ar) << 3) + ((*ar) << 1) + (*cr + *br + *br + *cr)) >> 4, | |
381 (((*ag) << 3) + ((*ag) << 1) + (*cg + *bg + *bg + *cg)) >> 4, | |
382 (((*ab) << 3) + ((*ab) << 1) + (*cb + *bb + *bb + *cb)) >> 4); | |
383 #endif | |
384 | |
385 // upper right | |
386 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); | |
387 | |
388 // lower left | |
389 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); | |
390 | |
391 // lower right | |
392 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, | |
393 (*ag + *bg + *cg + *dg) >> 2, | |
394 (*ab + *bb + *cb + *db) >> 2); | |
395 | |
396 // 'b' becomes 'a', 'd' becomes 'c' | |
397 ar = br; | |
398 ag = bg; | |
399 ab = bb; | |
400 cr = dr; | |
401 cg = dg; | |
402 cb = db; | |
403 } | |
404 | |
405 // the "next" rgb row becomes the current; the old current rgb row is | |
406 // recycled and serves as the new "next" row | |
407 u8 *temp; | |
408 temp = rgb_row_cur; | |
409 rgb_row_cur = rgb_row_next; | |
410 rgb_row_next = temp; | |
411 | |
412 // update the pointers for start of next pair of lines | |
413 from = (u32 *)((u8 *)from_orig + srcPitch); | |
414 to = (u32 *)((u8 *)to_orig + (dstPitch << 1)); | |
415 to_odd = (u32 *)((u8 *)to + dstPitch); | |
416 } | |
417 } | |
418 |