Mercurial > vba-linux
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/filters/bilinear.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,418 @@ 1.4 +/** Code adapted from Exult source code by Forgotten 1.5 +** Scale.cc - Trying to scale with bilinear interpolation. 1.6 +** 1.7 +** Written: 6/14/00 - JSF 1.8 +**/ 1.9 + 1.10 +#include "../common/System.h" 1.11 + 1.12 +static u8 row_cur[3 * 322]; 1.13 +static u8 row_next[3 * 322]; 1.14 + 1.15 +static u8 *rgb_row_cur = row_cur; 1.16 +static u8 *rgb_row_next = row_next; 1.17 + 1.18 +#ifdef RGB 1.19 +#undef RGB // wingdi.h has it 1.20 +#endif 1.21 +#define RGB(r, g, b) \ 1.22 + ((r) >> 3) << systemRedShift | \ 1.23 + ((g) >> 3) << systemGreenShift | \ 1.24 + ((b) >> 3) << systemBlueShift \ 1.25 + 1.26 +static void fill_rgb_row_16(u16 *from, int src_width, u8 *row, int width) 1.27 +{ 1.28 + u8 *copy_start = row + src_width * 3; 1.29 + u8 *all_stop = row + width * 3; 1.30 + while (row < copy_start) 1.31 + { 1.32 + u16 color = *from++; 1.33 + *row++ = ((color >> systemRedShift) & 0x1f) << 3; 1.34 + *row++ = ((color >> systemGreenShift) & 0x1f) << 3; 1.35 + *row++ = ((color >> systemBlueShift) & 0x1f) << 3; 1.36 + } 1.37 + // any remaining elements to be written to 'row' are a replica of the 1.38 + // preceding pixel 1.39 + u8 *p = row - 3; 1.40 + while (row < all_stop) 1.41 + { 1.42 + // we're guaranteed three elements per pixel; could unroll the loop 1.43 + // further, especially with a Duff's Device, but the gains would be 1.44 + // probably limited (judging by profiler output) 1.45 + *row++ = *p++; 1.46 + *row++ = *p++; 1.47 + *row++ = *p++; 1.48 + } 1.49 +} 1.50 + 1.51 +static void fill_rgb_row_32(u32 *from, int src_width, u8 *row, int width) 1.52 +{ 1.53 + u8 *copy_start = row + src_width * 3; 1.54 + u8 *all_stop = row + width * 3; 1.55 + while (row < copy_start) 1.56 + { 1.57 + u32 color = *from++; 1.58 + *row++ = ((color >> systemRedShift) & 0x1f) << 3; 1.59 + *row++ = ((color >> systemGreenShift) & 0x1f) << 3; 1.60 + *row++ = ((color >> systemBlueShift) & 0x1f) << 3; 1.61 + } 1.62 + // any remaining elements to be written to 'row' are a replica of the 1.63 + // preceding pixel 1.64 + u8 *p = row - 3; 1.65 + while (row < all_stop) 1.66 + { 1.67 + // we're guaranteed three elements per pixel; could unroll the loop 1.68 + // further, especially with a Duff's Device, but the gains would be 1.69 + // probably limited (judging by profiler output) 1.70 + *row++ = *p++; 1.71 + *row++ = *p++; 1.72 + *row++ = *p++; 1.73 + } 1.74 +} 1.75 + 1.76 +void Bilinear(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, 1.77 + u8 *dstPtr, u32 dstPitch, int width, int height) 1.78 +{ 1.79 + u16 *to = (u16 *)dstPtr; 1.80 + u16 *to_odd = (u16 *)(dstPtr + dstPitch); 1.81 + 1.82 + int from_width = width; 1.83 + u16 *from = (u16 *)srcPtr; 1.84 + fill_rgb_row_16(from, from_width, rgb_row_cur, width + 1); 1.85 + 1.86 + for (int y = 0; y < height; y++) 1.87 + { 1.88 + u16 *from_orig = from; 1.89 + u16 *to_orig = to; 1.90 + 1.91 + if (y + 1 < height) 1.92 + fill_rgb_row_16(from + width + 2, from_width, rgb_row_next, 1.93 + width + 1); 1.94 + else 1.95 + fill_rgb_row_16(from, from_width, rgb_row_next, width + 1); 1.96 + 1.97 + // every pixel in the src region, is extended to 4 pixels in the 1.98 + // destination, arranged in a square 'quad'; if the current src 1.99 + // pixel is 'a', then in what follows 'b' is the src pixel to the 1.100 + // right, 'c' is the src pixel below, and 'd' is the src pixel to 1.101 + // the right and down 1.102 + u8 *cur_row = rgb_row_cur; 1.103 + u8 *next_row = rgb_row_next; 1.104 + u8 *ar = cur_row++; 1.105 + u8 *ag = cur_row++; 1.106 + u8 *ab = cur_row++; 1.107 + u8 *cr = next_row++; 1.108 + u8 *cg = next_row++; 1.109 + u8 *cb = next_row++; 1.110 + for (int x = 0; x < width; x++) 1.111 + { 1.112 + u8 *br = cur_row++; 1.113 + u8 *bg = cur_row++; 1.114 + u8 *bb = cur_row++; 1.115 + u8 *dr = next_row++; 1.116 + u8 *dg = next_row++; 1.117 + u8 *db = next_row++; 1.118 + 1.119 + // upper left pixel in quad: just copy it in 1.120 + *to++ = RGB(*ar, *ag, *ab); 1.121 + 1.122 + // upper right 1.123 + *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); 1.124 + 1.125 + // lower left 1.126 + *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); 1.127 + 1.128 + // lower right 1.129 + *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, 1.130 + (*ag + *bg + *cg + *dg) >> 2, 1.131 + (*ab + *bb + *cb + *db) >> 2); 1.132 + 1.133 + // 'b' becomes 'a', 'd' becomes 'c' 1.134 + ar = br; 1.135 + ag = bg; 1.136 + ab = bb; 1.137 + cr = dr; 1.138 + cg = dg; 1.139 + cb = db; 1.140 + } 1.141 + 1.142 + // the "next" rgb row becomes the current; the old current rgb row is 1.143 + // recycled and serves as the new "next" row 1.144 + u8 *temp; 1.145 + temp = rgb_row_cur; 1.146 + rgb_row_cur = rgb_row_next; 1.147 + rgb_row_next = temp; 1.148 + 1.149 + // update the pointers for start of next pair of lines 1.150 + from = (u16 *)((u8 *)from_orig + srcPitch); 1.151 + to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); 1.152 + to_odd = (u16 *)((u8 *)to + dstPitch); 1.153 + } 1.154 +} 1.155 + 1.156 +void BilinearPlus(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, 1.157 + u8 *dstPtr, u32 dstPitch, int width, int height) 1.158 +{ 1.159 + u16 *to = (u16 *)dstPtr; 1.160 + u16 *to_odd = (u16 *)(dstPtr + dstPitch); 1.161 + 1.162 + int from_width = width; 1.163 + u16 *from = (u16 *)srcPtr; 1.164 + fill_rgb_row_16(from, from_width, rgb_row_cur, width + 1); 1.165 + 1.166 + for (int y = 0; y < height; y++) 1.167 + { 1.168 + u16 *from_orig = from; 1.169 + u16 *to_orig = to; 1.170 + 1.171 + if (y + 1 < height) 1.172 + fill_rgb_row_16(from + width + 2, from_width, rgb_row_next, 1.173 + width + 1); 1.174 + else 1.175 + fill_rgb_row_16(from, from_width, rgb_row_next, width + 1); 1.176 + 1.177 + // every pixel in the src region, is extended to 4 pixels in the 1.178 + // destination, arranged in a square 'quad'; if the current src 1.179 + // pixel is 'a', then in what follows 'b' is the src pixel to the 1.180 + // right, 'c' is the src pixel below, and 'd' is the src pixel to 1.181 + // the right and down 1.182 + u8 *cur_row = rgb_row_cur; 1.183 + u8 *next_row = rgb_row_next; 1.184 + u8 *ar = cur_row++; 1.185 + u8 *ag = cur_row++; 1.186 + u8 *ab = cur_row++; 1.187 + u8 *cr = next_row++; 1.188 + u8 *cg = next_row++; 1.189 + u8 *cb = next_row++; 1.190 + for (int x = 0; x < width; x++) 1.191 + { 1.192 + u8 *br = cur_row++; 1.193 + u8 *bg = cur_row++; 1.194 + u8 *bb = cur_row++; 1.195 + u8 *dr = next_row++; 1.196 + u8 *dg = next_row++; 1.197 + u8 *db = next_row++; 1.198 + 1.199 + // upper left pixel in quad: just copy it in 1.200 + //*to++ = manip.rgb(*ar, *ag, *ab); 1.201 +#ifdef USE_ORIGINAL_BILINEAR_PLUS 1.202 + *to++ = RGB( 1.203 + (((*ar) << 2) + ((*ar)) + (*cr + *br + *br)) >> 3, 1.204 + (((*ag) << 2) + ((*ag)) + (*cg + *bg + *bg)) >> 3, 1.205 + (((*ab) << 2) + ((*ab)) + (*cb + *bb + *bb)) >> 3); 1.206 +#else 1.207 + *to++ = RGB( 1.208 + (((*ar) << 3) + ((*ar) << 1) + (*cr + *br + *br + *cr)) >> 4, 1.209 + (((*ag) << 3) + ((*ag) << 1) + (*cg + *bg + *bg + *cg)) >> 4, 1.210 + (((*ab) << 3) + ((*ab) << 1) + (*cb + *bb + *bb + *cb)) >> 4); 1.211 +#endif 1.212 + 1.213 + // upper right 1.214 + *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); 1.215 + 1.216 + // lower left 1.217 + *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); 1.218 + 1.219 + // lower right 1.220 + *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, 1.221 + (*ag + *bg + *cg + *dg) >> 2, 1.222 + (*ab + *bb + *cb + *db) >> 2); 1.223 + 1.224 + // 'b' becomes 'a', 'd' becomes 'c' 1.225 + ar = br; 1.226 + ag = bg; 1.227 + ab = bb; 1.228 + cr = dr; 1.229 + cg = dg; 1.230 + cb = db; 1.231 + } 1.232 + 1.233 + // the "next" rgb row becomes the current; the old current rgb row is 1.234 + // recycled and serves as the new "next" row 1.235 + u8 *temp; 1.236 + temp = rgb_row_cur; 1.237 + rgb_row_cur = rgb_row_next; 1.238 + rgb_row_next = temp; 1.239 + 1.240 + // update the pointers for start of next pair of lines 1.241 + from = (u16 *)((u8 *)from_orig + srcPitch); 1.242 + to = (u16 *)((u8 *)to_orig + (dstPitch << 1)); 1.243 + to_odd = (u16 *)((u8 *)to + dstPitch); 1.244 + } 1.245 +} 1.246 + 1.247 +void Bilinear32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, 1.248 + u8 *dstPtr, u32 dstPitch, int width, int height) 1.249 +{ 1.250 + u32 *to = (u32 *)dstPtr; 1.251 + u32 *to_odd = (u32 *)(dstPtr + dstPitch); 1.252 + 1.253 + int from_width = width; 1.254 + if (width + 1 < from_width) 1.255 + from_width = width + 1; 1.256 + u32 *from = (u32 *)srcPtr; 1.257 + fill_rgb_row_32(from, from_width, rgb_row_cur, width + 1); 1.258 + 1.259 + for (int y = 0; y < height; y++) 1.260 + { 1.261 + u32 *from_orig = from; 1.262 + u32 *to_orig = to; 1.263 + 1.264 + if (y + 1 < height) 1.265 + fill_rgb_row_32(from + width + 1, from_width, rgb_row_next, 1.266 + width + 1); 1.267 + else 1.268 + fill_rgb_row_32(from, from_width, rgb_row_next, width + 1); 1.269 + 1.270 + // every pixel in the src region, is extended to 4 pixels in the 1.271 + // destination, arranged in a square 'quad'; if the current src 1.272 + // pixel is 'a', then in what follows 'b' is the src pixel to the 1.273 + // right, 'c' is the src pixel below, and 'd' is the src pixel to 1.274 + // the right and down 1.275 + u8 *cur_row = rgb_row_cur; 1.276 + u8 *next_row = rgb_row_next; 1.277 + u8 *ar = cur_row++; 1.278 + u8 *ag = cur_row++; 1.279 + u8 *ab = cur_row++; 1.280 + u8 *cr = next_row++; 1.281 + u8 *cg = next_row++; 1.282 + u8 *cb = next_row++; 1.283 + for (int x = 0; x < width; x++) 1.284 + { 1.285 + u8 *br = cur_row++; 1.286 + u8 *bg = cur_row++; 1.287 + u8 *bb = cur_row++; 1.288 + u8 *dr = next_row++; 1.289 + u8 *dg = next_row++; 1.290 + u8 *db = next_row++; 1.291 + 1.292 + // upper left pixel in quad: just copy it in 1.293 + *to++ = RGB(*ar, *ag, *ab); 1.294 + 1.295 + // upper right 1.296 + *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); 1.297 + 1.298 + // lower left 1.299 + *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); 1.300 + 1.301 + // lower right 1.302 + *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, 1.303 + (*ag + *bg + *cg + *dg) >> 2, 1.304 + (*ab + *bb + *cb + *db) >> 2); 1.305 + 1.306 + // 'b' becomes 'a', 'd' becomes 'c' 1.307 + ar = br; 1.308 + ag = bg; 1.309 + ab = bb; 1.310 + cr = dr; 1.311 + cg = dg; 1.312 + cb = db; 1.313 + } 1.314 + 1.315 + // the "next" rgb row becomes the current; the old current rgb row is 1.316 + // recycled and serves as the new "next" row 1.317 + u8 *temp; 1.318 + temp = rgb_row_cur; 1.319 + rgb_row_cur = rgb_row_next; 1.320 + rgb_row_next = temp; 1.321 + 1.322 + // update the pointers for start of next pair of lines 1.323 + from = (u32 *)((u8 *)from_orig + srcPitch); 1.324 + to = (u32 *)((u8 *)to_orig + (dstPitch << 1)); 1.325 + to_odd = (u32 *)((u8 *)to + dstPitch); 1.326 + } 1.327 +} 1.328 + 1.329 +void BilinearPlus32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, 1.330 + u8 *dstPtr, u32 dstPitch, int width, int height) 1.331 +{ 1.332 + u32 *to = (u32 *)dstPtr; 1.333 + u32 *to_odd = (u32 *)(dstPtr + dstPitch); 1.334 + 1.335 + int from_width = width; 1.336 + if (width + 1 < from_width) 1.337 + from_width = width + 1; 1.338 + u32 *from = (u32 *)srcPtr; 1.339 + fill_rgb_row_32(from, from_width, rgb_row_cur, width + 1); 1.340 + 1.341 + for (int y = 0; y < height; y++) 1.342 + { 1.343 + u32 *from_orig = from; 1.344 + u32 *to_orig = to; 1.345 + 1.346 + if (y + 1 < height) 1.347 + fill_rgb_row_32(from + width + 1, from_width, rgb_row_next, 1.348 + width + 1); 1.349 + else 1.350 + fill_rgb_row_32(from, from_width, rgb_row_next, width + 1); 1.351 + 1.352 + // every pixel in the src region, is extended to 4 pixels in the 1.353 + // destination, arranged in a square 'quad'; if the current src 1.354 + // pixel is 'a', then in what follows 'b' is the src pixel to the 1.355 + // right, 'c' is the src pixel below, and 'd' is the src pixel to 1.356 + // the right and down 1.357 + u8 *cur_row = rgb_row_cur; 1.358 + u8 *next_row = rgb_row_next; 1.359 + u8 *ar = cur_row++; 1.360 + u8 *ag = cur_row++; 1.361 + u8 *ab = cur_row++; 1.362 + u8 *cr = next_row++; 1.363 + u8 *cg = next_row++; 1.364 + u8 *cb = next_row++; 1.365 + for (int x = 0; x < width; x++) 1.366 + { 1.367 + u8 *br = cur_row++; 1.368 + u8 *bg = cur_row++; 1.369 + u8 *bb = cur_row++; 1.370 + u8 *dr = next_row++; 1.371 + u8 *dg = next_row++; 1.372 + u8 *db = next_row++; 1.373 + 1.374 + // upper left pixel in quad: just copy it in 1.375 + //*to++ = manip.rgb(*ar, *ag, *ab); 1.376 +#ifdef USE_ORIGINAL_BILINEAR_PLUS 1.377 + *to++ = RGB( 1.378 + (((*ar) << 2) + ((*ar)) + (*cr + *br + *br)) >> 3, 1.379 + (((*ag) << 2) + ((*ag)) + (*cg + *bg + *bg)) >> 3, 1.380 + (((*ab) << 2) + ((*ab)) + (*cb + *bb + *bb)) >> 3); 1.381 +#else 1.382 + *to++ = RGB( 1.383 + (((*ar) << 3) + ((*ar) << 1) + (*cr + *br + *br + *cr)) >> 4, 1.384 + (((*ag) << 3) + ((*ag) << 1) + (*cg + *bg + *bg + *cg)) >> 4, 1.385 + (((*ab) << 3) + ((*ab) << 1) + (*cb + *bb + *bb + *cb)) >> 4); 1.386 +#endif 1.387 + 1.388 + // upper right 1.389 + *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1); 1.390 + 1.391 + // lower left 1.392 + *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1); 1.393 + 1.394 + // lower right 1.395 + *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2, 1.396 + (*ag + *bg + *cg + *dg) >> 2, 1.397 + (*ab + *bb + *cb + *db) >> 2); 1.398 + 1.399 + // 'b' becomes 'a', 'd' becomes 'c' 1.400 + ar = br; 1.401 + ag = bg; 1.402 + ab = bb; 1.403 + cr = dr; 1.404 + cg = dg; 1.405 + cb = db; 1.406 + } 1.407 + 1.408 + // the "next" rgb row becomes the current; the old current rgb row is 1.409 + // recycled and serves as the new "next" row 1.410 + u8 *temp; 1.411 + temp = rgb_row_cur; 1.412 + rgb_row_cur = rgb_row_next; 1.413 + rgb_row_next = temp; 1.414 + 1.415 + // update the pointers for start of next pair of lines 1.416 + from = (u32 *)((u8 *)from_orig + srcPitch); 1.417 + to = (u32 *)((u8 *)to_orig + (dstPitch << 1)); 1.418 + to_odd = (u32 *)((u8 *)to + dstPitch); 1.419 + } 1.420 +} 1.421 +