diff --git a/Android.mk b/Android.mk index 15b00873..cecd9633 100644 --- a/Android.mk +++ b/Android.mk @@ -55,6 +55,7 @@ LOCAL_SRC_FILES := \ src/utils/huffman_encode.c \ src/utils/quant_levels.c \ src/utils/quant_levels_dec.c \ + src/utils/random.c \ src/utils/rescaler.c \ src/utils/thread.c \ src/utils/utils.c \ diff --git a/Makefile.vc b/Makefile.vc index a5b3d49e..acceba22 100644 --- a/Makefile.vc +++ b/Makefile.vc @@ -224,6 +224,7 @@ UTILS_DEC_OBJS = \ $(DIROBJ)\utils\huffman.obj \ $(DIROBJ)\utils\quant_levels_dec.obj \ $(DIROBJ)\utils\rescaler.obj \ + $(DIROBJ)\utils\random.obj \ $(DIROBJ)\utils\thread.obj \ $(DIROBJ)\utils\utils.obj \ diff --git a/makefile.unix b/makefile.unix index c47c8474..4d3cd5e0 100644 --- a/makefile.unix +++ b/makefile.unix @@ -156,6 +156,7 @@ UTILS_DEC_OBJS = \ src/utils/filters.o \ src/utils/huffman.o \ src/utils/quant_levels_dec.o \ + src/utils/random.o \ src/utils/rescaler.o \ src/utils/thread.o \ src/utils/utils.o \ @@ -199,6 +200,7 @@ HDRS = \ src/utils/huffman_encode.h \ src/utils/quant_levels.h \ src/utils/quant_levels_dec.h \ + src/utils/random.h \ src/utils/rescaler.h \ src/utils/thread.h \ src/webp/format_constants.h \ diff --git a/src/enc/picture.c b/src/enc/picture.c index bbfdc37b..31ce2f0d 100644 --- a/src/enc/picture.c +++ b/src/enc/picture.c @@ -17,6 +17,7 @@ #include "./vp8enci.h" #include "../utils/alpha_processing.h" +#include "../utils/random.h" #include "../utils/rescaler.h" #include "../utils/utils.h" #include "../dsp/dsp.h" @@ -593,62 +594,16 @@ int WebPPictureHasTransparency(const WebPPicture* picture) { //------------------------------------------------------------------------------ // RGB -> YUV conversion -#define DITHER_FIX 8 // fixed-point precision for dithering - -#define kRandomTableSize 55 -static const uint32_t kRandomTable[kRandomTableSize] = { // 31b-range values - 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, - 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, - 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, - 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, - 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, - 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, - 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, - 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, - 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, - 0x27e5ed3c -}; - -typedef struct { - int index1_, index2_; - uint32_t tab_[kRandomTableSize]; - int amp_; -} VP8Random; - -static void InitRandom(VP8Random* const rg, float dithering) { - memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); - rg->index1_ = 0; - rg->index2_ = 31; - rg->amp_ = (dithering < 0.0) ? 0 - : (dithering > 1.0) ? (1 << DITHER_FIX) - : (uint32_t)((1 << DITHER_FIX) * dithering); -} - -// D.Knuth's Difference-based random generator. -static WEBP_INLINE int Random(VP8Random* const rg, int num_bits) { - int diff; - assert(num_bits + DITHER_FIX <= 31); - diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; - if (diff < 0) diff += (1u << 31); - rg->tab_[rg->index1_] = diff; - if (++rg->index1_ == kRandomTableSize) rg->index1_ = 0; - if (++rg->index2_ == kRandomTableSize) rg->index2_ = 0; - diff = (diff << 1) >> (32 - num_bits); // sign-extend, 0-center - diff = (diff * rg->amp_) >> DITHER_FIX; // restrict range - diff += 1 << (num_bits - 1); // shift back to 0.5-center - return diff; -} - static int RGBToY(int r, int g, int b, VP8Random* const rg) { - return VP8RGBToY(r, g, b, Random(rg, YUV_FIX)); + return VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX)); } static int RGBToU(int r, int g, int b, VP8Random* const rg) { - return VP8RGBToU(r, g, b, Random(rg, YUV_FIX + 2)); + return VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); } static int RGBToV(int r, int g, int b, VP8Random* const rg) { - return VP8RGBToV(r, g, b, Random(rg, YUV_FIX + 2)); + return VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); } //------------------------------------------------------------------------------ @@ -774,7 +729,7 @@ static int ImportYUVAFromRGBA(const uint8_t* const r_ptr, } if (!WebPPictureAlloc(picture)) return 0; - InitRandom(&rg, dithering); + VP8InitRandom(&rg, dithering); InitGammaTables(); // Import luma plane @@ -1100,7 +1055,7 @@ void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) { VP8Random rg; int x, y; if (pic == NULL) return; - InitRandom(&rg, 0.f); + VP8InitRandom(&rg, 0.f); if (!pic->use_argb) { const int uv_width = (pic->width >> 1); // omit last pixel during u/v loop const int Y0 = RGBToY(red, green, blue, &rg); diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 47a0f8ee..86dc6f30 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -23,6 +23,8 @@ COMMON_SOURCES += quant_levels_dec.c COMMON_SOURCES += quant_levels_dec.h COMMON_SOURCES += rescaler.c COMMON_SOURCES += rescaler.h +COMMON_SOURCES += random.c +COMMON_SOURCES += random.h COMMON_SOURCES += thread.c COMMON_SOURCES += thread.h COMMON_SOURCES += utils.c diff --git a/src/utils/random.c b/src/utils/random.c new file mode 100644 index 00000000..76a8fc3c --- /dev/null +++ b/src/utils/random.c @@ -0,0 +1,50 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include "./random.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +//------------------------------------------------------------------------------ + +// 31b-range values +static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = { + 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, + 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, + 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, + 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, + 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, + 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, + 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, + 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, + 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, + 0x27e5ed3c +}; + +void VP8InitRandom(VP8Random* const rg, float dithering) { + memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); + rg->index1_ = 0; + rg->index2_ = 31; + rg->amp_ = (dithering < 0.0) ? 0 + : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX) + : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering); +} + +//------------------------------------------------------------------------------ + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif diff --git a/src/utils/random.h b/src/utils/random.h new file mode 100644 index 00000000..39235316 --- /dev/null +++ b/src/utils/random.h @@ -0,0 +1,56 @@ +// Copyright 2013 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Pseudo-random utilities +// +// Author: Skal (pascal.massimino@gmail.com) + +#ifndef WEBP_UTILS_RANDOM_H_ +#define WEBP_UTILS_RANDOM_H_ + +#include +#include "../webp/types.h" + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#define VP8_RANDOM_DITHER_FIX 8 // fixed-point precision for dithering +#define VP8_RANDOM_TABLE_SIZE 55 + +typedef struct { + int index1_, index2_; + uint32_t tab_[VP8_RANDOM_TABLE_SIZE]; + int amp_; +} VP8Random; + +// Initializes random generator with an amplitude 'dithering' in range [0..1]. +extern void VP8InitRandom(VP8Random* const rg, float dithering); + +// Returns a centered pseudo-random number with 'num_bits' amplitude. +// (uses D.Knuth's Difference-based random generator) +static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { + int diff; + assert(num_bits + VP8_RANDOM_DITHER_FIX <= 31); + diff = rg->tab_[rg->index1_] - rg->tab_[rg->index2_]; + if (diff < 0) diff += (1u << 31); + rg->tab_[rg->index1_] = diff; + if (++rg->index1_ == VP8_RANDOM_TABLE_SIZE) rg->index1_ = 0; + if (++rg->index2_ == VP8_RANDOM_TABLE_SIZE) rg->index2_ = 0; + diff = (diff << 1) >> (32 - num_bits); // sign-extend, 0-center + diff = (diff * rg->amp_) >> VP8_RANDOM_DITHER_FIX; // restrict range + diff += 1 << (num_bits - 1); // shift back to 0.5-center + return diff; +} + +#if defined(__cplusplus) || defined(c_plusplus) +} // extern "C" +#endif + +#endif /* WEBP_UTILS_RANDOM_H_ */