Commit ef888b7d authored by fbarchard@google.com's avatar fbarchard@google.com

ARGBScale accept negative width for scaling to indicate mirror horizontally.

BUG=220
TEST=convert util and ARGBScale unittests with set LIBYUV_WIDTH=-1280
Review URL: https://webrtc-codereview.appspot.com/1409005

git-svn-id: http://libyuv.googlecode.com/svn/trunk@685 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent 1a8c7916
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 684
Version: 685
License: BSD
License File: LICENSE
......
......@@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 684
#define LIBYUV_VERSION 685
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
......@@ -23,6 +23,10 @@ namespace libyuv {
extern "C" {
#endif
static __inline int Abs(int v) {
return v >= 0 ? v : -v;
}
// ARGB scaling uses bilinear or point, but not box filter.
#if !defined(LIBYUV_DISABLE_NEON) && \
(defined(__ARM_NEON__) || defined(LIBYUV_NEON))
......@@ -794,7 +798,13 @@ static void ScaleARGBDownEven(int src_width, int src_height,
// Adjust to point to center of box.
int row_step = src_height / dst_height;
int row_stride = row_step * src_stride;
src_argb += ((row_step >> 1) - 1) * src_stride + ((src_step >> 1) - 1) * 4;
src_argb += ((row_step >> 1) - 1) * src_stride +
((Abs(src_step) >> 1) - 1) * 4;
// Negative src_width means horizontally mirror.
if (src_width < 0) {
src_argb += -src_step * (dst_width - 1) * 4;
}
for (int y = 0; y < dst_height; ++y) {
ScaleARGBRowDownEven(src_argb, src_stride, src_step, dst_argb, dst_width);
src_argb += row_stride;
......@@ -810,15 +820,15 @@ static void ScaleARGBBilinearDown(int src_width, int src_height,
const uint8* src_argb, uint8* dst_argb) {
assert(dst_width > 0);
assert(dst_height > 0);
assert(src_width * 4 <= kMaxStride);
assert(Abs(src_width) * 4 <= kMaxStride);
SIMD_ALIGNED(uint8 row[kMaxStride + 16]);
void (*ScaleARGBFilterRows)(uint8* dst_argb, const uint8* src_argb,
ptrdiff_t src_stride, int dst_width, int source_y_fraction) =
ARGBInterpolateRow_C;
#if defined(HAS_ARGBINTERPOLATEROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) && src_width >= 4) {
if (TestCpuFlag(kCpuHasSSE2) && Abs(src_width) >= 4) {
ScaleARGBFilterRows = ARGBInterpolateRow_Any_SSE2;
if (IS_ALIGNED(src_width, 4)) {
if (IS_ALIGNED(Abs(src_width), 4)) {
ScaleARGBFilterRows = ARGBInterpolateRow_Unaligned_SSE2;
if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16)) {
ScaleARGBFilterRows = ARGBInterpolateRow_SSE2;
......@@ -827,9 +837,9 @@ static void ScaleARGBBilinearDown(int src_width, int src_height,
}
#endif
#if defined(HAS_ARGBINTERPOLATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3) && src_width >= 4) {
if (TestCpuFlag(kCpuHasSSSE3) && Abs(src_width) >= 4) {
ScaleARGBFilterRows = ARGBInterpolateRow_Any_SSSE3;
if (IS_ALIGNED(src_width, 4)) {
if (IS_ALIGNED(Abs(src_width), 4)) {
ScaleARGBFilterRows = ARGBInterpolateRow_Unaligned_SSSE3;
if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride, 16)) {
ScaleARGBFilterRows = ARGBInterpolateRow_SSSE3;
......@@ -838,9 +848,9 @@ static void ScaleARGBBilinearDown(int src_width, int src_height,
}
#endif
#if defined(HAS_ARGBINTERPOLATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON) && src_width >= 4) {
if (TestCpuFlag(kCpuHasNEON) && Abs(src_width) >= 4) {
ScaleARGBFilterRows = ARGBInterpolateRow_Any_NEON;
if (IS_ALIGNED(src_width, 4)) {
if (IS_ALIGNED(Abs(src_width), 4)) {
ScaleARGBFilterRows = ARGBInterpolateRow_NEON;
}
}
......@@ -856,11 +866,17 @@ static void ScaleARGBBilinearDown(int src_width, int src_height,
int dy = 0;
int x = 0;
int y = 0;
if (dst_width <= src_width) {
dx = (src_width << 16) / dst_width;
if (dst_width <= Abs(src_width)) {
dx = (Abs(src_width) << 16) / dst_width;
x = (dx >> 1) - 32768;
} else if (dst_width > 1) {
dx = ((src_width - 1) << 16) / (dst_width - 1);
dx = ((Abs(src_width) - 1) << 16) / (dst_width - 1);
}
// Negative src_width means horizontally mirror.
if (src_width < 0) {
x += (dst_width - 1) * dx;
dx = -dx;
src_width = -src_width;
}
if (dst_height <= src_height) {
dy = (src_height << 16) / dst_height;
......@@ -936,11 +952,17 @@ static void ScaleARGBBilinearUp(int src_width, int src_height,
int dy = 0;
int x = 0;
int y = 0;
if (dst_width <= src_width) {
dx = (src_width << 16) / dst_width;
if (dst_width <= Abs(src_width)) {
dx = (Abs(src_width) << 16) / dst_width;
x = (dx >> 1) - 32768;
} else if (dst_width > 1) {
dx = ((src_width - 1) << 16) / (dst_width - 1);
dx = ((Abs(src_width) - 1) << 16) / (dst_width - 1);
}
// Negative src_width means horizontally mirror.
if (src_width < 0) {
x += (dst_width - 1) * dx;
dx = -dx;
src_width = -src_width;
}
if (dst_height <= src_height) {
dy = (src_height << 16) / dst_height;
......@@ -1024,10 +1046,29 @@ static void ScaleARGBSimple(int src_width, int src_height,
ScaleARGBCols = ScaleARGBCols_SSE2;
}
#endif
int dx = (src_width << 16) / dst_width;
int dy = (src_height << 16) / dst_height;
int x = (dx >= 65536) ? ((dx >> 1) - 32768) : (dx >> 1);
int y = (dy >= 65536) ? ((dy >> 1) - 32768) : (dy >> 1);
int dx = 0;
int dy = 0;
int x = 0;
int y = 0;
if (dst_width <= Abs(src_width)) {
dx = (Abs(src_width) << 16) / dst_width;
x = (dx >> 1) - 32768;
} else if (dst_width > 1) {
dx = ((Abs(src_width) - 1) << 16) / (dst_width - 1);
}
// Negative src_width means horizontally mirror.
if (src_width < 0) {
x += (dst_width - 1) * dx;
dx = -dx;
src_width = -src_width;
}
if (dst_height <= src_height) {
dy = (src_height << 16) / dst_height;
y = (dy >> 1) - 32768;
} else if (dst_height > 1) {
dy = ((src_height - 1) << 16) / (dst_height - 1);
}
for (int i = 0; i < dst_height; ++i) {
ScaleARGBCols(dst_argb, src_argb + (y >> 16) * src_stride,
dst_width, x, dx);
......@@ -1044,7 +1085,7 @@ static void ScaleARGBAnySize(int src_width, int src_height,
const uint8* src_argb, uint8* dst_argb,
FilterMode filtering) {
if (!filtering ||
(src_width * 4 > kMaxStride && dst_width * 4 > kMaxStride)) {
(Abs(src_width) * 4 > kMaxStride && dst_width * 4 > kMaxStride)) {
ScaleARGBSimple(src_width, src_height, dst_width, dst_height,
src_stride, dst_stride, src_argb, dst_argb);
return;
......@@ -1111,7 +1152,7 @@ int ARGBScale(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int dst_width, int dst_height,
FilterMode filtering) {
if (!src_argb || src_width <= 0 || src_height == 0 ||
if (!src_argb || src_width == 0 || src_height == 0 ||
!dst_argb || dst_width <= 0 || dst_height <= 0) {
return -1;
}
......
......@@ -17,12 +17,16 @@
namespace libyuv {
static __inline int Abs(int v) {
return v >= 0 ? v : -v;
}
static int ARGBTestFilter(int src_width, int src_height,
int dst_width, int dst_height,
FilterMode f, int benchmark_iterations) {
const int b = 128;
int src_argb_plane_size = (src_width + b * 2) * (src_height + b * 2) * 4;
int src_stride_argb = (b * 2 + src_width) * 4;
int src_argb_plane_size = (Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4;
int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
align_buffer_64(src_argb, src_argb_plane_size)
memset(src_argb, 1, src_argb_plane_size);
......@@ -33,8 +37,8 @@ static int ARGBTestFilter(int src_width, int src_height,
srandom(time(NULL));
int i, j;
for (i = b; i < (src_height + b); ++i) {
for (j = b; j < (src_width + b) * 4; ++j) {
for (i = b; i < (Abs(src_height) + b); ++i) {
for (j = b; j < (Abs(src_width) + b) * 4; ++j) {
src_argb[(i * src_stride_argb) + j] = (random() & 0xff);
}
}
......@@ -103,8 +107,8 @@ static int ARGBTestFilter(int src_width, int src_height,
TEST_F(libyuvTest, ARGBScaleDownBy2_None) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 2;
const int dst_height = src_height / 2;
const int dst_width = Abs(src_width) / 2;
const int dst_height = Abs(src_height) / 2;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -116,8 +120,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy2_None) {
TEST_F(libyuvTest, ARGBScaleDownBy2_Bilinear) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 2;
const int dst_height = src_height / 2;
const int dst_width = Abs(src_width) / 2;
const int dst_height = Abs(src_height) / 2;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -129,8 +133,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy2_Bilinear) {
TEST_F(libyuvTest, ARGBScaleDownBy4_None) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 4;
const int dst_height = src_height / 4;
const int dst_width = Abs(src_width) / 4;
const int dst_height = Abs(src_height) / 4;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -142,8 +146,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy4_None) {
TEST_F(libyuvTest, ARGBScaleDownBy4_Bilinear) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 4;
const int dst_height = src_height / 4;
const int dst_width = Abs(src_width) / 4;
const int dst_height = Abs(src_height) / 4;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -155,8 +159,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy4_Bilinear) {
TEST_F(libyuvTest, ARGBScaleDownBy5_None) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 5;
const int dst_height = src_height / 5;
const int dst_width = Abs(src_width) / 5;
const int dst_height = Abs(src_height) / 5;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -168,8 +172,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy5_None) {
TEST_F(libyuvTest, ARGBScaleDownBy5_Bilinear) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 5;
const int dst_height = src_height / 5;
const int dst_width = Abs(src_width) / 5;
const int dst_height = Abs(src_height) / 5;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -181,8 +185,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy5_Bilinear) {
TEST_F(libyuvTest, ARGBScaleDownBy8_None) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 8;
const int dst_height = src_height / 8;
const int dst_width = Abs(src_width) / 8;
const int dst_height = Abs(src_height) / 8;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -194,8 +198,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy8_None) {
TEST_F(libyuvTest, ARGBScaleDownBy8_Bilinear) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 8;
const int dst_height = src_height / 8;
const int dst_width = Abs(src_width) / 8;
const int dst_height = Abs(src_height) / 8;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -207,8 +211,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy8_Bilinear) {
TEST_F(libyuvTest, ARGBScaleDownBy16_None) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 16;
const int dst_height = src_height / 16;
const int dst_width = Abs(src_width) / 16;
const int dst_height = Abs(src_height) / 16;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -220,8 +224,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy16_None) {
TEST_F(libyuvTest, ARGBScaleDownBy16_Bilinear) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width / 16;
const int dst_height = src_height / 16;
const int dst_width = Abs(src_width) / 16;
const int dst_height = Abs(src_height) / 16;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -233,8 +237,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy16_Bilinear) {
TEST_F(libyuvTest, ARGBScaleDownBy34_None) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width * 3 / 4;
const int dst_height = src_height * 3 / 4;
const int dst_width = Abs(src_width) * 3 / 4;
const int dst_height = Abs(src_height) * 3 / 4;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -246,8 +250,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy34_None) {
TEST_F(libyuvTest, ARGBScaleDownBy34_Bilinear) {
const int src_width = benchmark_width_;
const int src_height = benchmark_height_;
const int dst_width = src_width * 3 / 4;
const int dst_height = src_height * 3 / 4;
const int dst_width = Abs(src_width) * 3 / 4;
const int dst_height = Abs(src_height) * 3 / 4;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -259,8 +263,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy34_Bilinear) {
TEST_F(libyuvTest, ARGBScaleDownBy38_None) {
int src_width = benchmark_width_;
int src_height = benchmark_height_;
int dst_width = src_width * 3 / 8;
int dst_height = src_height * 3 / 8;
int dst_width = Abs(src_width) * 3 / 8;
int dst_height = Abs(src_height) * 3 / 8;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -272,8 +276,8 @@ TEST_F(libyuvTest, ARGBScaleDownBy38_None) {
TEST_F(libyuvTest, ARGBScaleDownBy38_Bilinear) {
int src_width = benchmark_width_;
int src_height = benchmark_height_;
int dst_width = src_width * 3 / 8;
int dst_height = src_height * 3 / 8;
int dst_width = Abs(src_width) * 3 / 8;
int dst_height = Abs(src_height) * 3 / 8;
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -364,8 +368,8 @@ TEST_F(libyuvTest, ARGBScaleTo853x480_Bilinear) {
TEST_F(libyuvTest, ARGBScaleFrom640x360_None) {
int src_width = 640;
int src_height = 360;
int dst_width = benchmark_width_;
int dst_height = benchmark_height_;
int dst_width = Abs(benchmark_width_);
int dst_height = Abs(benchmark_height_);
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......@@ -377,8 +381,8 @@ TEST_F(libyuvTest, ARGBScaleFrom640x360_None) {
TEST_F(libyuvTest, ARGBScaleFrom640x360_Bilinear) {
int src_width = 640;
int src_height = 360;
int dst_width = benchmark_width_;
int dst_height = benchmark_height_;
int dst_width = Abs(benchmark_width_);
int dst_height = Abs(benchmark_height_);
int max_diff = ARGBTestFilter(src_width, src_height,
dst_width, dst_height,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment