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

Flat shade an ARGB image

BUG=none
TEST=none
Review URL: https://webrtc-codereview.appspot.com/683004

git-svn-id: http://libyuv.googlecode.com/svn/trunk@298 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent c4500c9f
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 297
Version: 298
License: BSD
License File: LICENSE
......
......@@ -15,7 +15,7 @@
// TODO(fbarchard): Remove the following headers includes
#include "libyuv/convert.h"
#include "libyuv/planar_functions.h"
#include "libyuv/convert_argb.h"
#ifdef __cplusplus
namespace libyuv {
......@@ -188,11 +188,6 @@ int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
// Multiply ARGB image by ARGB value.
int ARGBShade(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height, uint32 value);
// Convert MJPG to ARGB.
int MJPGToARGB(const uint8* sample, size_t sample_size,
uint8* argb, int argb_stride,
......@@ -212,6 +207,11 @@ int ARGBBlur(const uint8* src_argb, int src_stride_argb,
int32* dst_cumsum, int dst_stride32_cumsum,
int width, int height, int radius);
// Multiply ARGB image by ARGB value.
int ARGBShade(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height, uint32 value);
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
......
......@@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ // NOLINT
#define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 297
#define LIBYUV_VERSION 298
#endif // INCLUDE_LIBYUV_VERSION_H_ NOLINT
......@@ -784,11 +784,9 @@ int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy,
return 0;
}
// Visual C for x86 defines these.
#if defined(_M_X64) || defined(_M_IX86)
#define LIBYUV_LITTLE_ENDIAN
// GCC provided macros.
#elif __BYTE_ORDER == __ORDER_LITTLE_ENDIAN__ || __BYTE_ORDER == __LITTLE_ENDIAN
// Visual C x86 or GCC little endian.
#if defined(_M_X64) || defined(_M_IX86) || (defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __ORDER_LITTLE_ENDIAN__ || __BYTE_ORDER == __LITTLE_ENDIAN))
#define LIBYUV_LITTLE_ENDIAN
#endif
......
......@@ -401,18 +401,15 @@ static void I42xToUYVYRow_C(const uint8* src_y,
}
}
// Visual C for x86 defines these.
#if defined(_M_X64) || defined(_M_IX86)
#define LIBYUV_LITTLE_ENDIAN
// GCC provided macros.
#elif __BYTE_ORDER == __ORDER_LITTLE_ENDIAN__ || __BYTE_ORDER == __LITTLE_ENDIAN
// Visual C x86 or GCC little endian.
#if defined(_M_X64) || defined(_M_IX86) || (defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __ORDER_LITTLE_ENDIAN__ || __BYTE_ORDER == __LITTLE_ENDIAN))
#define LIBYUV_LITTLE_ENDIAN
#endif
#ifdef LIBYUV_LITTLE_ENDIAN
#define WRITEWORD(p, v) *reinterpret_cast<uint32*>(p) = v
#else
static inline void WRITEWORD(uint8* p, uint32 v) {
p[0] = (uint8)(v & 255);
p[1] = (uint8)((v >> 8) & 255);
......
......@@ -60,8 +60,7 @@ int I420ToI400(const uint8* src_y, int src_stride_y,
uint8*, int,
uint8*, int,
int width, int height) {
if (!src_y || !dst_y ||
width <= 0 || height == 0) {
if (!src_y || !dst_y || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
......@@ -112,8 +111,7 @@ int I420Mirror(const uint8* src_y, int src_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height) {
if (!src_y || !src_u || !src_v ||
!dst_y || !dst_u || !dst_v ||
if (!src_y || !src_u || !src_v || !dst_y || !dst_u || !dst_v ||
width <= 0 || height == 0) {
return -1;
}
......@@ -143,9 +141,7 @@ int I420Mirror(const uint8* src_y, int src_stride_y,
int ARGBMirror(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
if (!src_argb ||
!dst_argb ||
width <= 0 || height == 0) {
if (!src_argb || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
......@@ -224,6 +220,9 @@ int ARGBBlend(const uint8* src_argb0, int src_stride_argb0,
int ARGBToI400(const uint8* src_argb, int src_stride_argb,
uint8* dst_y, int dst_stride_y,
int width, int height) {
if (!src_argb || !dst_y || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -255,6 +254,9 @@ int ARGBToI422(const uint8* src_argb, int src_stride_argb,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height) {
if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -298,6 +300,9 @@ int ARGBToI422(const uint8* src_argb, int src_stride_argb,
int ARGBToRGB24(const uint8* src_argb, int src_stride_argb,
uint8* dst_rgb24, int dst_stride_rgb24,
int width, int height) {
if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -330,6 +335,9 @@ int ARGBToRGB24(const uint8* src_argb, int src_stride_argb,
int ARGBToRAW(const uint8* src_argb, int src_stride_argb,
uint8* dst_raw, int dst_stride_raw,
int width, int height) {
if (!src_argb || !dst_raw || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -362,6 +370,9 @@ int ARGBToRAW(const uint8* src_argb, int src_stride_argb,
int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
uint8* dst_rgb565, int dst_stride_rgb565,
int width, int height) {
if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -393,6 +404,9 @@ int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb1555, int dst_stride_argb1555,
int width, int height) {
if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -424,6 +438,9 @@ int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb4444, int dst_stride_argb4444,
int width, int height) {
if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -457,6 +474,9 @@ int NV12ToRGB565(const uint8* src_y, int src_stride_y,
const uint8* src_uv, int src_stride_uv,
uint8* dst_rgb565, int dst_stride_rgb565,
int width, int height) {
if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
......@@ -499,6 +519,9 @@ int NV21ToRGB565(const uint8* src_y, int src_stride_y,
const uint8* src_vu, int src_stride_vu,
uint8* dst_rgb565, int dst_stride_rgb565,
int width, int height) {
if (!src_y || !src_vu || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
......@@ -762,6 +785,9 @@ int ARGBRect(uint8* dst_argb, int dst_stride_argb,
int ARGBAttenuate(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
if (!src_argb || !dst_argb || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -796,6 +822,9 @@ int ARGBAttenuate(const uint8* src_argb, int src_stride_argb,
int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
if (!src_argb || !dst_argb || width <= 0 || height == 0) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
......@@ -866,7 +895,8 @@ int ARGBSepia(uint8* dst_argb, int dst_stride_argb,
int ARGBColorMatrix(uint8* dst_argb, int dst_stride_argb,
const int8* matrix_argb,
int dst_x, int dst_y, int width, int height) {
if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
if (!dst_argb || !matrix_argb || width <= 0 || height <= 0 ||
dst_x < 0 || dst_y < 0) {
return -1;
}
void (*ARGBColorMatrixRow)(uint8* dst_argb, const int8* matrix_argb,
......@@ -890,7 +920,8 @@ int ARGBColorMatrix(uint8* dst_argb, int dst_stride_argb,
int ARGBColorTable(uint8* dst_argb, int dst_stride_argb,
const uint8* table_argb,
int dst_x, int dst_y, int width, int height) {
if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) {
if (!dst_argb || !table_argb || width <= 0 || height <= 0 ||
dst_x < 0 || dst_y < 0) {
return -1;
}
void (*ARGBColorTableRow)(uint8* dst_argb, const uint8* table_argb,
......@@ -972,6 +1003,9 @@ int ARGBBlur(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int32* dst_cumsum, int dst_stride32_cumsum,
int width, int height, int radius) {
if (!src_argb || !dst_argb || width <= 0 || height == 0) {
return -1;
}
void (*ComputeCumulativeSumRow)(const uint8* row, int32* cumsum,
const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C;
void (*CumulativeSumToAverage)(const int32* topleft, const int32* botleft,
......@@ -1052,6 +1086,30 @@ int ARGBBlur(const uint8* src_argb, int src_stride_argb,
int ARGBShade(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb, int dst_stride_argb,
int width, int height, uint32 value) {
if (!src_argb || !dst_argb || width <= 0 || height == 0 || value == 0u) {
return -1;
}
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
void (*ARGBShadeRow)(const uint8* src_argb, uint8* dst_argb,
int width, uint32 value) = ARGBShadeRow_C;
#if defined(HAS_ARGBSHADE_SSE2)
if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
ARGBShadeRow = ARGBShadeRow_SSE2;
}
#endif
for (int y = 0; y < height; ++y) {
ARGBShadeRow(src_argb, dst_argb, width, value);
src_argb += src_stride_argb;
dst_argb += dst_stride_argb;
}
return 0;
}
#ifdef __cplusplus
......
......@@ -85,6 +85,7 @@ extern "C" {
// The following are Windows only:
#if !defined(YUV_DISABLE_ASM) && defined(_M_IX86)
#define HAS_ARGBCOLORTABLEROW_X86
#define HAS_ARGBSHADE_SSE2
#endif
// The following are disabled when SSSE3 is available:
......@@ -516,6 +517,11 @@ void CumulativeSumToAverage_C(const int32* topleft, const int32* botleft,
void ComputeCumulativeSumRow_C(const uint8* row, int32* cumsum,
const int32* previous_cumsum, int width);
void ARGBShadeRow_C(const uint8* src_argb, uint8* dst_argb, int width,
uint32 value);
void ARGBShadeRow_SSE2(const uint8* src_argb, uint8* dst_argb, int width,
uint32 value);
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
......
......@@ -956,6 +956,32 @@ void CumulativeSumToAverage_C(const int32* tl, const int32* bl,
}
}
#define REPEAT8(v) (v) | ((v) << 8)
#define SHADE(f, v) v * f >> 24
void ARGBShadeRow_C(const uint8* src_argb, uint8* dst_argb, int width,
uint32 value) {
const uint32 b_scale = REPEAT8(value & 0xff);
const uint32 g_scale = REPEAT8((value >> 8) & 0xff);
const uint32 r_scale = REPEAT8((value >> 16) & 0xff);
const uint32 a_scale = REPEAT8(value >> 24);
for (int i = 0; i < width; ++i) {
const uint32 b = REPEAT8(src_argb[0]);
const uint32 g = REPEAT8(src_argb[1]);
const uint32 r = REPEAT8(src_argb[2]);
const uint32 a = REPEAT8(src_argb[3]);
dst_argb[0] = SHADE(b, b_scale);
dst_argb[1] = SHADE(g, g_scale);
dst_argb[2] = SHADE(r, r_scale);
dst_argb[3] = SHADE(a, a_scale);
src_argb += 4;
dst_argb += 4;
}
}
#undef REPEAT8
#undef SHADE
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
......
This diff is collapsed.
......@@ -331,7 +331,6 @@ TESTATOBRANDOM(RGB565, 2, 2, ARGB, 4)
TESTATOBRANDOM(ARGB1555, 2, 2, ARGB, 4)
TESTATOBRANDOM(ARGB4444, 2, 2, ARGB, 4)
TEST_F(libyuvTest, TestAttenuate) {
SIMD_ALIGNED(uint8 orig_pixels[256][4]);
SIMD_ALIGNED(uint8 atten_pixels[256][4]);
......@@ -649,4 +648,56 @@ TEST_F(libyuvTest, TestARGBMirror) {
}
}
TEST_F(libyuvTest, TestShade) {
SIMD_ALIGNED(uint8 orig_pixels[256][4]);
SIMD_ALIGNED(uint8 shade_pixels[256][4]);
// Test unattenuation clamps
orig_pixels[0][0] = 10u;
orig_pixels[0][1] = 20u;
orig_pixels[0][2] = 40u;
orig_pixels[0][3] = 80u;
// Test unattenuation transparent and opaque are unaffected
orig_pixels[1][0] = 0u;
orig_pixels[1][1] = 0u;
orig_pixels[1][2] = 0u;
orig_pixels[1][3] = 255u;
orig_pixels[2][0] = 0u;
orig_pixels[2][1] = 0u;
orig_pixels[2][2] = 0u;
orig_pixels[2][3] = 0u;
orig_pixels[3][0] = 0u;
orig_pixels[3][1] = 0u;
orig_pixels[3][2] = 0u;
orig_pixels[3][3] = 0u;
ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 4, 1, 0x80ffffff);
EXPECT_EQ(10u, shade_pixels[0][0]);
EXPECT_EQ(20u, shade_pixels[0][1]);
EXPECT_EQ(40u, shade_pixels[0][2]);
EXPECT_EQ(40u, shade_pixels[0][3]);
EXPECT_EQ(0u, shade_pixels[1][0]);
EXPECT_EQ(0u, shade_pixels[1][1]);
EXPECT_EQ(0u, shade_pixels[1][2]);
EXPECT_EQ(128u, shade_pixels[1][3]);
EXPECT_EQ(0u, shade_pixels[2][0]);
EXPECT_EQ(0u, shade_pixels[2][1]);
EXPECT_EQ(0u, shade_pixels[2][2]);
EXPECT_EQ(0u, shade_pixels[2][3]);
EXPECT_EQ(0u, shade_pixels[3][0]);
EXPECT_EQ(0u, shade_pixels[3][1]);
EXPECT_EQ(0u, shade_pixels[3][2]);
EXPECT_EQ(0u, shade_pixels[3][3]);
ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 4, 1, 0x80808080);
EXPECT_EQ(5u, shade_pixels[0][0]);
EXPECT_EQ(10u, shade_pixels[0][1]);
EXPECT_EQ(20u, shade_pixels[0][2]);
EXPECT_EQ(40u, shade_pixels[0][3]);
for (int i = 0; i < 1000 * 1280 * 720 / 256; ++i) {
ARGBShade(&orig_pixels[0][0], 0, &shade_pixels[0][0], 0, 256, 1,
0x80808080);
}
}
} // namespace libyuv
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