mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 05:38:22 +01:00
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:
parent
8c515d54ea
commit
323dc4d9b9
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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(
|
||||||
|
@ -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) {
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user