From 3c11e185a83e78a8e12f765f3ae4bca381af6965 Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Mon, 26 Aug 2013 22:24:08 +0000 Subject: [PATCH] Scale vertically only BUG=260 TESTED=manually tested with LIBYUV_HEIGHT=270 R=dingkai@google.com, ryanpetrie@google.com Review URL: https://webrtc-codereview.appspot.com/2113004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@770 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/version.h | 2 +- source/row_common.cc | 4 ++ source/scale_argb.cc | 92 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/README.chromium b/README.chromium index aac234f4a..0ad1e35b8 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 769 +Version: 770 License: BSD License File: LICENSE diff --git a/include/libyuv/version.h b/include/libyuv/version.h index bc2fc8b9d..21cc877dd 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 769 +#define LIBYUV_VERSION 770 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/row_common.cc b/source/row_common.cc index 1de05a69c..d607822ea 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -1796,6 +1796,10 @@ void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride, void InterpolateRow_C(uint8* dst_ptr, const uint8* src_ptr, ptrdiff_t src_stride, int width, int source_y_fraction) { + if (source_y_fraction == 0) { + memcpy(dst_ptr, src_ptr, width); + return; + } int y1_fraction = source_y_fraction; int y0_fraction = 256 - y1_fraction; const uint8* src_ptr1 = src_ptr + src_stride; diff --git a/source/scale_argb.cc b/source/scale_argb.cc index 2a15076d2..a7599d27d 100644 --- a/source/scale_argb.cc +++ b/source/scale_argb.cc @@ -893,6 +893,78 @@ static void ScaleARGBDownEven(int src_width, int src_height, } } +// Scale ARGB vertically with bilinear interpolation. +// TODO(fbarchard): Use this for all formats. +static void ScaleARGBBilinearVertical(int src_height, + int dst_width, int dst_height, + int src_stride, int dst_stride, + const uint8* src_argb, uint8* dst_argb, + int x, int y, int dy, + int bpp, FilterMode filtering) { + int dst_widthx4 = dst_width * bpp; + src_argb += (x >> 16) * bpp; + assert(src_height > 0); + assert(dst_width > 0); + assert(dst_height > 0); + void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb, + ptrdiff_t src_stride, int dst_width, int source_y_fraction) = + InterpolateRow_C; +#if defined(HAS_INTERPOLATEROW_SSE2) + if (TestCpuFlag(kCpuHasSSE2) && dst_widthx4 >= 16) { + InterpolateRow = InterpolateRow_Any_SSE2; + if (IS_ALIGNED(dst_widthx4, 16)) { + InterpolateRow = InterpolateRow_Unaligned_SSE2; + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && + IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { + InterpolateRow = InterpolateRow_SSE2; + } + } + } +#endif +#if defined(HAS_INTERPOLATEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && dst_widthx4 >= 16) { + InterpolateRow = InterpolateRow_Any_SSSE3; + if (IS_ALIGNED(dst_widthx4, 16)) { + InterpolateRow = InterpolateRow_Unaligned_SSSE3; + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16) && + IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride, 16)) { + InterpolateRow = InterpolateRow_SSSE3; + } + } + } +#endif +#if defined(HAS_INTERPOLATEROW_NEON) + if (TestCpuFlag(kCpuHasNEON) && dst_widthx4 >= 16) { + InterpolateRow = InterpolateRow_Any_NEON; + if (IS_ALIGNED(dst_widthx4, 16)) { + InterpolateRow = InterpolateRow_NEON; + } + } +#endif +#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && dst_widthx4 >= 4 && + IS_ALIGNED(src_argb, 4) && IS_ALIGNED(src_stride, 4) && + IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride, 4)) { + InterpolateRow = InterpolateRow_Any_MIPS_DSPR2; + if (IS_ALIGNED(dst_widthx4, 4)) { + InterpolateRow = InterpolateRow_MIPS_DSPR2; + } + } +#endif + const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0; + for (int j = 0; j < dst_height; ++j) { + if (y > max_y) { + y = max_y; + } + int yi = y >> 16; + int yf = filtering ? ((y >> 8) & 255) : 0; + const uint8* src = src_argb + yi * src_stride; + InterpolateRow(dst_argb, src, src_stride, dst_widthx4, yf); + dst_argb += dst_stride; + y += dy; + } +} + // Scale ARGB down with bilinear interpolation. static void ScaleARGBBilinearDown(int src_height, int dst_width, int dst_height, @@ -1365,19 +1437,21 @@ static void ScaleARGB(const uint8* src, int src_stride, // Special case for integer step values. if (((dx | dy) & 0xffff) == 0) { - if (!dx || !dy) { + if (!dx || !dy) { // 1 pixel wide and/or tall. filtering = kFilterNone; } else { // Optimized even scale down. ie 2, 4, 6, 8, 10x. if (!(dx & 0x10000) && !(dy & 0x10000)) { if ((dx >> 16) == 2) { // Optimized 1/2 horizontal. - ScaleARGBDown2(src_width, src_height, clip_width, clip_height, + ScaleARGBDown2(src_width, src_height, + clip_width, clip_height, src_stride, dst_stride, src, dst, x, dx, y, dy, filtering); return; } - ScaleARGBDownEven(src_width, src_height, clip_width, clip_height, + ScaleARGBDownEven(src_width, src_height, + clip_width, clip_height, src_stride, dst_stride, src, dst, x, dx, y, dy, filtering); return; @@ -1394,11 +1468,21 @@ static void ScaleARGB(const uint8* src, int src_stride, } } } + if (dx == 0x10000 && (dx & 0xffff) == 0) { + // Arbitrary scale vertically, but unscaled vertically. + ScaleARGBBilinearVertical(src_height, + clip_width, clip_height, + src_stride, dst_stride, src, dst, + x, y, dy, 4, filtering); + return; + } + // Arbitrary scale up and/or down. ScaleARGBAnySize(src_width, src_height, dst_width, dst_height, clip_width, clip_height, - src_stride, dst_stride, src, dst, x, dx, y, dy, filtering); + src_stride, dst_stride, src, dst, + x, dx, y, dy, filtering); } LIBYUV_API