From 5520710ef7ce306357ab35c501f776b1fb0266e8 Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Wed, 24 Jul 2013 21:35:57 +0000 Subject: [PATCH] Add RGBColorTable which is like ARGBColorTable but only does first 3 channels. BUG=none TEST=none R=dingkai@google.com, thorcarpenter@google.com, wuwang@google.com Review URL: https://webrtc-codereview.appspot.com/1858004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@739 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/planar_functions.h | 7 ++++ include/libyuv/row.h | 6 +++- include/libyuv/version.h | 2 +- source/planar_functions.cc | 32 +++++++++++++++++ source/row_common.cc | 13 +++++++ source/row_win.cc | 43 ++++++++++++++++++++++ unit_test/planar_test.cc | 59 +++++++++++++++++++++++++++++++ 8 files changed, 161 insertions(+), 3 deletions(-) diff --git a/README.chromium b/README.chromium index d99032125..ab87d1002 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 738 +Version: 739 License: BSD License File: LICENSE diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index cb14678a8..4f8dc2ef8 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -203,6 +203,13 @@ int ARGBColorTable(uint8* dst_argb, int dst_stride_argb, const uint8* table_argb, int x, int y, int width, int height); +// Apply a color table each ARGB pixel but preserve destination alpha. +// Table contains 256 ARGB values. +LIBYUV_API +int RGBColorTable(uint8* dst_argb, int dst_stride_argb, + const uint8* table_argb, + int x, int y, int width, int height); + // Quantize a rectangle of ARGB. Alpha unaffected. // scale is a 16 bit fractional fixed point scaler between 0 and 65535. // interval_size should be a value between 1 and 255. diff --git a/include/libyuv/row.h b/include/libyuv/row.h index d6fc637e8..12a3e8188 100644 --- a/include/libyuv/row.h +++ b/include/libyuv/row.h @@ -28,7 +28,7 @@ extern "C" { #if defined(__CLR_VER) || defined(COVERAGE_ENABLED) || \ defined(TARGET_IPHONE_SIMULATOR) || \ - defined(__native_client__) && defined(__x86_64__) + (defined(__native_client__) && defined(__x86_64__)) #define LIBYUV_DISABLE_X86 #endif // True if compiling for SSSE3 as a requirement. @@ -132,6 +132,7 @@ extern "C" { // TODO(fbarchard): Port to gcc. #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER) #define HAS_ARGBCOLORTABLEROW_X86 +#define HAS_RGBCOLORTABLEROW_X86 // Visual C 2012 required for AVX2. #if _MSC_VER >= 1700 #define HAS_ARGBSHUFFLEROW_AVX2 @@ -1426,6 +1427,9 @@ void ARGBColorMatrixRow_NEON(uint8* dst_argb, const int8* matrix_argb, void ARGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width); void ARGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width); +void RGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width); +void RGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width); + void ARGBQuantizeRow_C(uint8* dst_argb, int scale, int interval_size, int interval_offset, int width); void ARGBQuantizeRow_SSE2(uint8* dst_argb, int scale, int interval_size, diff --git a/include/libyuv/version.h b/include/libyuv/version.h index a76b86dfb..0fdd18181 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 738 +#define LIBYUV_VERSION 739 #endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT diff --git a/source/planar_functions.cc b/source/planar_functions.cc index 2f7033132..93a1603ed 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -1413,6 +1413,38 @@ int ARGBColorTable(uint8* dst_argb, int dst_stride_argb, return 0; } +// Apply a color table each ARGB pixel but preserve destination alpha. +// Table contains 256 ARGB values. +LIBYUV_API +int RGBColorTable(uint8* dst_argb, int dst_stride_argb, + const uint8* table_argb, + int dst_x, int dst_y, int width, int height) { + if (!dst_argb || !table_argb || width <= 0 || height <= 0 || + dst_x < 0 || dst_y < 0) { + return -1; + } + // Coalesce contiguous rows. + if (dst_stride_argb == width * 4) { + return RGBColorTable(dst_argb, dst_stride_argb, + table_argb, + dst_x, dst_y, + width * height, 1); + } + void (*RGBColorTableRow)(uint8* dst_argb, const uint8* table_argb, + int width) = RGBColorTableRow_C; +#if defined(HAS_RGBCOLORTABLEROW_X86) + if (TestCpuFlag(kCpuHasX86)) { + RGBColorTableRow = RGBColorTableRow_X86; + } +#endif + uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; + for (int y = 0; y < height; ++y) { + RGBColorTableRow(dst, table_argb, width); + dst += dst_stride_argb; + } + return 0; +} + // ARGBQuantize is used to posterize art. // e.g. rgb / qvalue * qvalue + qvalue / 2 // But the low levels implement efficiently with 3 parameters, and could be diff --git a/source/row_common.cc b/source/row_common.cc index b17c18ea2..60af38608 100644 --- a/source/row_common.cc +++ b/source/row_common.cc @@ -688,6 +688,19 @@ void ARGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width) { } } +// Apply color table to a row of image. +void RGBColorTableRow_C(uint8* dst_argb, const uint8* table_argb, int width) { + for (int x = 0; x < width; ++x) { + int b = dst_argb[0]; + int g = dst_argb[1]; + int r = dst_argb[2]; + dst_argb[0] = table_argb[b * 4 + 0]; + dst_argb[1] = table_argb[g * 4 + 1]; + dst_argb[2] = table_argb[r * 4 + 2]; + dst_argb += 4; + } +} + void ARGBQuantizeRow_C(uint8* dst_argb, int scale, int interval_size, int interval_offset, int width) { for (int x = 0; x < width; ++x) { diff --git a/source/row_win.cc b/source/row_win.cc index f671b233b..025a82562 100644 --- a/source/row_win.cc +++ b/source/row_win.cc @@ -5138,6 +5138,49 @@ void ARGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, } #endif // HAS_ARGBCOLORTABLEROW_X86 +#ifdef HAS_RGBCOLORTABLEROW_X86 +// Tranform RGB pixels with color table. +__declspec(naked) __declspec(align(16)) +void RGBColorTableRow_X86(uint8* dst_argb, const uint8* table_argb, int width) { + __asm { + push ebx + push esi + push edi + push ebp + mov eax, [esp + 16 + 4] /* dst_argb */ + mov edi, [esp + 16 + 8] /* table_argb */ + mov ecx, [esp + 16 + 12] /* width */ + xor ebx, ebx + xor edx, edx + + align 16 + convertloop: + mov ebp, dword ptr [eax] // BGRA + mov esi, ebp + and ebp, 255 + shr esi, 8 + and esi, 255 + mov bl, [edi + ebp * 4 + 0] // B + mov dl, [edi + esi * 4 + 1] // G + mov ebp, dword ptr [eax] // BGRA + shr ebp, 16 + and ebp, 255 + mov [eax], bl + mov [eax + 1], dl + mov bl, [edi + ebp * 4 + 2] // R + mov [eax + 2], bl + lea eax, [eax + 4] + sub ecx, 1 + jg convertloop + pop ebp + pop edi + pop esi + pop ebx + ret + } +} +#endif // HAS_RGBCOLORTABLEROW_X86 + #ifdef HAS_ARGBQUANTIZEROW_SSE2 // Quantize 4 ARGB pixels (16 bytes). // Aligned to 16 bytes. diff --git a/unit_test/planar_test.cc b/unit_test/planar_test.cc index 2c9958baa..cc1b55597 100644 --- a/unit_test/planar_test.cc +++ b/unit_test/planar_test.cc @@ -596,6 +596,65 @@ TEST_F(libyuvTest, TestARGBColorTable) { } } +// Same as TestARGBColorTable except alpha does not change. +TEST_F(libyuvTest, TestRGBColorTable) { + SIMD_ALIGNED(uint8 orig_pixels[256][4]); + memset(orig_pixels, 0, sizeof(orig_pixels)); + + // Matrix for Sepia. + static const uint8 kARGBTable[256 * 4] = { + 1u, 2u, 3u, 4u, + 5u, 6u, 7u, 8u, + 9u, 10u, 11u, 12u, + 13u, 14u, 15u, 16u, + }; + + orig_pixels[0][0] = 0u; + orig_pixels[0][1] = 0u; + orig_pixels[0][2] = 0u; + orig_pixels[0][3] = 0u; + orig_pixels[1][0] = 1u; + orig_pixels[1][1] = 1u; + orig_pixels[1][2] = 1u; + orig_pixels[1][3] = 1u; + orig_pixels[2][0] = 2u; + orig_pixels[2][1] = 2u; + orig_pixels[2][2] = 2u; + orig_pixels[2][3] = 2u; + orig_pixels[3][0] = 0u; + orig_pixels[3][1] = 1u; + orig_pixels[3][2] = 2u; + orig_pixels[3][3] = 3u; + // Do 16 to test asm version. + RGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 16, 1); + EXPECT_EQ(1u, orig_pixels[0][0]); + EXPECT_EQ(2u, orig_pixels[0][1]); + EXPECT_EQ(3u, orig_pixels[0][2]); + EXPECT_EQ(0u, orig_pixels[0][3]); // Alpha unchanged. + EXPECT_EQ(5u, orig_pixels[1][0]); + EXPECT_EQ(6u, orig_pixels[1][1]); + EXPECT_EQ(7u, orig_pixels[1][2]); + EXPECT_EQ(1u, orig_pixels[1][3]); // Alpha unchanged. + EXPECT_EQ(9u, orig_pixels[2][0]); + EXPECT_EQ(10u, orig_pixels[2][1]); + EXPECT_EQ(11u, orig_pixels[2][2]); + EXPECT_EQ(2u, orig_pixels[2][3]); // Alpha unchanged. + EXPECT_EQ(1u, orig_pixels[3][0]); + EXPECT_EQ(6u, orig_pixels[3][1]); + EXPECT_EQ(11u, orig_pixels[3][2]); + EXPECT_EQ(3u, orig_pixels[3][3]); // Alpha unchanged. + + for (int i = 0; i < 256; ++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_div256_; ++i) { + RGBColorTable(&orig_pixels[0][0], 0, &kARGBTable[0], 0, 0, 256, 1); + } +} + TEST_F(libyuvTest, TestARGBQuantize) { SIMD_ALIGNED(uint8 orig_pixels[256][4]);