From 829e7ea402a06fa616e4c70ee91675318e00e134 Mon Sep 17 00:00:00 2001 From: "fbarchard@google.com" Date: Tue, 17 Apr 2012 00:49:28 +0000 Subject: [PATCH] ARGBAttenuate and ARGBUnattenuate for converting to/from attentuated ARGB BUG=none TEST=none Review URL: https://webrtc-codereview.appspot.com/490008 git-svn-id: http://libyuv.googlecode.com/svn/trunk@240 16f28f9a-4ce2-e073-06de-1de4eb20be90 --- README.chromium | 2 +- include/libyuv/planar_functions.h | 10 ++++ include/libyuv/version.h | 2 +- source/planar_functions.cc | 99 +++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) diff --git a/README.chromium b/README.chromium index 1da0a1fc6..4ba0135de 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 239 +Version: 240 License: BSD License File: LICENSE diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index d7fd3e10e..bf7a92a84 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -160,6 +160,16 @@ int I422ToUYVY(const uint8* src_y, int src_stride_y, uint8* dst_frame, int dst_stride_frame, int width, int height); +// Convert unattentuated ARGB values to preattenuated ARGB. +int ARGBAttenuate(const uint8* src_argb, int src_stride_argb, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + +// Convert preattentuated ARGB values to unattenuated ARGB. +int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb, + uint8* dst_argb, int dst_stride_argb, + int width, int height); + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/include/libyuv/version.h b/include/libyuv/version.h index fd72a817c..cee7aebb0 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,7 +11,7 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 239 +#define LIBYUV_VERSION 240 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/planar_functions.cc b/source/planar_functions.cc index 455722d08..24c72862f 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -863,6 +863,105 @@ int ARGBRect(uint8* dst_argb, int dst_stride_argb, return 0; } +// Multiply source RGB by alpha and store to destination. +static void ARGBAttenuateRow_C(const uint8* src_argb, uint8* dst_argb, + int width) { + for (int i = 0; i < width; ++i) { + const uint32 b = src_argb[0]; + const uint32 g = src_argb[1]; + const uint32 r = src_argb[2]; + const uint32 a = src_argb[3]; + dst_argb[0] = (b * a + 128) / 255; + dst_argb[1] = (g * a + 128) / 255; + dst_argb[2] = (r * a + 128) / 255; + dst_argb[3] = a; + src_argb += 4; + dst_argb += 4; + } +} + +// Convert unattentuated ARGB values to preattenuated ARGB by multiplying RGB by +// by alpha. +// An unattenutated ARGB alpha blend uses the formula +// p = a * f + (1 - a) * b +// where +// p is output pixel +// f is foreground pixel +// b is background pixel +// a is alpha value from foreground pixel +// An preattenutated ARGB alpha blend uses the formula +// p = f + (1 - a) * b +// where +// f is foreground pixel premultiplied by alpha + +int ARGBAttenuate(const uint8* src_argb, int src_stride_argb, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + + for (int y = 0; y < height; ++y) { + ARGBAttenuateRow_C(src_argb, dst_argb, width); + src_argb += src_stride_argb; + dst_argb += dst_stride_argb; + } + return 0; +} + +// Divide source RGB by alpha and store to destination. +static void ARGBUnattenuateRow_C(const uint8* src_argb, uint8* dst_argb, + int width) { + for (int i = 0; i < width; ++i) { + uint32 b = src_argb[0]; + uint32 g = src_argb[1]; + uint32 r = src_argb[2]; + const uint32 a = src_argb[3]; + if (a) { + b = (b * 255 + 127) / a; + if (b > 255) { + b = 255; + } + g = (g * 255 + 127) / a; + if (g > 255) { + g = 255; + } + r = (r * 255 + 127) / a; + if (r > 255) { + r = 255; + } + } + dst_argb[0] = b; + dst_argb[1] = g; + dst_argb[2] = r; + dst_argb[3] = a; + src_argb += 4; + dst_argb += 4; + } +} + +// Convert unattentuated ARGB values to preattenuated ARGB by multiplying RGB by +// by alpha. +int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + if (height < 0) { + height = -height; + src_argb = src_argb + (height - 1) * src_stride_argb; + src_stride_argb = -src_stride_argb; + } + + for (int y = 0; y < height; ++y) { + ARGBUnattenuateRow_C(src_argb, dst_argb, width); + src_argb += src_stride_argb; + dst_argb += dst_stride_argb; + } + return 0; +} + + #ifdef __cplusplus } // extern "C" } // namespace libyuv