remove use of log2(). Use VP8LFastLog2() instead.

Order-by-cost mostly unchanged (up to a scaling constant 1/log(2))
(except for few minor diff in < 2% of cases)

+ remove unused field cost_mode->cache_bits_

Change-Id: I714f8ab12f49a23f5d499a64c741382c9b489a3e
This commit is contained in:
Pascal Massimino 2012-08-01 18:22:06 -07:00
parent 8c515d54ea
commit 323dc4d9b9
5 changed files with 214 additions and 192 deletions

View File

@ -23,113 +23,156 @@ extern "C" {
#include "../dsp/dsp.h" #include "../dsp/dsp.h"
#include "../enc/histogram.h" #include "../enc/histogram.h"
// A lookup table for small values of log(int) to be used in entropy #define MAX_DIFF_COST (1e30f)
// computation.
// // lookup table for small values of log2(int)
// ", ".join(["%.16ff" % x for x in [0.0]+[log(x) for x in range(1, 256)]]) #define APPROX_LOG_MAX 4096
#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
#define LOG_LOOKUP_IDX_MAX 256 #define LOG_LOOKUP_IDX_MAX 256
static const float kLogTable[LOG_LOOKUP_IDX_MAX] = { static const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
0.0000000000000000f, 0.0000000000000000f, 0.6931471805599453f, 0.0000000000000000f, 0.0000000000000000f,
1.0986122886681098f, 1.3862943611198906f, 1.6094379124341003f, 1.0000000000000000f, 1.5849625007211560f,
1.7917594692280550f, 1.9459101490553132f, 2.0794415416798357f, 2.0000000000000000f, 2.3219280948873621f,
2.1972245773362196f, 2.3025850929940459f, 2.3978952727983707f, 2.5849625007211560f, 2.8073549220576041f,
2.4849066497880004f, 2.5649493574615367f, 2.6390573296152584f, 3.0000000000000000f, 3.1699250014423121f,
2.7080502011022101f, 2.7725887222397811f, 2.8332133440562162f, 3.3219280948873621f, 3.4594316186372973f,
2.8903717578961645f, 2.9444389791664403f, 2.9957322735539909f, 3.5849625007211560f, 3.7004397181410921f,
3.0445224377234230f, 3.0910424533583161f, 3.1354942159291497f, 3.8073549220576041f, 3.9068905956085187f,
3.1780538303479458f, 3.2188758248682006f, 3.2580965380214821f, 4.0000000000000000f, 4.0874628412503390f,
3.2958368660043291f, 3.3322045101752038f, 3.3672958299864741f, 4.1699250014423121f, 4.2479275134435852f,
3.4011973816621555f, 3.4339872044851463f, 3.4657359027997265f, 4.3219280948873626f, 4.3923174227787606f,
3.4965075614664802f, 3.5263605246161616f, 3.5553480614894135f, 4.4594316186372973f, 4.5235619560570130f,
3.5835189384561099f, 3.6109179126442243f, 3.6375861597263857f, 4.5849625007211560f, 4.6438561897747243f,
3.6635616461296463f, 3.6888794541139363f, 3.7135720667043080f, 4.7004397181410917f, 4.7548875021634682f,
3.7376696182833684f, 3.7612001156935624f, 3.7841896339182610f, 4.8073549220576037f, 4.8579809951275718f,
3.8066624897703196f, 3.8286413964890951f, 3.8501476017100584f, 4.9068905956085187f, 4.9541963103868749f,
3.8712010109078911f, 3.8918202981106265f, 3.9120230054281460f, 5.0000000000000000f, 5.0443941193584533f,
3.9318256327243257f, 3.9512437185814275f, 3.9702919135521220f, 5.0874628412503390f, 5.1292830169449663f,
3.9889840465642745f, 4.0073331852324712f, 4.0253516907351496f, 5.1699250014423121f, 5.2094533656289501f,
4.0430512678345503f, 4.0604430105464191f, 4.0775374439057197f, 5.2479275134435852f, 5.2854022188622487f,
4.0943445622221004f, 4.1108738641733114f, 4.1271343850450917f, 5.3219280948873626f, 5.3575520046180837f,
4.1431347263915326f, 4.1588830833596715f, 4.1743872698956368f, 5.3923174227787606f, 5.4262647547020979f,
4.1896547420264252f, 4.2046926193909657f, 4.2195077051761070f, 5.4594316186372973f, 5.4918530963296747f,
4.2341065045972597f, 4.2484952420493594f, 4.2626798770413155f, 5.5235619560570130f, 5.5545888516776376f,
4.2766661190160553f, 4.2904594411483910f, 4.3040650932041702f, 5.5849625007211560f, 5.6147098441152083f,
4.3174881135363101f, 4.3307333402863311f, 4.3438054218536841f, 5.6438561897747243f, 5.6724253419714951f,
4.3567088266895917f, 4.3694478524670215f, 4.3820266346738812f, 5.7004397181410917f, 5.7279204545631987f,
4.3944491546724391f, 4.4067192472642533f, 4.4188406077965983f, 5.7548875021634682f, 5.7813597135246599f,
4.4308167988433134f, 4.4426512564903167f, 4.4543472962535073f, 5.8073549220576037f, 5.8328900141647412f,
4.4659081186545837f, 4.4773368144782069f, 4.4886363697321396f, 5.8579809951275718f, 5.8826430493618415f,
4.4998096703302650f, 4.5108595065168497f, 4.5217885770490405f, 5.9068905956085187f, 5.9307373375628866f,
4.5325994931532563f, 4.5432947822700038f, 4.5538768916005408f, 5.9541963103868749f, 5.9772799234999167f,
4.5643481914678361f, 4.5747109785033828f, 4.5849674786705723f, 6.0000000000000000f, 6.0223678130284543f,
4.5951198501345898f, 4.6051701859880918f, 4.6151205168412597f, 6.0443941193584533f, 6.0660891904577720f,
4.6249728132842707f, 4.6347289882296359f, 4.6443908991413725f, 6.0874628412503390f, 6.1085244567781691f,
4.6539603501575231f, 4.6634390941120669f, 4.6728288344619058f, 6.1292830169449663f, 6.1497471195046822f,
4.6821312271242199f, 4.6913478822291435f, 4.7004803657924166f, 6.1699250014423121f, 6.1898245588800175f,
4.7095302013123339f, 4.7184988712950942f, 4.7273878187123408f, 6.2094533656289501f, 6.2288186904958804f,
4.7361984483944957f, 4.7449321283632502f, 4.7535901911063645f, 6.2479275134435852f, 6.2667865406949010f,
4.7621739347977563f, 4.7706846244656651f, 4.7791234931115296f, 6.2854022188622487f, 6.3037807481771030f,
4.7874917427820458f, 4.7957905455967413f, 4.8040210447332568f, 6.3219280948873626f, 6.3398500028846243f,
4.8121843553724171f, 4.8202815656050371f, 4.8283137373023015f, 6.3575520046180837f, 6.3750394313469245f,
4.8362819069514780f, 4.8441870864585912f, 4.8520302639196169f, 6.3923174227787606f, 6.4093909361377017f,
4.8598124043616719f, 4.8675344504555822f, 4.8751973232011512f, 6.4262647547020979f, 6.4429434958487279f,
4.8828019225863706f, 4.8903491282217537f, 4.8978397999509111f, 6.4594316186372973f, 6.4757334309663976f,
4.9052747784384296f, 4.9126548857360524f, 4.9199809258281251f, 6.4918530963296747f, 6.5077946401986963f,
4.9272536851572051f, 4.9344739331306915f, 4.9416424226093039f, 6.5235619560570130f, 6.5391588111080309f,
4.9487598903781684f, 4.9558270576012609f, 4.9628446302599070f, 6.5545888516776376f, 6.5698556083309478f,
4.9698132995760007f, 4.9767337424205742f, 4.9836066217083363f, 6.5849625007211560f, 6.5999128421871278f,
4.9904325867787360f, 4.9972122737641147f, 5.0039463059454592f, 6.6147098441152083f, 6.6293566200796094f,
5.0106352940962555f, 5.0172798368149243f, 5.0238805208462765f, 6.6438561897747243f, 6.6582114827517946f,
5.0304379213924353f, 5.0369526024136295f, 5.0434251169192468f, 6.6724253419714951f, 6.6865005271832185f,
5.0498560072495371f, 5.0562458053483077f, 5.0625950330269669f, 6.7004397181410917f, 6.7142455176661224f,
5.0689042022202315f, 5.0751738152338266f, 5.0814043649844631f, 6.7279204545631987f, 6.7414669864011464f,
5.0875963352323836f, 5.0937502008067623f, 5.0998664278241987f, 6.7548875021634682f, 6.7681843247769259f,
5.1059454739005803f, 5.1119877883565437f, 5.1179938124167554f, 6.7813597135246599f, 6.7944158663501061f,
5.1239639794032588f, 5.1298987149230735f, 5.1357984370502621f, 6.8073549220576037f, 6.8201789624151878f,
5.1416635565026603f, 5.1474944768134527f, 5.1532915944977793f, 6.8328900141647412f, 6.8454900509443747f,
5.1590552992145291f, 5.1647859739235145f, 5.1704839950381514f, 6.8579809951275718f, 6.8703647195834047f,
5.1761497325738288f, 5.1817835502920850f, 5.1873858058407549f, 6.8826430493618415f, 6.8948177633079437f,
5.1929568508902104f, 5.1984970312658261f, 5.2040066870767951f, 6.9068905956085187f, 6.9188632372745946f,
5.2094861528414214f, 5.2149357576089859f, 5.2203558250783244f, 6.9307373375628866f, 6.9425145053392398f,
5.2257466737132017f, 5.2311086168545868f, 5.2364419628299492f, 6.9541963103868749f, 6.9657842846620869f,
5.2417470150596426f, 5.2470240721604862f, 5.2522734280466299f, 6.9772799234999167f, 6.9886846867721654f,
5.2574953720277815f, 5.2626901889048856f, 5.2678581590633282f, 7.0000000000000000f, 7.0112272554232539f,
5.2729995585637468f, 5.2781146592305168f, 5.2832037287379885f, 7.0223678130284543f, 7.0334230015374501f,
5.2882670306945352f, 5.2933048247244923f, 5.2983173665480363f, 7.0443941193584533f, 7.0552824355011898f,
5.3033049080590757f, 5.3082676974012051f, 5.3132059790417872f, 7.0660891904577720f, 7.0768155970508308f,
5.3181199938442161f, 5.3230099791384085f, 5.3278761687895813f, 7.0874628412503390f, 7.0980320829605263f,
5.3327187932653688f, 5.3375380797013179f, 5.3423342519648109f, 7.1085244567781691f, 7.1189410727235076f,
5.3471075307174685f, 5.3518581334760666f, 5.3565862746720123f, 7.1292830169449663f, 7.1395513523987936f,
5.3612921657094255f, 5.3659760150218512f, 5.3706380281276624f, 7.1497471195046822f, 7.1598713367783890f,
5.3752784076841653f, 5.3798973535404597f, 5.3844950627890888f, 7.1699250014423121f, 7.1799090900149344f,
5.3890717298165010f, 5.3936275463523620f, 5.3981627015177525f, 7.1898245588800175f, 7.1996723448363644f,
5.4026773818722793f, 5.4071717714601188f, 5.4116460518550396f, 7.2094533656289501f, 7.2191685204621611f,
5.4161004022044201f, 5.4205349992722862f, 5.4249500174814029f, 7.2288186904958804f, 7.2384047393250785f,
5.4293456289544411f, 5.4337220035542400f, 5.4380793089231956f, 7.2479275134435852f, 7.2573878426926521f,
5.4424177105217932f, 5.4467373716663099f, 5.4510384535657002f, 7.2667865406949010f, 7.2761244052742375f,
5.4553211153577017f, 5.4595855141441589f, 5.4638318050256105f, 7.2854022188622487f, 7.2946207488916270f,
5.4680601411351315f, 5.4722706736714750f, 5.4764635519315110f, 7.3037807481771030f, 7.3128829552843557f,
5.4806389233419912f, 5.4847969334906548f, 5.4889377261566867f, 7.3219280948873626f, 7.3309168781146167f,
5.4930614433405482f, 5.4971682252932021f, 5.5012582105447274f, 7.3398500028846243f, 7.3487281542310771f,
5.5053315359323625f, 5.5093883366279774f, 5.5134287461649825f, 7.3575520046180837f, 7.3663222142458160f,
5.5174528964647074f, 5.5214609178622460f, 5.5254529391317835f, 7.3750394313469245f, 7.3837042924740519f,
5.5294290875114234f, 5.5333894887275203f, 5.5373342670185366f, 7.3923174227787606f, 7.4008794362821843f,
5.5412635451584258f 7.4093909361377017f, 7.4178525148858982f,
7.4262647547020979f, 7.4346282276367245f,
7.4429434958487279f, 7.4512111118323289f,
7.4594316186372973f, 7.4676055500829976f,
7.4757334309663976f, 7.4838157772642563f,
7.4918530963296747f, 7.4998458870832056f,
7.5077946401986963f, 7.5156998382840427f,
7.5235619560570130f, 7.5313814605163118f,
7.5391588111080309f, 7.5468944598876364f,
7.5545888516776376f, 7.5622424242210728f,
7.5698556083309478f, 7.5774288280357486f,
7.5849625007211560f, 7.5924570372680806f,
7.5999128421871278f, 7.6073303137496104f,
7.6147098441152083f, 7.6220518194563764f,
7.6293566200796094f, 7.6366246205436487f,
7.6438561897747243f, 7.6510516911789281f,
7.6582114827517946f, 7.6653359171851764f,
7.6724253419714951f, 7.6794800995054464f,
7.6865005271832185f, 7.6934869574993252f,
7.7004397181410917f, 7.7073591320808825f,
7.7142455176661224f, 7.7210991887071855f,
7.7279204545631987f, 7.7347096202258383f,
7.7414669864011464f, 7.7481928495894605f,
7.7548875021634682f, 7.7615512324444795f,
7.7681843247769259f, 7.7747870596011736f,
7.7813597135246599f, 7.7879025593914317f,
7.7944158663501061f, 7.8008998999203047f,
7.8073549220576037f, 7.8137811912170374f,
7.8201789624151878f, 7.8265484872909150f,
7.8328900141647412f, 7.8392037880969436f,
7.8454900509443747f, 7.8517490414160571f,
7.8579809951275718f, 7.8641861446542797f,
7.8703647195834047f, 7.8765169465649993f,
7.8826430493618415f, 7.8887432488982591f,
7.8948177633079437f, 7.9008668079807486f,
7.9068905956085187f, 7.9128893362299619f,
7.9188632372745946f, 7.9248125036057812f,
7.9307373375628866f, 7.9366379390025709f,
7.9425145053392398f, 7.9483672315846778f,
7.9541963103868749f, 7.9600019320680805f,
7.9657842846620869f, 7.9715435539507719f,
7.9772799234999167f, 7.9829935746943103f,
7.9886846867721654f, 7.9943534368588577f
}; };
#define APPROX_LOG_MAX 4096 float VP8LFastLog2(int v) {
#define LOG_2_BASE_E 0.6931471805599453f if (v < LOG_LOOKUP_IDX_MAX) {
return kLog2Table[v];
float VP8LFastLog(int v) { } else if (v < APPROX_LOG_MAX) {
if (v < APPROX_LOG_MAX) {
int log_cnt = 0; int log_cnt = 0;
while (v >= LOG_LOOKUP_IDX_MAX) { while (v >= LOG_LOOKUP_IDX_MAX) {
++log_cnt; ++log_cnt;
v = v >> 1; v = v >> 1;
} }
return kLogTable[v] + (log_cnt * LOG_2_BASE_E); return kLog2Table[v] + (float)log_cnt;
} else {
return (float)(LOG_2_RECIPROCAL * log((double)v));
} }
return (float)log(v);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -284,7 +327,7 @@ static const PredictorFunc kPredictors[16] = {
}; };
// TODO(vikasa): Replace 256 etc with defines. // TODO(vikasa): Replace 256 etc with defines.
static double PredictionCostSpatial(const int* counts, static float PredictionCostSpatial(const int* counts,
int weight_0, double exp_val) { int weight_0, double exp_val) {
const int significant_symbols = 16; const int significant_symbols = 16;
const double exp_decay_factor = 0.6; const double exp_decay_factor = 0.6;
@ -294,27 +337,26 @@ static double PredictionCostSpatial(const int* counts,
bits += exp_val * (counts[i] + counts[256 - i]); bits += exp_val * (counts[i] + counts[256 - i]);
exp_val *= exp_decay_factor; exp_val *= exp_decay_factor;
} }
return -0.1 * bits; return (float)(-0.1 * bits);
} }
// Compute the Shanon's entropy: Sum(p*log2(p)) // Compute the Shanon's entropy: Sum(p*log2(p))
static double ShannonEntropy(const int* const array, int n) { static float ShannonEntropy(const int* const array, int n) {
int i; int i;
double retval = 0; float retval = 0.f;
int sum = 0; int sum = 0;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
if (array[i] != 0) { if (array[i] != 0) {
sum += array[i]; sum += array[i];
retval += array[i] * VP8LFastLog(array[i]); retval -= VP8LFastSLog2(array[i]);
} }
} }
retval -= sum * VP8LFastLog(sum); retval += VP8LFastSLog2(sum);
retval *= -1.4426950408889634; // 1.0 / -FastLog(2);
return retval; return retval;
} }
static double PredictionCostSpatialHistogram(int accumulated[4][256], static float PredictionCostSpatialHistogram(int accumulated[4][256],
int tile[4][256]) { int tile[4][256]) {
int i; int i;
int k; int k;
int combo[256]; int combo[256];
@ -328,7 +370,7 @@ static double PredictionCostSpatialHistogram(int accumulated[4][256],
} }
retval += ShannonEntropy(&combo[0], 256); retval += ShannonEntropy(&combo[0], 256);
} }
return retval; return (float)retval;
} }
static int GetBestPredictorForTile(int width, int height, static int GetBestPredictorForTile(int width, int height,
@ -344,14 +386,14 @@ static int GetBestPredictorForTile(int width, int height,
const int xmax = (tile_size <= width - col_start) ? const int xmax = (tile_size <= width - col_start) ?
tile_size : width - col_start; tile_size : width - col_start;
int histo[4][256]; int histo[4][256];
double best_diff = 1e99; float best_diff = MAX_DIFF_COST;
int best_mode = 0; int best_mode = 0;
int mode; int mode;
for (mode = 0; mode < kNumPredModes; ++mode) { for (mode = 0; mode < kNumPredModes; ++mode) {
const uint32_t* current_row = argb_scratch; const uint32_t* current_row = argb_scratch;
const PredictorFunc pred_func = kPredictors[mode]; const PredictorFunc pred_func = kPredictors[mode];
double cur_diff; float cur_diff;
int y; int y;
memset(&histo[0][0], 0, sizeof(histo)); memset(&histo[0][0], 0, sizeof(histo));
for (y = 0; y < ymax; ++y) { for (y = 0; y < ymax; ++y) {
@ -630,8 +672,8 @@ static WEBP_INLINE int SkipRepeatedPixels(const uint32_t* const argb,
return 0; return 0;
} }
static double PredictionCostCrossColor(const int accumulated[256], static float PredictionCostCrossColor(const int accumulated[256],
const int counts[256]) { const int counts[256]) {
// Favor low entropy, locally and globally. // Favor low entropy, locally and globally.
int i; int i;
int combo[256]; int combo[256];
@ -651,8 +693,8 @@ static Multipliers GetBestColorTransformForTile(
int* accumulated_red_histo, int* accumulated_red_histo,
int* accumulated_blue_histo, int* accumulated_blue_histo,
const uint32_t* const argb) { const uint32_t* const argb) {
double best_diff = 1e99; float best_diff = MAX_DIFF_COST;
double cur_diff; float cur_diff;
const int halfstep = step / 2; const int halfstep = step / 2;
const int max_tile_size = 1 << bits; const int max_tile_size = 1 << bits;
const int tile_y_offset = tile_y * max_tile_size; const int tile_y_offset = tile_y * max_tile_size;
@ -704,7 +746,7 @@ static Multipliers GetBestColorTransformForTile(
best_tx = tx; best_tx = tx;
} }
} }
best_diff = 1e99; best_diff = MAX_DIFF_COST;
green_to_red = best_tx.green_to_red_; green_to_red = best_tx.green_to_red_;
for (green_to_blue = -32; green_to_blue <= 32; green_to_blue += step) { for (green_to_blue = -32; green_to_blue <= 32; green_to_blue += step) {
for (red_to_blue = -32; red_to_blue <= 32; red_to_blue += step) { for (red_to_blue = -32; red_to_blue <= 32; red_to_blue += step) {

View File

@ -59,8 +59,10 @@ static WEBP_INLINE uint32_t VP8LSubSampleSize(uint32_t size,
return (size + (1 << sampling_bits) - 1) >> sampling_bits; return (size + (1 << sampling_bits) - 1) >> sampling_bits;
} }
// Faster logarithm for small integers, with the property of log(0) == 0. // Faster logarithm for integers, with the property of log2(0) == 0.
float VP8LFastLog(int v); float VP8LFastLog2(int v);
// Fast calculation of v * log2(v) for integer input.
static WEBP_INLINE float VP8LFastSLog2(int v) { return VP8LFastLog2(v) * v; }
// In-place difference of each component with mod 256. // In-place difference of each component with mod 256.
static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) { static WEBP_INLINE uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {

View File

@ -14,6 +14,7 @@
#include "./backward_references.h" #include "./backward_references.h"
#include "./histogram.h" #include "./histogram.h"
#include "../dsp/lossless.h"
#include "../utils/color_cache.h" #include "../utils/color_cache.h"
#include "../utils/utils.h" #include "../utils/utils.h"
@ -357,46 +358,65 @@ typedef struct {
double literal_[PIX_OR_COPY_CODES_MAX]; double literal_[PIX_OR_COPY_CODES_MAX];
double blue_[VALUES_IN_BYTE]; double blue_[VALUES_IN_BYTE];
double distance_[NUM_DISTANCE_CODES]; double distance_[NUM_DISTANCE_CODES];
int cache_bits_;
} CostModel; } CostModel;
static int BackwardReferencesTraceBackwards( static int BackwardReferencesTraceBackwards(
int xsize, int ysize, int recursive_cost_model, int xsize, int ysize, int recursive_cost_model,
const uint32_t* const argb, int cache_bits, VP8LBackwardRefs* const refs); const uint32_t* const argb, int cache_bits, VP8LBackwardRefs* const refs);
static int CostModelBuild(CostModel* const p, int xsize, int ysize, static void ConvertPopulationCountTableToBitEstimates(
int num_symbols, const int population_counts[], double output[]) {
int sum = 0;
int nonzeros = 0;
int i;
for (i = 0; i < num_symbols; ++i) {
sum += population_counts[i];
if (population_counts[i] > 0) {
++nonzeros;
}
}
if (nonzeros <= 1) {
memset(output, 0, num_symbols * sizeof(*output));
} else {
const double logsum = VP8LFastLog2(sum);
for (i = 0; i < num_symbols; ++i) {
output[i] = logsum - VP8LFastLog2(population_counts[i]);
}
}
}
static int CostModelBuild(CostModel* const m, int xsize, int ysize,
int recursion_level, const uint32_t* const argb, int recursion_level, const uint32_t* const argb,
int cache_bits) { int cache_bits) {
int ok = 0; int ok = 0;
VP8LHistogram histo; VP8LHistogram histo;
VP8LBackwardRefs refs; VP8LBackwardRefs refs;
const int quality = 100;
if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize)) goto Error; if (!VP8LBackwardRefsAlloc(&refs, xsize * ysize)) goto Error;
p->cache_bits_ = cache_bits;
if (recursion_level > 0) { if (recursion_level > 0) {
if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1, if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1,
argb, cache_bits, &refs)) { argb, cache_bits, &refs)) {
goto Error; goto Error;
} }
} else { } else {
const int quality = 100;
if (!BackwardReferencesHashChain(xsize, ysize, argb, cache_bits, quality, if (!BackwardReferencesHashChain(xsize, ysize, argb, cache_bits, quality,
&refs)) { &refs)) {
goto Error; goto Error;
} }
} }
VP8LHistogramCreate(&histo, &refs, cache_bits); VP8LHistogramCreate(&histo, &refs, cache_bits);
VP8LConvertPopulationCountTableToBitEstimates( ConvertPopulationCountTableToBitEstimates(
VP8LHistogramNumCodes(&histo), histo.literal_, p->literal_); VP8LHistogramNumCodes(&histo), histo.literal_, m->literal_);
VP8LConvertPopulationCountTableToBitEstimates( ConvertPopulationCountTableToBitEstimates(
VALUES_IN_BYTE, histo.red_, p->red_); VALUES_IN_BYTE, histo.red_, m->red_);
VP8LConvertPopulationCountTableToBitEstimates( ConvertPopulationCountTableToBitEstimates(
VALUES_IN_BYTE, histo.blue_, p->blue_); VALUES_IN_BYTE, histo.blue_, m->blue_);
VP8LConvertPopulationCountTableToBitEstimates( ConvertPopulationCountTableToBitEstimates(
VALUES_IN_BYTE, histo.alpha_, p->alpha_); VALUES_IN_BYTE, histo.alpha_, m->alpha_);
VP8LConvertPopulationCountTableToBitEstimates( ConvertPopulationCountTableToBitEstimates(
NUM_DISTANCE_CODES, histo.distance_, p->distance_); NUM_DISTANCE_CODES, histo.distance_, m->distance_);
ok = 1; ok = 1;
Error: Error:
@ -404,30 +424,30 @@ static int CostModelBuild(CostModel* const p, int xsize, int ysize,
return ok; return ok;
} }
static WEBP_INLINE double GetLiteralCost(const CostModel* const p, uint32_t v) { static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) {
return p->alpha_[v >> 24] + return m->alpha_[v >> 24] +
p->red_[(v >> 16) & 0xff] + m->red_[(v >> 16) & 0xff] +
p->literal_[(v >> 8) & 0xff] + m->literal_[(v >> 8) & 0xff] +
p->blue_[v & 0xff]; m->blue_[v & 0xff];
} }
static WEBP_INLINE double GetCacheCost(const CostModel* const p, uint32_t idx) { static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx;
return p->literal_[literal_idx]; return m->literal_[literal_idx];
} }
static WEBP_INLINE double GetLengthCost(const CostModel* const p, static WEBP_INLINE double GetLengthCost(const CostModel* const m,
uint32_t length) { uint32_t length) {
int code, extra_bits_count, extra_bits_value; int code, extra_bits_count, extra_bits_value;
PrefixEncode(length, &code, &extra_bits_count, &extra_bits_value); PrefixEncode(length, &code, &extra_bits_count, &extra_bits_value);
return p->literal_[VALUES_IN_BYTE + code] + extra_bits_count; return m->literal_[VALUES_IN_BYTE + code] + extra_bits_count;
} }
static WEBP_INLINE double GetDistanceCost(const CostModel* const p, static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
uint32_t distance) { uint32_t distance) {
int code, extra_bits_count, extra_bits_value; int code, extra_bits_count, extra_bits_value;
PrefixEncode(distance, &code, &extra_bits_count, &extra_bits_value); PrefixEncode(distance, &code, &extra_bits_count, &extra_bits_value);
return p->distance_[code] + extra_bits_count; return m->distance_[code] + extra_bits_count;
} }
static int BackwardReferencesHashChainDistanceOnly( static int BackwardReferencesHashChainDistanceOnly(

View File

@ -19,17 +19,6 @@
#include "../dsp/lossless.h" #include "../dsp/lossless.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#if defined(_MSC_VER) && !defined(NOT_HAVE_LOG2)
# define NOT_HAVE_LOG2 1
#endif
#ifdef NOT_HAVE_LOG2
static WEBP_INLINE double log2(double d) {
const double kLog2Reciprocal = 1.442695040888963;
return log(d) * kLog2Reciprocal;
}
#endif
static void HistogramClear(VP8LHistogram* const p) { static void HistogramClear(VP8LHistogram* const p) {
memset(p->literal_, 0, sizeof(p->literal_)); memset(p->literal_, 0, sizeof(p->literal_));
memset(p->red_, 0, sizeof(p->red_)); memset(p->red_, 0, sizeof(p->red_));
@ -88,33 +77,6 @@ VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void VP8LConvertPopulationCountTableToBitEstimates(
int num_symbols, const int population_counts[], double output[]) {
int sum = 0;
int nonzeros = 0;
int i;
for (i = 0; i < num_symbols; ++i) {
sum += population_counts[i];
if (population_counts[i] > 0) {
++nonzeros;
}
}
if (nonzeros <= 1) {
memset(output, 0, num_symbols * sizeof(*output));
return;
}
{
const double log2sum = log2(sum);
for (i = 0; i < num_symbols; ++i) {
if (population_counts[i] == 0) {
output[i] = log2sum;
} else {
output[i] = log2sum - log2(population_counts[i]);
}
}
}
}
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
const PixOrCopy* const v) { const PixOrCopy* const v) {
if (PixOrCopyIsLiteral(v)) { if (PixOrCopyIsLiteral(v)) {
@ -139,7 +101,7 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo,
static double BitsEntropy(const int* const array, int n) { static double BitsEntropy(const int* const array, int n) {
double retval = 0; double retval = 0.;
int sum = 0; int sum = 0;
int nonzeros = 0; int nonzeros = 0;
int max_val = 0; int max_val = 0;
@ -149,15 +111,14 @@ static double BitsEntropy(const int* const array, int n) {
if (array[i] != 0) { if (array[i] != 0) {
sum += array[i]; sum += array[i];
++nonzeros; ++nonzeros;
retval += array[i] * VP8LFastLog(array[i]); retval -= VP8LFastSLog2(array[i]);
if (max_val < array[i]) { if (max_val < array[i]) {
max_val = array[i]; max_val = array[i];
} }
} }
} }
retval -= sum * VP8LFastLog(sum); retval += VP8LFastSLog2(sum);
retval *= -1.4426950408889634; // 1.0 / -Log(2);
mix = 0.627;
if (nonzeros < 5) { if (nonzeros < 5) {
if (nonzeros <= 1) { if (nonzeros <= 1) {
return 0; return 0;
@ -177,15 +138,15 @@ static double BitsEntropy(const int* const array, int n) {
} else { } else {
mix = 0.7; // nonzeros == 4. mix = 0.7; // nonzeros == 4.
} }
} else {
mix = 0.627;
} }
{ {
double min_limit = 2 * sum - max_val; double min_limit = 2 * sum - max_val;
min_limit = mix * min_limit + (1.0 - mix) * retval; min_limit = mix * min_limit + (1.0 - mix) * retval;
if (retval < min_limit) { return (retval < min_limit) ? min_limit : retval;
return min_limit;
}
} }
return retval;
} }
double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) { double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) {

View File

@ -101,9 +101,6 @@ static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) {
((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0); ((p->palette_code_bits_ > 0) ? (1 << p->palette_code_bits_) : 0);
} }
void VP8LConvertPopulationCountTableToBitEstimates(
int num_symbols, const int population_counts[], double output[]);
// Builds the histogram image. // Builds the histogram image.
int VP8LGetHistoImageSymbols(int xsize, int ysize, int VP8LGetHistoImageSymbols(int xsize, int ysize,
const VP8LBackwardRefs* const refs, const VP8LBackwardRefs* const refs,