From b38b73d88cb63f41d943062aa579fc8c27544689 Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Tue, 10 Sep 2013 20:34:09 +0000 Subject: [PATCH] ARGBLumaColorTable function. BUG=267 TEST=Luma* R=thorcarpenter@google.com Review URL: https://webrtc-codereview.appspot.com/2202004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@783 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/planar_functions.h | 9 +++++ include/libyuv/row.h | 12 +++++- include/libyuv/version.h | 2 +- source/planar_functions.cc | 32 ++++++++++++++++ source/row_common.cc | 33 ++++++++++++++++ unit_test/planar_test.cc | 62 +++++++++++++++++++++++++++++++ 7 files changed, 148 insertions(+), 4 deletions(-) diff --git a/README.chromium b/README.chromium index 766b50a13..140da8828 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 782 +Version: 783 License: BSD License File: LICENSE diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index 57da063d6..31490012c 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -210,6 +210,15 @@ int RGBColorTable(uint8* dst_argb, int dst_stride_argb, const uint8* table_argb, int x, int y, int width, int height); +// Apply a luma/color table each ARGB pixel but preserve destination alpha. +// Table contains 32768 values indexed by [Y][C] where 7 it 7 bit luma from +// RGB (YJ style) and C is an 8 bit color component (R, G or B). +LIBYUV_API +int ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb, + uint8* dst_argb, int dst_stride_argb, + const uint8* luma_rgb_table, + int width, int height); + // Apply a 3 term polynomial to ARGB values. // poly points to a 4x4 matrix. The first row is constants. The 2nd row is // coefficients for b, g, r and a. The 3rd row is coefficients for b squared, diff --git a/include/libyuv/row.h b/include/libyuv/row.h index 9bafdb42f..fa9ecda74 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -144,6 +144,7 @@ extern "C" { #define HAS_ARGBCOLORTABLEROW_X86 #define HAS_ARGBPOLYNOMIALROW_SSE2 #define HAS_RGBCOLORTABLEROW_X86 +#define HAS_ARGBLUMACOLORTABLEROW_SSE2 // Caveat: Visual C 2012 required for AVX2. #if _MSC_VER >= 1700 @@ -1554,8 +1555,15 @@ void ARGBPolynomialRow_SSE2(const uint8* src_argb, uint8* dst_argb, const float* poly, int width); void ARGBPolynomialRow_AVX2(const uint8* src_argb, - uint8* dst_argb, const float* poly, - int width); + uint8* dst_argb, const float* poly, + int width); + +void ARGBLumaColorTableRow_C(const uint8* src_argb, + uint8* dst_argb, const uint8* luma, + int width); +void ARGBLumaColorTableRow_SSSE3(const uint8* src_argb, + uint8* dst_argb, const uint8* luma, + int width); // Divide num by div and return as 16.16 fixed point result. int FixedDiv_C(int num, int div); diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 0f24bd848..2ee4a02b2 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 782 +#define LIBYUV_VERSION 783 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/planar_functions.cc b/source/planar_functions.cc index 24f03dfa3..606b199a5 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -2069,6 +2069,38 @@ int ARGBPolynomial(const uint8* src_argb, int src_stride_argb, return 0; } +// Apply a lumacolortable to each ARGB pixel. +LIBYUV_API +int ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb, + uint8* dst_argb, int dst_stride_argb, + const uint8* luma, + int width, int height) { + if (!src_argb || !dst_argb || !luma || width <= 0 || height <= 0) { + return -1; + } + // Coalesce contiguous rows. + if (src_stride_argb == width * 4 && dst_stride_argb == width * 4) { + return ARGBLumaColorTable(src_argb, 0, + dst_argb, 0, + luma, + width * height, 1); + } + void (*ARGBLumaColorTableRow)(const uint8* src_argb, + uint8* dst_argb, const uint8* luma, + int width) = ARGBLumaColorTableRow_C; +#if defined(HAS_ARGBLUMACOLORTABLEROW_SSSE3) + if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 2)) { + ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3; + } +#endif + for (int y = 0; y < height; ++y) { + ARGBLumaColorTableRow(src_argb, dst_argb, luma, width); + src_argb += src_stride_argb; + dst_argb += dst_stride_argb; + } + return 0; +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/source/row_common.cc b/source/row_common.cc index 07128a73b..305499cf4 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -2051,6 +2051,39 @@ void ARGBPolynomialRow_C(const uint8* src_argb, } } +// RGB to Luminance. +// Leverage the fact that we want shifted left by 8 by the caller. +// +// Borrowed from libyuv/files/source/row_common.cc. +// JPeg 7 bit Y: +// b 0.11400 * 128 = 14.592 = 15 +// g 0.58700 * 128 = 75.136 = 75 +// r 0.29900 * 128 = 38.272 = 38 +static __inline unsigned int RGBToYJx256(uint8 r, uint8 g, uint8 b) { + return (38u * r + 75u * g + 15u * b) & 0x7F00u; +} +void ARGBLumaColorTableRow_C(const uint8* src_argb, + uint8* dst_argb, const uint8* luma, + int width) { + for (int i = 0; i < width - 1; i += 2) { + // Luminance in rows, color values in columns. + const uint8* luma0 = RGBToYJx256(src_argb[2], src_argb[1], src_argb[0]) + + luma; + dst_argb[0] = luma0[src_argb[0]]; + dst_argb[1] = luma0[src_argb[1]]; + dst_argb[2] = luma0[src_argb[2]]; + dst_argb[3] = src_argb[3]; + const uint8* luma1 = RGBToYJx256(src_argb[6], src_argb[5], src_argb[4]) + + luma; + dst_argb[4] = luma0[src_argb[4]]; + dst_argb[5] = luma0[src_argb[5]]; + dst_argb[6] = luma0[src_argb[6]]; + dst_argb[7] = src_argb[7]; + src_argb += 8; + dst_argb += 8; + } +} + #undef clamp0 #undef clamp255 diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 117d6d276..6a81bacce 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -1719,5 +1719,67 @@ TEST_F(libyuvTest, TestARGBPolynomial) { } } +TEST_F(libyuvTest, TestARGBLumaColorTable) { + SIMD_ALIGNED(uint8 orig_pixels[1280][4]); + SIMD_ALIGNED(uint8 dst_pixels[1280][4]); + + SIMD_ALIGNED(uint8 kLumaColorTable[32768]); + int v = 0; + for (int i = 0; i < 32768; ++i) { + kLumaColorTable[i] = v; + v += 3; + } + // Test blue + orig_pixels[0][0] = 255u; + orig_pixels[0][1] = 0u; + orig_pixels[0][2] = 0u; + orig_pixels[0][3] = 128u; + // Test green + orig_pixels[1][0] = 0u; + orig_pixels[1][1] = 255u; + orig_pixels[1][2] = 0u; + orig_pixels[1][3] = 0u; + // Test red + orig_pixels[2][0] = 0u; + orig_pixels[2][1] = 0u; + orig_pixels[2][2] = 255u; + orig_pixels[2][3] = 255u; + // Test color + orig_pixels[3][0] = 16u; + orig_pixels[3][1] = 64u; + orig_pixels[3][2] = 192u; + orig_pixels[3][3] = 224u; + // Do 16 to test asm version. + ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels[0][0], 0, + &kLumaColorTable[0], 16, 1); + EXPECT_EQ(253u, dst_pixels[0][0]); + EXPECT_EQ(0u, dst_pixels[0][1]); + EXPECT_EQ(0u, dst_pixels[0][2]); + EXPECT_EQ(128u, dst_pixels[0][3]); + EXPECT_EQ(0u, dst_pixels[1][0]); + EXPECT_EQ(253u, dst_pixels[1][1]); + EXPECT_EQ(0u, dst_pixels[1][2]); + EXPECT_EQ(0u, dst_pixels[1][3]); + EXPECT_EQ(0u, dst_pixels[2][0]); + EXPECT_EQ(0u, dst_pixels[2][1]); + EXPECT_EQ(253u, dst_pixels[2][2]); + EXPECT_EQ(255u, dst_pixels[2][3]); + EXPECT_EQ(48u, dst_pixels[3][0]); + EXPECT_EQ(192u, dst_pixels[3][1]); + EXPECT_EQ(64u, dst_pixels[3][2]); + EXPECT_EQ(224u, dst_pixels[3][3]); + + for (int i = 0; i < 1280; ++i) { + orig_pixels[i][0] = i; + orig_pixels[i][1] = i / 2; + orig_pixels[i][2] = i / 3; + orig_pixels[i][3] = i; + } + for (int i = 0; i < benchmark_pixels_div1280_; ++i) { + ARGBLumaColorTable(&orig_pixels[0][0], 0, &dst_pixels[0][0], 0, + &kLumaColorTable[0], 1280, 1); + } +} + } // namespace libyuv