Mercurial > vba-clojure
view src/filters/bilinear.cpp @ 262:868783405ac2
script: left oak's lab.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 26 Mar 2012 21:00:23 -0500 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 /** Code adapted from Exult source code by Forgotten2 ** Scale.cc - Trying to scale with bilinear interpolation.3 **4 ** Written: 6/14/00 - JSF5 **/7 #include "../common/System.h"9 static u8 row_cur[3 * 322];10 static u8 row_next[3 * 322];12 static u8 *rgb_row_cur = row_cur;13 static u8 *rgb_row_next = row_next;15 #ifdef RGB16 #undef RGB // wingdi.h has it17 #endif18 #define RGB(r, g, b) \19 ((r) >> 3) << systemRedShift | \20 ((g) >> 3) << systemGreenShift | \21 ((b) >> 3) << systemBlueShift \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 the35 // preceding pixel36 u8 *p = row - 3;37 while (row < all_stop)38 {39 // we're guaranteed three elements per pixel; could unroll the loop40 // further, especially with a Duff's Device, but the gains would be41 // probably limited (judging by profiler output)42 *row++ = *p++;43 *row++ = *p++;44 *row++ = *p++;45 }46 }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 the60 // preceding pixel61 u8 *p = row - 3;62 while (row < all_stop)63 {64 // we're guaranteed three elements per pixel; could unroll the loop65 // further, especially with a Duff's Device, but the gains would be66 // probably limited (judging by profiler output)67 *row++ = *p++;68 *row++ = *p++;69 *row++ = *p++;70 }71 }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);79 int from_width = width;80 u16 *from = (u16 *)srcPtr;81 fill_rgb_row_16(from, from_width, rgb_row_cur, width + 1);83 for (int y = 0; y < height; y++)84 {85 u16 *from_orig = from;86 u16 *to_orig = to;88 if (y + 1 < height)89 fill_rgb_row_16(from + width + 2, from_width, rgb_row_next,90 width + 1);91 else92 fill_rgb_row_16(from, from_width, rgb_row_next, width + 1);94 // every pixel in the src region, is extended to 4 pixels in the95 // destination, arranged in a square 'quad'; if the current src96 // pixel is 'a', then in what follows 'b' is the src pixel to the97 // right, 'c' is the src pixel below, and 'd' is the src pixel to98 // the right and down99 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++;116 // upper left pixel in quad: just copy it in117 *to++ = RGB(*ar, *ag, *ab);119 // upper right120 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1);122 // lower left123 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1);125 // lower right126 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2,127 (*ag + *bg + *cg + *dg) >> 2,128 (*ab + *bb + *cb + *db) >> 2);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 }139 // the "next" rgb row becomes the current; the old current rgb row is140 // recycled and serves as the new "next" row141 u8 *temp;142 temp = rgb_row_cur;143 rgb_row_cur = rgb_row_next;144 rgb_row_next = temp;146 // update the pointers for start of next pair of lines147 from = (u16 *)((u8 *)from_orig + srcPitch);148 to = (u16 *)((u8 *)to_orig + (dstPitch << 1));149 to_odd = (u16 *)((u8 *)to + dstPitch);150 }151 }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);159 int from_width = width;160 u16 *from = (u16 *)srcPtr;161 fill_rgb_row_16(from, from_width, rgb_row_cur, width + 1);163 for (int y = 0; y < height; y++)164 {165 u16 *from_orig = from;166 u16 *to_orig = to;168 if (y + 1 < height)169 fill_rgb_row_16(from + width + 2, from_width, rgb_row_next,170 width + 1);171 else172 fill_rgb_row_16(from, from_width, rgb_row_next, width + 1);174 // every pixel in the src region, is extended to 4 pixels in the175 // destination, arranged in a square 'quad'; if the current src176 // pixel is 'a', then in what follows 'b' is the src pixel to the177 // right, 'c' is the src pixel below, and 'd' is the src pixel to178 // the right and down179 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++;196 // upper left pixel in quad: just copy it in197 //*to++ = manip.rgb(*ar, *ag, *ab);198 #ifdef USE_ORIGINAL_BILINEAR_PLUS199 *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 #else204 *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 #endif210 // upper right211 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1);213 // lower left214 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1);216 // lower right217 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2,218 (*ag + *bg + *cg + *dg) >> 2,219 (*ab + *bb + *cb + *db) >> 2);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 }230 // the "next" rgb row becomes the current; the old current rgb row is231 // recycled and serves as the new "next" row232 u8 *temp;233 temp = rgb_row_cur;234 rgb_row_cur = rgb_row_next;235 rgb_row_next = temp;237 // update the pointers for start of next pair of lines238 from = (u16 *)((u8 *)from_orig + srcPitch);239 to = (u16 *)((u8 *)to_orig + (dstPitch << 1));240 to_odd = (u16 *)((u8 *)to + dstPitch);241 }242 }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);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);256 for (int y = 0; y < height; y++)257 {258 u32 *from_orig = from;259 u32 *to_orig = to;261 if (y + 1 < height)262 fill_rgb_row_32(from + width + 1, from_width, rgb_row_next,263 width + 1);264 else265 fill_rgb_row_32(from, from_width, rgb_row_next, width + 1);267 // every pixel in the src region, is extended to 4 pixels in the268 // destination, arranged in a square 'quad'; if the current src269 // pixel is 'a', then in what follows 'b' is the src pixel to the270 // right, 'c' is the src pixel below, and 'd' is the src pixel to271 // the right and down272 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++;289 // upper left pixel in quad: just copy it in290 *to++ = RGB(*ar, *ag, *ab);292 // upper right293 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1);295 // lower left296 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1);298 // lower right299 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2,300 (*ag + *bg + *cg + *dg) >> 2,301 (*ab + *bb + *cb + *db) >> 2);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 }312 // the "next" rgb row becomes the current; the old current rgb row is313 // recycled and serves as the new "next" row314 u8 *temp;315 temp = rgb_row_cur;316 rgb_row_cur = rgb_row_next;317 rgb_row_next = temp;319 // update the pointers for start of next pair of lines320 from = (u32 *)((u8 *)from_orig + srcPitch);321 to = (u32 *)((u8 *)to_orig + (dstPitch << 1));322 to_odd = (u32 *)((u8 *)to + dstPitch);323 }324 }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);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);338 for (int y = 0; y < height; y++)339 {340 u32 *from_orig = from;341 u32 *to_orig = to;343 if (y + 1 < height)344 fill_rgb_row_32(from + width + 1, from_width, rgb_row_next,345 width + 1);346 else347 fill_rgb_row_32(from, from_width, rgb_row_next, width + 1);349 // every pixel in the src region, is extended to 4 pixels in the350 // destination, arranged in a square 'quad'; if the current src351 // pixel is 'a', then in what follows 'b' is the src pixel to the352 // right, 'c' is the src pixel below, and 'd' is the src pixel to353 // the right and down354 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++;371 // upper left pixel in quad: just copy it in372 //*to++ = manip.rgb(*ar, *ag, *ab);373 #ifdef USE_ORIGINAL_BILINEAR_PLUS374 *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 #else379 *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 #endif385 // upper right386 *to++ = RGB((*ar + *br) >> 1, (*ag + *bg) >> 1, (*ab + *bb) >> 1);388 // lower left389 *to_odd++ = RGB((*ar + *cr) >> 1, (*ag + *cg) >> 1, (*ab + *cb) >> 1);391 // lower right392 *to_odd++ = RGB((*ar + *br + *cr + *dr) >> 2,393 (*ag + *bg + *cg + *dg) >> 2,394 (*ab + *bb + *cb + *db) >> 2);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 }405 // the "next" rgb row becomes the current; the old current rgb row is406 // recycled and serves as the new "next" row407 u8 *temp;408 temp = rgb_row_cur;409 rgb_row_cur = rgb_row_next;410 rgb_row_next = temp;412 // update the pointers for start of next pair of lines413 from = (u32 *)((u8 *)from_orig + srcPitch);414 to = (u32 *)((u8 *)to_orig + (dstPitch << 1));415 to_odd = (u32 *)((u8 *)to + dstPitch);416 }417 }