From 980150f7f1c9cf99b1729d0274b46092a47449bd Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Fri, 6 Dec 2013 18:13:46 +0000 Subject: [PATCH] Compute slope considering filtering, mirror. BUG=261 TEST=valgrind R=tpsiaki@google.com Review URL: https://webrtc-codereview.appspot.com/5199004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@896 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/scale_row.h | 15 ++++++--- include/libyuv/version.h | 2 +- source/scale_argb.cc | 29 ++-------------- source/scale_common.cc | 69 +++++++++++++++++++++++++++++++++++++- 5 files changed, 83 insertions(+), 34 deletions(-) diff --git a/README.chromium b/README.chromium index 573e90866..3869dd6d8 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 895 +Version: 896 License: BSD License File: LICENSE diff --git a/include/libyuv/scale_row.h b/include/libyuv/scale_row.h index b94bf5c1f..23c4e9079 100644 --- a/include/libyuv/scale_row.h +++ b/include/libyuv/scale_row.h @@ -55,10 +55,6 @@ extern "C" { #define HAS_SCALEROWDOWN38_MIPS_DSPR2 #endif -FilterMode ScaleFilterReduce(int src_width, int src_height, - int dst_width, int dst_height, - FilterMode filtering); - // Scale ARGB vertically with bilinear interpolation. void ScalePlaneVertical(int src_height, int dst_width, int dst_height, @@ -67,6 +63,17 @@ void ScalePlaneVertical(int src_height, int x, int y, int dy, int bpp, FilterMode filtering); +// Simplify the filtering based on scale factors. +FilterMode ScaleFilterReduce(int src_width, int src_height, + int dst_width, int dst_height, + FilterMode filtering); + +// Compute slope values for stepping. +void ScaleSlope(int src_width, int src_height, + int dst_width, int dst_height, + FilterMode filtering, + int* x, int* y, int* dx, int* dy); + void ScaleRowDown2_C(const uint8* src_ptr, ptrdiff_t /* src_stride */, uint8* dst, int dst_width); void ScaleRowDown2Linear_C(const uint8* src_ptr, ptrdiff_t src_stride, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index ef91aac09..981139b33 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 895 +#define LIBYUV_VERSION 896 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/scale_argb.cc b/source/scale_argb.cc index 5e4d65208..8d051b333 100644 --- a/source/scale_argb.cc +++ b/source/scale_argb.cc @@ -593,33 +593,8 @@ static void ScaleARGB(const uint8* src, int src_stride, int dy = 0; int x = 0; int y = 0; - if (filtering) { - // Scale step for bilinear sampling renders last pixel once for upsample. - if (dst_width <= Abs(src_width)) { - dx = FixedDiv(Abs(src_width), dst_width); - x = (dx >> 1) - 32768; - } else if (dst_width > 1) { - dx = FixedDiv(Abs(src_width) - 1, dst_width - 1); - } - if (dst_height <= src_height) { - dy = FixedDiv(src_height, dst_height); - y = (dy >> 1) - 32768; - } else if (dst_height > 1) { - dy = FixedDiv(src_height - 1, dst_height - 1); - } - } else { - // Scale step for point sampling duplicates all pixels equally. - dx = FixedDiv(Abs(src_width), dst_width); - dy = FixedDiv(src_height, dst_height); - x = dx >> 1; - y = dy >> 1; - } - // Negative src_width means horizontally mirror. - if (src_width < 0) { - x += (dst_width - 1) * dx; - dx = -dx; - src_width = -src_width; - } + ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, + &dx, &dy, &x, &y); if (clip_x) { x += clip_x * dx; dst += clip_x * 4; diff --git a/source/scale_common.cc b/source/scale_common.cc index f5944f1ec..277a94e10 100644 --- a/source/scale_common.cc +++ b/source/scale_common.cc @@ -534,7 +534,7 @@ void ScalePlaneVertical(int src_height, } } -// Scale plane vertically with bilinear interpolation. +// Simplify the filtering based on scale factors. FilterMode ScaleFilterReduce(int src_width, int src_height, int dst_width, int dst_height, FilterMode filtering) { @@ -575,6 +575,73 @@ FilterMode ScaleFilterReduce(int src_width, int src_height, return filtering; } +#define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s) +#define FIXEDDIV1(src, dst) FixedDiv((src << 16) - 0x00010001, \ + (dst << 16) - 0x00010001); + +// Compute slope values for stepping. +void ScaleSlope(int src_width, int src_height, + int dst_width, int src_height, + FilterMode filtering, + int* x, int* y, int* dx, int* dy) { + assert(x != NULL); + assert(y != NULL); + assert(dx != NULL); + assert(dy != NULL); + assert(src_width != 0); + assert(src_height != 0); + assert(dst_width > 0); + assert(dst_height > 0); + if (filtering == kFilterBox) { + // Scale step for point sampling duplicates all pixels equally. + *dx = FixedDiv(Abs(src_width), dst_width); + *dy = FixedDiv(src_height, dst_height); + *x = 0; + *y = 0; + } else if (filtering == kFilterBilinear) { + // Scale step for bilinear sampling renders last pixel once for upsample. + if (dst_width <= Abs(src_width)) { + *dx = FixedDiv(Abs(src_width), dst_width); + *x = CENTERSTART(*dx, -32768); + } else if (dst_width > 1) { + *dx = FIXEDDIV1(Abs(src_width), dst_width); + *x = 0; + } + if (dst_height <= src_height) { + *dy = FixedDiv(src_height, dst_height); + *y = CENTERSTART(*dy, -32768); + } else if (dst_height > 1) { + *dy = FIXEDDIV1(src_height, dst_height); + *y = 0; + } + } else if (filtering == kFilterLinear) { + // Scale step for bilinear sampling renders last pixel once for upsample. + if (dst_width <= Abs(src_width)) { + *dx = FixedDiv(Abs(src_width), dst_width); + *x = CENTERSTART(*dx, -32768); + } else if (dst_width > 1) { + *dx = FIXEDDIV1(Abs(src_width), dst_width); + *x = 0; + } + *dy = FixedDiv(src_height, dst_height); + *y = *dy >> 1; + } else { + // Scale step for point sampling duplicates all pixels equally. + *dx = FixedDiv(Abs(src_width), dst_width); + *dy = FixedDiv(src_height, dst_height); + *x = CENTERSTART(*dx, 0); + *y = CENTERSTART(*dy, 0); + } + // Negative src_width means horizontally mirror. + if (src_width < 0) { + *x += (dst_width - 1) * dx; + *dx = -*dx; + src_width = -src_width; + } +} +#undef CENTERSTART +#undef FIXEDDIV1 + #ifdef __cplusplus } // extern "C" } // namespace libyuv