tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

histogram_enc.c (44593B)


      1 // Copyright 2012 Google Inc. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the COPYING file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS. All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 // -----------------------------------------------------------------------------
      9 //
     10 // Author: Jyrki Alakuijala (jyrki@google.com)
     11 //
     12 #ifdef HAVE_CONFIG_H
     13 #include "src/webp/config.h"
     14 #endif
     15 
     16 #include <assert.h>
     17 #include <stdlib.h>
     18 #include <string.h>
     19 
     20 #include "src/dsp/lossless.h"
     21 #include "src/dsp/lossless_common.h"
     22 #include "src/enc/backward_references_enc.h"
     23 #include "src/enc/histogram_enc.h"
     24 #include "src/enc/vp8i_enc.h"
     25 #include "src/utils/utils.h"
     26 #include "src/webp/encode.h"
     27 #include "src/webp/format_constants.h"
     28 #include "src/webp/types.h"
     29 
     30 // Number of partitions for the three dominant (literal, red and blue) symbol
     31 // costs.
     32 #define NUM_PARTITIONS 4
     33 // The size of the bin-hash corresponding to the three dominant costs.
     34 #define BIN_SIZE (NUM_PARTITIONS * NUM_PARTITIONS * NUM_PARTITIONS)
     35 // Maximum number of histograms allowed in greedy combining algorithm.
     36 #define MAX_HISTO_GREEDY 100
     37 
     38 // Enum to meaningfully access the elements of the Histogram arrays.
     39 typedef enum {
     40  LITERAL = 0,
     41  RED,
     42  BLUE,
     43  ALPHA,
     44  DISTANCE
     45 } HistogramIndex;
     46 
     47 // Return the size of the histogram for a given cache_bits.
     48 static int GetHistogramSize(int cache_bits) {
     49  const int literal_size = VP8LHistogramNumCodes(cache_bits);
     50  const size_t total_size = sizeof(VP8LHistogram) + sizeof(int) * literal_size;
     51  assert(total_size <= (size_t)0x7fffffff);
     52  return (int)total_size;
     53 }
     54 
     55 static void HistogramStatsClear(VP8LHistogram* const h) {
     56  int i;
     57  for (i = 0; i < 5; ++i) {
     58    h->trivial_symbol[i] = VP8L_NON_TRIVIAL_SYM;
     59    // By default, the histogram is assumed to be used.
     60    h->is_used[i] = 1;
     61  }
     62  h->bit_cost = 0;
     63  memset(h->costs, 0, sizeof(h->costs));
     64 }
     65 
     66 static void HistogramClear(VP8LHistogram* const h) {
     67  uint32_t* const literal = h->literal;
     68  const int cache_bits = h->palette_code_bits;
     69  const int histo_size = GetHistogramSize(cache_bits);
     70  memset(h, 0, histo_size);
     71  h->palette_code_bits = cache_bits;
     72  h->literal = literal;
     73  HistogramStatsClear(h);
     74 }
     75 
     76 // Swap two histogram pointers.
     77 static void HistogramSwap(VP8LHistogram** const h1, VP8LHistogram** const h2) {
     78  VP8LHistogram* const tmp = *h1;
     79  *h1 = *h2;
     80  *h2 = tmp;
     81 }
     82 
     83 static void HistogramCopy(const VP8LHistogram* const src,
     84                          VP8LHistogram* const dst) {
     85  uint32_t* const dst_literal = dst->literal;
     86  const int dst_cache_bits = dst->palette_code_bits;
     87  const int literal_size = VP8LHistogramNumCodes(dst_cache_bits);
     88  const int histo_size = GetHistogramSize(dst_cache_bits);
     89  assert(src->palette_code_bits == dst_cache_bits);
     90  memcpy(dst, src, histo_size);
     91  dst->literal = dst_literal;
     92  memcpy(dst->literal, src->literal, literal_size * sizeof(*dst->literal));
     93 }
     94 
     95 void VP8LFreeHistogram(VP8LHistogram* const h) { WebPSafeFree(h); }
     96 
     97 void VP8LFreeHistogramSet(VP8LHistogramSet* const histograms) {
     98  WebPSafeFree(histograms);
     99 }
    100 
    101 void VP8LHistogramCreate(VP8LHistogram* const h,
    102                         const VP8LBackwardRefs* const refs,
    103                         int palette_code_bits) {
    104  if (palette_code_bits >= 0) {
    105    h->palette_code_bits = palette_code_bits;
    106  }
    107  HistogramClear(h);
    108  VP8LHistogramStoreRefs(refs, /*distance_modifier=*/NULL,
    109                         /*distance_modifier_arg0=*/0, h);
    110 }
    111 
    112 void VP8LHistogramInit(VP8LHistogram* const h, int palette_code_bits,
    113                       int init_arrays) {
    114  h->palette_code_bits = palette_code_bits;
    115  if (init_arrays) {
    116    HistogramClear(h);
    117  } else {
    118    HistogramStatsClear(h);
    119  }
    120 }
    121 
    122 VP8LHistogram* VP8LAllocateHistogram(int cache_bits) {
    123  VP8LHistogram* histo = NULL;
    124  const int total_size = GetHistogramSize(cache_bits);
    125  uint8_t* const memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
    126  if (memory == NULL) return NULL;
    127  histo = (VP8LHistogram*)memory;
    128  // 'literal' won't necessary be aligned.
    129  histo->literal = (uint32_t*)(memory + sizeof(VP8LHistogram));
    130  VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 0);
    131  return histo;
    132 }
    133 
    134 // Resets the pointers of the histograms to point to the bit buffer in the set.
    135 static void HistogramSetResetPointers(VP8LHistogramSet* const set,
    136                                      int cache_bits) {
    137  int i;
    138  const int histo_size = GetHistogramSize(cache_bits);
    139  uint8_t* memory = (uint8_t*) (set->histograms);
    140  memory += set->max_size * sizeof(*set->histograms);
    141  for (i = 0; i < set->max_size; ++i) {
    142    memory = (uint8_t*) WEBP_ALIGN(memory);
    143    set->histograms[i] = (VP8LHistogram*) memory;
    144    // 'literal' won't necessary be aligned.
    145    set->histograms[i]->literal = (uint32_t*)(memory + sizeof(VP8LHistogram));
    146    memory += histo_size;
    147  }
    148 }
    149 
    150 // Returns the total size of the VP8LHistogramSet.
    151 static size_t HistogramSetTotalSize(int size, int cache_bits) {
    152  const int histo_size = GetHistogramSize(cache_bits);
    153  return (sizeof(VP8LHistogramSet) + size * (sizeof(VP8LHistogram*) +
    154          histo_size + WEBP_ALIGN_CST));
    155 }
    156 
    157 VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) {
    158  int i;
    159  VP8LHistogramSet* set;
    160  const size_t total_size = HistogramSetTotalSize(size, cache_bits);
    161  uint8_t* memory = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*memory));
    162  if (memory == NULL) return NULL;
    163 
    164  set = (VP8LHistogramSet*)memory;
    165  memory += sizeof(*set);
    166  set->histograms = (VP8LHistogram**)memory;
    167  set->max_size = size;
    168  set->size = size;
    169  HistogramSetResetPointers(set, cache_bits);
    170  for (i = 0; i < size; ++i) {
    171    VP8LHistogramInit(set->histograms[i], cache_bits, /*init_arrays=*/ 0);
    172  }
    173  return set;
    174 }
    175 
    176 void VP8LHistogramSetClear(VP8LHistogramSet* const set) {
    177  int i;
    178  const int cache_bits = set->histograms[0]->palette_code_bits;
    179  const int size = set->max_size;
    180  const size_t total_size = HistogramSetTotalSize(size, cache_bits);
    181  uint8_t* memory = (uint8_t*)set;
    182 
    183  memset(memory, 0, total_size);
    184  memory += sizeof(*set);
    185  set->histograms = (VP8LHistogram**)memory;
    186  set->max_size = size;
    187  set->size = size;
    188  HistogramSetResetPointers(set, cache_bits);
    189  for (i = 0; i < size; ++i) {
    190    set->histograms[i]->palette_code_bits = cache_bits;
    191  }
    192 }
    193 
    194 // Removes the histogram 'i' from 'set'.
    195 static void HistogramSetRemoveHistogram(VP8LHistogramSet* const set, int i) {
    196  set->histograms[i] = set->histograms[set->size - 1];
    197  --set->size;
    198  assert(set->size > 0);
    199 }
    200 
    201 // -----------------------------------------------------------------------------
    202 
    203 static void HistogramAddSinglePixOrCopy(
    204    VP8LHistogram* const histo, const PixOrCopy* const v,
    205    int (*const distance_modifier)(int, int), int distance_modifier_arg0) {
    206  if (PixOrCopyIsLiteral(v)) {
    207    ++histo->alpha[PixOrCopyLiteral(v, 3)];
    208    ++histo->red[PixOrCopyLiteral(v, 2)];
    209    ++histo->literal[PixOrCopyLiteral(v, 1)];
    210    ++histo->blue[PixOrCopyLiteral(v, 0)];
    211  } else if (PixOrCopyIsCacheIdx(v)) {
    212    const int literal_ix =
    213        NUM_LITERAL_CODES + NUM_LENGTH_CODES + PixOrCopyCacheIdx(v);
    214    assert(histo->palette_code_bits != 0);
    215    ++histo->literal[literal_ix];
    216  } else {
    217    int code, extra_bits;
    218    VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits);
    219    ++histo->literal[NUM_LITERAL_CODES + code];
    220    if (distance_modifier == NULL) {
    221      VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits);
    222    } else {
    223      VP8LPrefixEncodeBits(
    224          distance_modifier(distance_modifier_arg0, PixOrCopyDistance(v)),
    225          &code, &extra_bits);
    226    }
    227    ++histo->distance[code];
    228  }
    229 }
    230 
    231 void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
    232                            int (*const distance_modifier)(int, int),
    233                            int distance_modifier_arg0,
    234                            VP8LHistogram* const histo) {
    235  VP8LRefsCursor c = VP8LRefsCursorInit(refs);
    236  while (VP8LRefsCursorOk(&c)) {
    237    HistogramAddSinglePixOrCopy(histo, c.cur_pos, distance_modifier,
    238                                distance_modifier_arg0);
    239    VP8LRefsCursorNext(&c);
    240  }
    241 }
    242 
    243 // -----------------------------------------------------------------------------
    244 // Entropy-related functions.
    245 
    246 static WEBP_INLINE uint64_t BitsEntropyRefine(const VP8LBitEntropy* entropy) {
    247  uint64_t mix;
    248  if (entropy->nonzeros < 5) {
    249    if (entropy->nonzeros <= 1) {
    250      return 0;
    251    }
    252    // Two symbols, they will be 0 and 1 in a Huffman code.
    253    // Let's mix in a bit of entropy to favor good clustering when
    254    // distributions of these are combined.
    255    if (entropy->nonzeros == 2) {
    256      return DivRound(99 * ((uint64_t)entropy->sum << LOG_2_PRECISION_BITS) +
    257                          entropy->entropy,
    258                      100);
    259    }
    260    // No matter what the entropy says, we cannot be better than min_limit
    261    // with Huffman coding. I am mixing a bit of entropy into the
    262    // min_limit since it produces much better (~0.5 %) compression results
    263    // perhaps because of better entropy clustering.
    264    if (entropy->nonzeros == 3) {
    265      mix = 950;
    266    } else {
    267      mix = 700;  // nonzeros == 4.
    268    }
    269  } else {
    270    mix = 627;
    271  }
    272 
    273  {
    274    uint64_t min_limit = (uint64_t)(2 * entropy->sum - entropy->max_val)
    275                         << LOG_2_PRECISION_BITS;
    276    min_limit =
    277        DivRound(mix * min_limit + (1000 - mix) * entropy->entropy, 1000);
    278    return (entropy->entropy < min_limit) ? min_limit : entropy->entropy;
    279  }
    280 }
    281 
    282 uint64_t VP8LBitsEntropy(const uint32_t* const array, int n) {
    283  VP8LBitEntropy entropy;
    284  VP8LBitsEntropyUnrefined(array, n, &entropy);
    285 
    286  return BitsEntropyRefine(&entropy);
    287 }
    288 
    289 static uint64_t InitialHuffmanCost(void) {
    290  // Small bias because Huffman code length is typically not stored in
    291  // full length.
    292  static const uint64_t kHuffmanCodeOfHuffmanCodeSize = CODE_LENGTH_CODES * 3;
    293  // Subtract a bias of 9.1.
    294  return (kHuffmanCodeOfHuffmanCodeSize << LOG_2_PRECISION_BITS) -
    295         DivRound(91ll << LOG_2_PRECISION_BITS, 10);
    296 }
    297 
    298 // Finalize the Huffman cost based on streak numbers and length type (<3 or >=3)
    299 static uint64_t FinalHuffmanCost(const VP8LStreaks* const stats) {
    300  // The constants in this function are empirical and got rounded from
    301  // their original values in 1/8 when switched to 1/1024.
    302  uint64_t retval = InitialHuffmanCost();
    303  // Second coefficient: Many zeros in the histogram are covered efficiently
    304  // by a run-length encode. Originally 2/8.
    305  uint32_t retval_extra = stats->counts[0] * 1600 + 240 * stats->streaks[0][1];
    306  // Second coefficient: Constant values are encoded less efficiently, but still
    307  // RLE'ed. Originally 6/8.
    308  retval_extra += stats->counts[1] * 2640 + 720 * stats->streaks[1][1];
    309  // 0s are usually encoded more efficiently than non-0s.
    310  // Originally 15/8.
    311  retval_extra += 1840 * stats->streaks[0][0];
    312  // Originally 26/8.
    313  retval_extra += 3360 * stats->streaks[1][0];
    314  return retval + ((uint64_t)retval_extra << (LOG_2_PRECISION_BITS - 10));
    315 }
    316 
    317 // Get the symbol entropy for the distribution 'population'.
    318 // Set 'trivial_sym', if there's only one symbol present in the distribution.
    319 static uint64_t PopulationCost(const uint32_t* const population, int length,
    320                               uint16_t* const trivial_sym,
    321                               uint8_t* const is_used) {
    322  VP8LBitEntropy bit_entropy;
    323  VP8LStreaks stats;
    324  VP8LGetEntropyUnrefined(population, length, &bit_entropy, &stats);
    325  if (trivial_sym != NULL) {
    326    *trivial_sym = (bit_entropy.nonzeros == 1) ? bit_entropy.nonzero_code
    327                                               : VP8L_NON_TRIVIAL_SYM;
    328  }
    329  if (is_used != NULL) {
    330    // The histogram is used if there is at least one non-zero streak.
    331    *is_used = (stats.streaks[1][0] != 0 || stats.streaks[1][1] != 0);
    332  }
    333 
    334  return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
    335 }
    336 
    337 static WEBP_INLINE void GetPopulationInfo(const VP8LHistogram* const histo,
    338                                          HistogramIndex index,
    339                                          const uint32_t** population,
    340                                          int* length) {
    341  switch (index) {
    342    case LITERAL:
    343      *population = histo->literal;
    344      *length = VP8LHistogramNumCodes(histo->palette_code_bits);
    345      break;
    346    case RED:
    347      *population = histo->red;
    348      *length = NUM_LITERAL_CODES;
    349      break;
    350    case BLUE:
    351      *population = histo->blue;
    352      *length = NUM_LITERAL_CODES;
    353      break;
    354    case ALPHA:
    355      *population = histo->alpha;
    356      *length = NUM_LITERAL_CODES;
    357      break;
    358    case DISTANCE:
    359      *population = histo->distance;
    360      *length = NUM_DISTANCE_CODES;
    361      break;
    362  }
    363 }
    364 
    365 // trivial_at_end is 1 if the two histograms only have one element that is
    366 // non-zero: both the zero-th one, or both the last one.
    367 // 'index' is the index of the symbol in the histogram (literal, red, blue,
    368 // alpha, distance).
    369 static WEBP_INLINE uint64_t GetCombinedEntropy(const VP8LHistogram* const h1,
    370                                               const VP8LHistogram* const h2,
    371                                               HistogramIndex index) {
    372  const uint32_t* X;
    373  const uint32_t* Y;
    374  int length;
    375  VP8LStreaks stats;
    376  VP8LBitEntropy bit_entropy;
    377  const int is_h1_used = h1->is_used[index];
    378  const int is_h2_used = h2->is_used[index];
    379  const int is_trivial = h1->trivial_symbol[index] != VP8L_NON_TRIVIAL_SYM &&
    380                         h1->trivial_symbol[index] == h2->trivial_symbol[index];
    381 
    382  if (is_trivial || !is_h1_used || !is_h2_used) {
    383    if (is_h1_used) return h1->costs[index];
    384    return h2->costs[index];
    385  }
    386  assert(is_h1_used && is_h2_used);
    387 
    388  GetPopulationInfo(h1, index, &X, &length);
    389  GetPopulationInfo(h2, index, &Y, &length);
    390  VP8LGetCombinedEntropyUnrefined(X, Y, length, &bit_entropy, &stats);
    391  return BitsEntropyRefine(&bit_entropy) + FinalHuffmanCost(&stats);
    392 }
    393 
    394 // Estimates the Entropy + Huffman + other block overhead size cost.
    395 uint64_t VP8LHistogramEstimateBits(const VP8LHistogram* const h) {
    396  int i;
    397  uint64_t cost = 0;
    398  for (i = 0; i < 5; ++i) {
    399    int length;
    400    const uint32_t* population;
    401    GetPopulationInfo(h, (HistogramIndex)i, &population, &length);
    402    cost += PopulationCost(population, length, /*trivial_sym=*/NULL,
    403                           /*is_used=*/NULL);
    404  }
    405  cost += ((uint64_t)(VP8LExtraCost(h->literal + NUM_LITERAL_CODES,
    406                                    NUM_LENGTH_CODES) +
    407                      VP8LExtraCost(h->distance, NUM_DISTANCE_CODES))
    408           << LOG_2_PRECISION_BITS);
    409  return cost;
    410 }
    411 
    412 // -----------------------------------------------------------------------------
    413 // Various histogram combine/cost-eval functions
    414 
    415 // Set a + b in b, saturating at WEBP_INT64_MAX.
    416 static WEBP_INLINE void SaturateAdd(uint64_t a, int64_t* b) {
    417  if (*b < 0 || (int64_t)a <= WEBP_INT64_MAX - *b) {
    418    *b += (int64_t)a;
    419  } else {
    420    *b = WEBP_INT64_MAX;
    421  }
    422 }
    423 
    424 // Returns 1 if the cost of the combined histogram is less than the threshold.
    425 // Otherwise returns 0 and the cost is invalid due to early bail-out.
    426 WEBP_NODISCARD static int GetCombinedHistogramEntropy(
    427    const VP8LHistogram* const a, const VP8LHistogram* const b,
    428    int64_t cost_threshold_in, uint64_t* cost, uint64_t costs[5]) {
    429  int i;
    430  const uint64_t cost_threshold = (uint64_t)cost_threshold_in;
    431  assert(a->palette_code_bits == b->palette_code_bits);
    432  if (cost_threshold_in <= 0) return 0;
    433  *cost = 0;
    434 
    435  // No need to add the extra cost for length and distance as it is a constant
    436  // that does not influence the histograms.
    437  for (i = 0; i < 5; ++i) {
    438    costs[i] = GetCombinedEntropy(a, b, (HistogramIndex)i);
    439    *cost += costs[i];
    440    if (*cost >= cost_threshold) return 0;
    441  }
    442 
    443  return 1;
    444 }
    445 
    446 static WEBP_INLINE void HistogramAdd(const VP8LHistogram* const h1,
    447                                     const VP8LHistogram* const h2,
    448                                     VP8LHistogram* const hout) {
    449  int i;
    450  assert(h1->palette_code_bits == h2->palette_code_bits);
    451 
    452  for (i = 0; i < 5; ++i) {
    453    int length;
    454    const uint32_t *p1, *p2, *pout_const;
    455    uint32_t* pout;
    456    GetPopulationInfo(h1, (HistogramIndex)i, &p1, &length);
    457    GetPopulationInfo(h2, (HistogramIndex)i, &p2, &length);
    458    GetPopulationInfo(hout, (HistogramIndex)i, &pout_const, &length);
    459    pout = (uint32_t*)pout_const;
    460    if (h2 == hout) {
    461      if (h1->is_used[i]) {
    462        if (hout->is_used[i]) {
    463          VP8LAddVectorEq(p1, pout, length);
    464        } else {
    465          memcpy(pout, p1, length * sizeof(pout[0]));
    466        }
    467      }
    468    } else {
    469      if (h1->is_used[i]) {
    470        if (h2->is_used[i]) {
    471          VP8LAddVector(p1, p2, pout, length);
    472        } else {
    473          memcpy(pout, p1, length * sizeof(pout[0]));
    474        }
    475      } else if (h2->is_used[i]) {
    476        memcpy(pout, p2, length * sizeof(pout[0]));
    477      } else {
    478        memset(pout, 0, length * sizeof(pout[0]));
    479      }
    480    }
    481  }
    482 
    483  for (i = 0; i < 5; ++i) {
    484    hout->trivial_symbol[i] = h1->trivial_symbol[i] == h2->trivial_symbol[i]
    485                                  ? h1->trivial_symbol[i]
    486                                  : VP8L_NON_TRIVIAL_SYM;
    487    hout->is_used[i] = h1->is_used[i] || h2->is_used[i];
    488  }
    489 }
    490 
    491 static void UpdateHistogramCost(uint64_t bit_cost, uint64_t costs[5],
    492                                VP8LHistogram* const h) {
    493  int i;
    494  h->bit_cost = bit_cost;
    495  for (i = 0; i < 5; ++i) {
    496    h->costs[i] = costs[i];
    497  }
    498 }
    499 
    500 // Performs out = a + b, computing the cost C(a+b) - C(a) - C(b) while comparing
    501 // to the threshold value 'cost_threshold'. The score returned is
    502 //  Score = C(a+b) - C(a) - C(b), where C(a) + C(b) is known and fixed.
    503 // Since the previous score passed is 'cost_threshold', we only need to compare
    504 // the partial cost against 'cost_threshold + C(a) + C(b)' to possibly bail-out
    505 // early.
    506 // Returns 1 if the cost is less than the threshold.
    507 // Otherwise returns 0 and the cost is invalid due to early bail-out.
    508 WEBP_NODISCARD static int HistogramAddEval(const VP8LHistogram* const a,
    509                                           const VP8LHistogram* const b,
    510                                           VP8LHistogram* const out,
    511                                           int64_t cost_threshold) {
    512  const uint64_t sum_cost = a->bit_cost + b->bit_cost;
    513  uint64_t bit_cost, costs[5];
    514  SaturateAdd(sum_cost, &cost_threshold);
    515  if (!GetCombinedHistogramEntropy(a, b, cost_threshold, &bit_cost, costs)) {
    516    return 0;
    517  }
    518 
    519  HistogramAdd(a, b, out);
    520  UpdateHistogramCost(bit_cost, costs, out);
    521  return 1;
    522 }
    523 
    524 // Same as HistogramAddEval(), except that the resulting histogram
    525 // is not stored. Only the cost C(a+b) - C(a) is evaluated. We omit
    526 // the term C(b) which is constant over all the evaluations.
    527 // Returns 1 if the cost is less than the threshold.
    528 // Otherwise returns 0 and the cost is invalid due to early bail-out.
    529 WEBP_NODISCARD static int HistogramAddThresh(const VP8LHistogram* const a,
    530                                             const VP8LHistogram* const b,
    531                                             int64_t cost_threshold,
    532                                             int64_t* cost_out) {
    533  uint64_t cost, costs[5];
    534  assert(a != NULL && b != NULL);
    535  SaturateAdd(a->bit_cost, &cost_threshold);
    536  if (!GetCombinedHistogramEntropy(a, b, cost_threshold, &cost, costs)) {
    537    return 0;
    538  }
    539 
    540  *cost_out = (int64_t)cost - (int64_t)a->bit_cost;
    541  return 1;
    542 }
    543 
    544 // -----------------------------------------------------------------------------
    545 
    546 // The structure to keep track of cost range for the three dominant entropy
    547 // symbols.
    548 typedef struct {
    549  uint64_t literal_max;
    550  uint64_t literal_min;
    551  uint64_t red_max;
    552  uint64_t red_min;
    553  uint64_t blue_max;
    554  uint64_t blue_min;
    555 } DominantCostRange;
    556 
    557 static void DominantCostRangeInit(DominantCostRange* const c) {
    558  c->literal_max = 0;
    559  c->literal_min = WEBP_UINT64_MAX;
    560  c->red_max = 0;
    561  c->red_min = WEBP_UINT64_MAX;
    562  c->blue_max = 0;
    563  c->blue_min = WEBP_UINT64_MAX;
    564 }
    565 
    566 static void UpdateDominantCostRange(
    567    const VP8LHistogram* const h, DominantCostRange* const c) {
    568  if (c->literal_max < h->costs[LITERAL]) c->literal_max = h->costs[LITERAL];
    569  if (c->literal_min > h->costs[LITERAL]) c->literal_min = h->costs[LITERAL];
    570  if (c->red_max < h->costs[RED]) c->red_max = h->costs[RED];
    571  if (c->red_min > h->costs[RED]) c->red_min = h->costs[RED];
    572  if (c->blue_max < h->costs[BLUE]) c->blue_max = h->costs[BLUE];
    573  if (c->blue_min > h->costs[BLUE]) c->blue_min = h->costs[BLUE];
    574 }
    575 
    576 static void ComputeHistogramCost(VP8LHistogram* const h) {
    577  int i;
    578  // No need to add the extra cost for length and distance as it is a constant
    579  // that does not influence the histograms.
    580  for (i = 0; i < 5; ++i) {
    581    const uint32_t* population;
    582    int length;
    583    GetPopulationInfo(h, i, &population, &length);
    584    h->costs[i] = PopulationCost(population, length, &h->trivial_symbol[i],
    585                                 &h->is_used[i]);
    586  }
    587  h->bit_cost = h->costs[LITERAL] + h->costs[RED] + h->costs[BLUE] +
    588                h->costs[ALPHA] + h->costs[DISTANCE];
    589 }
    590 
    591 static int GetBinIdForEntropy(uint64_t min, uint64_t max, uint64_t val) {
    592  const uint64_t range = max - min;
    593  if (range > 0) {
    594    const uint64_t delta = val - min;
    595    return (int)((NUM_PARTITIONS - 1e-6) * delta / range);
    596  } else {
    597    return 0;
    598  }
    599 }
    600 
    601 static int GetHistoBinIndex(const VP8LHistogram* const h,
    602                            const DominantCostRange* const c, int low_effort) {
    603  int bin_id =
    604      GetBinIdForEntropy(c->literal_min, c->literal_max, h->costs[LITERAL]);
    605  assert(bin_id < NUM_PARTITIONS);
    606  if (!low_effort) {
    607    bin_id = bin_id * NUM_PARTITIONS +
    608             GetBinIdForEntropy(c->red_min, c->red_max, h->costs[RED]);
    609    bin_id = bin_id * NUM_PARTITIONS +
    610             GetBinIdForEntropy(c->blue_min, c->blue_max, h->costs[BLUE]);
    611    assert(bin_id < BIN_SIZE);
    612  }
    613  return bin_id;
    614 }
    615 
    616 // Construct the histograms from backward references.
    617 static void HistogramBuild(
    618    int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs,
    619    VP8LHistogramSet* const image_histo) {
    620  int x = 0, y = 0;
    621  const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits);
    622  VP8LHistogram** const histograms = image_histo->histograms;
    623  VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs);
    624  assert(histo_bits > 0);
    625  VP8LHistogramSetClear(image_histo);
    626  while (VP8LRefsCursorOk(&c)) {
    627    const PixOrCopy* const v = c.cur_pos;
    628    const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits);
    629    HistogramAddSinglePixOrCopy(histograms[ix], v, NULL, 0);
    630    x += PixOrCopyLength(v);
    631    while (x >= xsize) {
    632      x -= xsize;
    633      ++y;
    634    }
    635    VP8LRefsCursorNext(&c);
    636  }
    637 }
    638 
    639 // Copies the histograms and computes its bit_cost.
    640 static void HistogramCopyAndAnalyze(VP8LHistogramSet* const orig_histo,
    641                                    VP8LHistogramSet* const image_histo) {
    642  int i;
    643  VP8LHistogram** const orig_histograms = orig_histo->histograms;
    644  VP8LHistogram** const histograms = image_histo->histograms;
    645  assert(image_histo->max_size == orig_histo->max_size);
    646  image_histo->size = 0;
    647  for (i = 0; i < orig_histo->max_size; ++i) {
    648    VP8LHistogram* const histo = orig_histograms[i];
    649    ComputeHistogramCost(histo);
    650 
    651    // Skip the histogram if it is completely empty, which can happen for tiles
    652    // with no information (when they are skipped because of LZ77).
    653    if (!histo->is_used[LITERAL] && !histo->is_used[RED] &&
    654        !histo->is_used[BLUE] && !histo->is_used[ALPHA] &&
    655        !histo->is_used[DISTANCE]) {
    656      // The first histogram is always used.
    657      assert(i > 0);
    658      orig_histograms[i] = NULL;
    659    } else {
    660      // Copy histograms from orig_histo[] to image_histo[].
    661      HistogramCopy(histo, histograms[image_histo->size]);
    662      ++image_histo->size;
    663    }
    664  }
    665 }
    666 
    667 // Partition histograms to different entropy bins for three dominant (literal,
    668 // red and blue) symbol costs and compute the histogram aggregate bit_cost.
    669 static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
    670                                       int low_effort) {
    671  int i;
    672  VP8LHistogram** const histograms = image_histo->histograms;
    673  const int histo_size = image_histo->size;
    674  DominantCostRange cost_range;
    675  DominantCostRangeInit(&cost_range);
    676 
    677  // Analyze the dominant (literal, red and blue) entropy costs.
    678  for (i = 0; i < histo_size; ++i) {
    679    UpdateDominantCostRange(histograms[i], &cost_range);
    680  }
    681 
    682  // bin-hash histograms on three of the dominant (literal, red and blue)
    683  // symbol costs and store the resulting bin_id for each histogram.
    684  for (i = 0; i < histo_size; ++i) {
    685    histograms[i]->bin_id =
    686        GetHistoBinIndex(histograms[i], &cost_range, low_effort);
    687  }
    688 }
    689 
    690 // Merges some histograms with same bin_id together if it's advantageous.
    691 // Sets the remaining histograms to NULL.
    692 // 'combine_cost_factor' has to be divided by 100.
    693 static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
    694                                       VP8LHistogram* cur_combo, int num_bins,
    695                                       int32_t combine_cost_factor,
    696                                       int low_effort) {
    697  VP8LHistogram** const histograms = image_histo->histograms;
    698  int idx;
    699  struct {
    700    int16_t first;    // position of the histogram that accumulates all
    701                      // histograms with the same bin_id
    702    uint16_t num_combine_failures;   // number of combine failures per bin_id
    703  } bin_info[BIN_SIZE];
    704 
    705  assert(num_bins <= BIN_SIZE);
    706  for (idx = 0; idx < num_bins; ++idx) {
    707    bin_info[idx].first = -1;
    708    bin_info[idx].num_combine_failures = 0;
    709  }
    710 
    711  for (idx = 0; idx < image_histo->size;) {
    712    const int bin_id = histograms[idx]->bin_id;
    713    const int first = bin_info[bin_id].first;
    714    if (first == -1) {
    715      bin_info[bin_id].first = idx;
    716      ++idx;
    717    } else if (low_effort) {
    718      HistogramAdd(histograms[idx], histograms[first], histograms[first]);
    719      HistogramSetRemoveHistogram(image_histo, idx);
    720    } else {
    721      // try to merge #idx into #first (both share the same bin_id)
    722      const uint64_t bit_cost = histograms[idx]->bit_cost;
    723      const int64_t bit_cost_thresh =
    724          -DivRound((int64_t)bit_cost * combine_cost_factor, 100);
    725      if (HistogramAddEval(histograms[first], histograms[idx], cur_combo,
    726                           bit_cost_thresh)) {
    727        const int max_combine_failures = 32;
    728        // Try to merge two histograms only if the combo is a trivial one or
    729        // the two candidate histograms are already non-trivial.
    730        // For some images, 'try_combine' turns out to be false for a lot of
    731        // histogram pairs. In that case, we fallback to combining
    732        // histograms as usual to avoid increasing the header size.
    733        int try_combine =
    734            cur_combo->trivial_symbol[RED] != VP8L_NON_TRIVIAL_SYM &&
    735            cur_combo->trivial_symbol[BLUE] != VP8L_NON_TRIVIAL_SYM &&
    736            cur_combo->trivial_symbol[ALPHA] != VP8L_NON_TRIVIAL_SYM;
    737        if (!try_combine) {
    738          try_combine =
    739              histograms[idx]->trivial_symbol[RED] == VP8L_NON_TRIVIAL_SYM ||
    740              histograms[idx]->trivial_symbol[BLUE] == VP8L_NON_TRIVIAL_SYM ||
    741              histograms[idx]->trivial_symbol[ALPHA] == VP8L_NON_TRIVIAL_SYM;
    742          try_combine &=
    743              histograms[first]->trivial_symbol[RED] == VP8L_NON_TRIVIAL_SYM ||
    744              histograms[first]->trivial_symbol[BLUE] == VP8L_NON_TRIVIAL_SYM ||
    745              histograms[first]->trivial_symbol[ALPHA] == VP8L_NON_TRIVIAL_SYM;
    746        }
    747        if (try_combine ||
    748            bin_info[bin_id].num_combine_failures >= max_combine_failures) {
    749          // move the (better) merged histogram to its final slot
    750          HistogramSwap(&cur_combo, &histograms[first]);
    751          HistogramSetRemoveHistogram(image_histo, idx);
    752        } else {
    753          ++bin_info[bin_id].num_combine_failures;
    754          ++idx;
    755        }
    756      } else {
    757        ++idx;
    758      }
    759    }
    760  }
    761  if (low_effort) {
    762    // for low_effort case, update the final cost when everything is merged
    763    for (idx = 0; idx < image_histo->size; ++idx) {
    764      ComputeHistogramCost(histograms[idx]);
    765    }
    766  }
    767 }
    768 
    769 // Implement a Lehmer random number generator with a multiplicative constant of
    770 // 48271 and a modulo constant of 2^31 - 1.
    771 static uint32_t MyRand(uint32_t* const seed) {
    772  *seed = (uint32_t)(((uint64_t)(*seed) * 48271u) % 2147483647u);
    773  assert(*seed > 0);
    774  return *seed;
    775 }
    776 
    777 // -----------------------------------------------------------------------------
    778 // Histogram pairs priority queue
    779 
    780 // Pair of histograms. Negative idx1 value means that pair is out-of-date.
    781 typedef struct {
    782  int idx1;
    783  int idx2;
    784  int64_t cost_diff;
    785  uint64_t cost_combo;
    786  uint64_t costs[5];
    787 } HistogramPair;
    788 
    789 typedef struct {
    790  HistogramPair* queue;
    791  int size;
    792  int max_size;
    793 } HistoQueue;
    794 
    795 static int HistoQueueInit(HistoQueue* const histo_queue, const int max_size) {
    796  histo_queue->size = 0;
    797  histo_queue->max_size = max_size;
    798  // We allocate max_size + 1 because the last element at index "size" is
    799  // used as temporary data (and it could be up to max_size).
    800  histo_queue->queue = (HistogramPair*)WebPSafeMalloc(
    801      histo_queue->max_size + 1, sizeof(*histo_queue->queue));
    802  return histo_queue->queue != NULL;
    803 }
    804 
    805 static void HistoQueueClear(HistoQueue* const histo_queue) {
    806  assert(histo_queue != NULL);
    807  WebPSafeFree(histo_queue->queue);
    808  histo_queue->size = 0;
    809  histo_queue->max_size = 0;
    810 }
    811 
    812 // Pop a specific pair in the queue by replacing it with the last one
    813 // and shrinking the queue.
    814 static void HistoQueuePopPair(HistoQueue* const histo_queue,
    815                              HistogramPair* const pair) {
    816  assert(pair >= histo_queue->queue &&
    817         pair < (histo_queue->queue + histo_queue->size));
    818  assert(histo_queue->size > 0);
    819  *pair = histo_queue->queue[histo_queue->size - 1];
    820  --histo_queue->size;
    821 }
    822 
    823 // Check whether a pair in the queue should be updated as head or not.
    824 static void HistoQueueUpdateHead(HistoQueue* const histo_queue,
    825                                 HistogramPair* const pair) {
    826  assert(pair->cost_diff < 0);
    827  assert(pair >= histo_queue->queue &&
    828         pair < (histo_queue->queue + histo_queue->size));
    829  assert(histo_queue->size > 0);
    830  if (pair->cost_diff < histo_queue->queue[0].cost_diff) {
    831    // Replace the best pair.
    832    const HistogramPair tmp = histo_queue->queue[0];
    833    histo_queue->queue[0] = *pair;
    834    *pair = tmp;
    835  }
    836 }
    837 
    838 // Replaces the bad_id with good_id in the pair.
    839 static void HistoQueueFixPair(int bad_id, int good_id,
    840                              HistogramPair* const pair) {
    841  if (pair->idx1 == bad_id) pair->idx1 = good_id;
    842  if (pair->idx2 == bad_id) pair->idx2 = good_id;
    843  if (pair->idx1 > pair->idx2) {
    844    const int tmp = pair->idx1;
    845    pair->idx1 = pair->idx2;
    846    pair->idx2 = tmp;
    847  }
    848 }
    849 
    850 // Update the cost diff and combo of a pair of histograms. This needs to be
    851 // called when the histograms have been merged with a third one.
    852 // Returns 1 if the cost diff is less than the threshold.
    853 // Otherwise returns 0 and the cost is invalid due to early bail-out.
    854 WEBP_NODISCARD static int HistoQueueUpdatePair(const VP8LHistogram* const h1,
    855                                               const VP8LHistogram* const h2,
    856                                               int64_t cost_threshold,
    857                                               HistogramPair* const pair) {
    858  const int64_t sum_cost = h1->bit_cost + h2->bit_cost;
    859  SaturateAdd(sum_cost, &cost_threshold);
    860  if (!GetCombinedHistogramEntropy(h1, h2, cost_threshold, &pair->cost_combo,
    861                                   pair->costs)) {
    862    return 0;
    863  }
    864  pair->cost_diff = (int64_t)pair->cost_combo - sum_cost;
    865  return 1;
    866 }
    867 
    868 // Create a pair from indices "idx1" and "idx2" provided its cost
    869 // is inferior to "threshold", a negative entropy.
    870 // It returns the cost of the pair, or 0 if it superior to threshold.
    871 static int64_t HistoQueuePush(HistoQueue* const histo_queue,
    872                              VP8LHistogram** const histograms, int idx1,
    873                              int idx2, int64_t threshold) {
    874  const VP8LHistogram* h1;
    875  const VP8LHistogram* h2;
    876  HistogramPair pair;
    877 
    878  // Stop here if the queue is full.
    879  if (histo_queue->size == histo_queue->max_size) return 0;
    880  assert(threshold <= 0);
    881  if (idx1 > idx2) {
    882    const int tmp = idx2;
    883    idx2 = idx1;
    884    idx1 = tmp;
    885  }
    886  pair.idx1 = idx1;
    887  pair.idx2 = idx2;
    888  h1 = histograms[idx1];
    889  h2 = histograms[idx2];
    890 
    891  // Do not even consider the pair if it does not improve the entropy.
    892  if (!HistoQueueUpdatePair(h1, h2, threshold, &pair)) return 0;
    893 
    894  histo_queue->queue[histo_queue->size++] = pair;
    895  HistoQueueUpdateHead(histo_queue, &histo_queue->queue[histo_queue->size - 1]);
    896 
    897  return pair.cost_diff;
    898 }
    899 
    900 // -----------------------------------------------------------------------------
    901 
    902 // Combines histograms by continuously choosing the one with the highest cost
    903 // reduction.
    904 static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) {
    905  int ok = 0;
    906  const int image_histo_size = image_histo->size;
    907  int i, j;
    908  VP8LHistogram** const histograms = image_histo->histograms;
    909  // Priority queue of histogram pairs.
    910  HistoQueue histo_queue;
    911 
    912  // image_histo_size^2 for the queue size is safe. If you look at
    913  // HistogramCombineGreedy, and imagine that UpdateQueueFront always pushes
    914  // data to the queue, you insert at most:
    915  // - image_histo_size*(image_histo_size-1)/2 (the first two for loops)
    916  // - image_histo_size - 1 in the last for loop at the first iteration of
    917  //   the while loop, image_histo_size - 2 at the second iteration ...
    918  //   therefore image_histo_size*(image_histo_size-1)/2 overall too
    919  if (!HistoQueueInit(&histo_queue, image_histo_size * image_histo_size)) {
    920    goto End;
    921  }
    922 
    923  // Initialize the queue.
    924  for (i = 0; i < image_histo_size; ++i) {
    925    for (j = i + 1; j < image_histo_size; ++j) {
    926      HistoQueuePush(&histo_queue, histograms, i, j, 0);
    927    }
    928  }
    929 
    930  while (histo_queue.size > 0) {
    931    const int idx1 = histo_queue.queue[0].idx1;
    932    const int idx2 = histo_queue.queue[0].idx2;
    933    HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]);
    934    UpdateHistogramCost(histo_queue.queue[0].cost_combo,
    935                        histo_queue.queue[0].costs, histograms[idx1]);
    936 
    937    // Remove merged histogram.
    938    HistogramSetRemoveHistogram(image_histo, idx2);
    939 
    940    // Remove pairs intersecting the just combined best pair.
    941    for (i = 0; i < histo_queue.size;) {
    942      HistogramPair* const p = histo_queue.queue + i;
    943      if (p->idx1 == idx1 || p->idx2 == idx1 ||
    944          p->idx1 == idx2 || p->idx2 == idx2) {
    945        HistoQueuePopPair(&histo_queue, p);
    946      } else {
    947        HistoQueueFixPair(image_histo->size, idx2, p);
    948        HistoQueueUpdateHead(&histo_queue, p);
    949        ++i;
    950      }
    951    }
    952 
    953    // Push new pairs formed with combined histogram to the queue.
    954    for (i = 0; i < image_histo->size; ++i) {
    955      if (i == idx1) continue;
    956      HistoQueuePush(&histo_queue, image_histo->histograms, idx1, i, 0);
    957    }
    958  }
    959 
    960  ok = 1;
    961 
    962 End:
    963  HistoQueueClear(&histo_queue);
    964  return ok;
    965 }
    966 
    967 // Perform histogram aggregation using a stochastic approach.
    968 // 'do_greedy' is set to 1 if a greedy approach needs to be performed
    969 // afterwards, 0 otherwise.
    970 static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
    971                                      int min_cluster_size,
    972                                      int* const do_greedy) {
    973  int j, iter;
    974  uint32_t seed = 1;
    975  int tries_with_no_success = 0;
    976  const int outer_iters = image_histo->size;
    977  const int num_tries_no_success = outer_iters / 2;
    978  VP8LHistogram** const histograms = image_histo->histograms;
    979  // Priority queue of histogram pairs. Its size of 'kHistoQueueSize'
    980  // impacts the quality of the compression and the speed: the smaller the
    981  // faster but the worse for the compression.
    982  HistoQueue histo_queue;
    983  const int kHistoQueueSize = 9;
    984  int ok = 0;
    985 
    986  if (image_histo->size < min_cluster_size) {
    987    *do_greedy = 1;
    988    return 1;
    989  }
    990 
    991  if (!HistoQueueInit(&histo_queue, kHistoQueueSize)) goto End;
    992 
    993  // Collapse similar histograms in 'image_histo'.
    994  for (iter = 0; iter < outer_iters && image_histo->size >= min_cluster_size &&
    995                ++tries_with_no_success < num_tries_no_success;
    996      ++iter) {
    997    int64_t best_cost =
    998        (histo_queue.size == 0) ? 0 : histo_queue.queue[0].cost_diff;
    999    int best_idx1 = -1, best_idx2 = 1;
   1000    const uint32_t rand_range = (image_histo->size - 1) * (image_histo->size);
   1001    // (image_histo->size) / 2 was chosen empirically. Less means faster but
   1002    // worse compression.
   1003    const int num_tries = (image_histo->size) / 2;
   1004 
   1005    // Pick random samples.
   1006    for (j = 0; image_histo->size >= 2 && j < num_tries; ++j) {
   1007      int64_t curr_cost;
   1008      // Choose two different histograms at random and try to combine them.
   1009      const uint32_t tmp = MyRand(&seed) % rand_range;
   1010      uint32_t idx1 = tmp / (image_histo->size - 1);
   1011      uint32_t idx2 = tmp % (image_histo->size - 1);
   1012      if (idx2 >= idx1) ++idx2;
   1013 
   1014      // Calculate cost reduction on combination.
   1015      curr_cost =
   1016          HistoQueuePush(&histo_queue, histograms, idx1, idx2, best_cost);
   1017      if (curr_cost < 0) {  // found a better pair?
   1018        best_cost = curr_cost;
   1019        // Empty the queue if we reached full capacity.
   1020        if (histo_queue.size == histo_queue.max_size) break;
   1021      }
   1022    }
   1023    if (histo_queue.size == 0) continue;
   1024 
   1025    // Get the best histograms.
   1026    best_idx1 = histo_queue.queue[0].idx1;
   1027    best_idx2 = histo_queue.queue[0].idx2;
   1028    assert(best_idx1 < best_idx2);
   1029    // Merge the histograms and remove best_idx2 from the queue.
   1030    HistogramAdd(histograms[best_idx2], histograms[best_idx1],
   1031                 histograms[best_idx1]);
   1032    UpdateHistogramCost(histo_queue.queue[0].cost_combo,
   1033                        histo_queue.queue[0].costs, histograms[best_idx1]);
   1034    HistogramSetRemoveHistogram(image_histo, best_idx2);
   1035    // Parse the queue and update each pair that deals with best_idx1,
   1036    // best_idx2 or image_histo_size.
   1037    for (j = 0; j < histo_queue.size;) {
   1038      HistogramPair* const p = histo_queue.queue + j;
   1039      const int is_idx1_best = p->idx1 == best_idx1 || p->idx1 == best_idx2;
   1040      const int is_idx2_best = p->idx2 == best_idx1 || p->idx2 == best_idx2;
   1041      // The front pair could have been duplicated by a random pick so
   1042      // check for it all the time nevertheless.
   1043      if (is_idx1_best && is_idx2_best) {
   1044        HistoQueuePopPair(&histo_queue, p);
   1045        continue;
   1046      }
   1047      // Any pair containing one of the two best indices should only refer to
   1048      // best_idx1. Its cost should also be updated.
   1049      if (is_idx1_best || is_idx2_best) {
   1050        HistoQueueFixPair(best_idx2, best_idx1, p);
   1051        // Re-evaluate the cost of an updated pair.
   1052        if (!HistoQueueUpdatePair(histograms[p->idx1], histograms[p->idx2], 0,
   1053                                  p)) {
   1054          HistoQueuePopPair(&histo_queue, p);
   1055          continue;
   1056        }
   1057      }
   1058      HistoQueueFixPair(image_histo->size, best_idx2, p);
   1059      HistoQueueUpdateHead(&histo_queue, p);
   1060      ++j;
   1061    }
   1062    tries_with_no_success = 0;
   1063  }
   1064  *do_greedy = (image_histo->size <= min_cluster_size);
   1065  ok = 1;
   1066 
   1067 End:
   1068  HistoQueueClear(&histo_queue);
   1069  return ok;
   1070 }
   1071 
   1072 // -----------------------------------------------------------------------------
   1073 // Histogram refinement
   1074 
   1075 // Find the best 'out' histogram for each of the 'in' histograms.
   1076 // At call-time, 'out' contains the histograms of the clusters.
   1077 // Note: we assume that out[]->bit_cost is already up-to-date.
   1078 static void HistogramRemap(const VP8LHistogramSet* const in,
   1079                           VP8LHistogramSet* const out,
   1080                           uint32_t* const symbols) {
   1081  int i;
   1082  VP8LHistogram** const in_histo = in->histograms;
   1083  VP8LHistogram** const out_histo = out->histograms;
   1084  const int in_size = out->max_size;
   1085  const int out_size = out->size;
   1086  if (out_size > 1) {
   1087    for (i = 0; i < in_size; ++i) {
   1088      int best_out = 0;
   1089      int64_t best_bits = WEBP_INT64_MAX;
   1090      int k;
   1091      if (in_histo[i] == NULL) {
   1092        // Arbitrarily set to the previous value if unused to help future LZ77.
   1093        symbols[i] = symbols[i - 1];
   1094        continue;
   1095      }
   1096      for (k = 0; k < out_size; ++k) {
   1097        int64_t cur_bits;
   1098        if (HistogramAddThresh(out_histo[k], in_histo[i], best_bits,
   1099                               &cur_bits)) {
   1100          best_bits = cur_bits;
   1101          best_out = k;
   1102        }
   1103      }
   1104      symbols[i] = best_out;
   1105    }
   1106  } else {
   1107    assert(out_size == 1);
   1108    for (i = 0; i < in_size; ++i) {
   1109      symbols[i] = 0;
   1110    }
   1111  }
   1112 
   1113  // Recompute each out based on raw and symbols.
   1114  VP8LHistogramSetClear(out);
   1115  out->size = out_size;
   1116 
   1117  for (i = 0; i < in_size; ++i) {
   1118    int idx;
   1119    if (in_histo[i] == NULL) continue;
   1120    idx = symbols[i];
   1121    HistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]);
   1122  }
   1123 }
   1124 
   1125 static int32_t GetCombineCostFactor(int histo_size, int quality) {
   1126  int32_t combine_cost_factor = 16;
   1127  if (quality < 90) {
   1128    if (histo_size > 256) combine_cost_factor /= 2;
   1129    if (histo_size > 512) combine_cost_factor /= 2;
   1130    if (histo_size > 1024) combine_cost_factor /= 2;
   1131    if (quality <= 50) combine_cost_factor /= 2;
   1132  }
   1133  return combine_cost_factor;
   1134 }
   1135 
   1136 int VP8LGetHistoImageSymbols(int xsize, int ysize,
   1137                             const VP8LBackwardRefs* const refs, int quality,
   1138                             int low_effort, int histogram_bits, int cache_bits,
   1139                             VP8LHistogramSet* const image_histo,
   1140                             VP8LHistogram* const tmp_histo,
   1141                             uint32_t* const histogram_symbols,
   1142                             const WebPPicture* const pic, int percent_range,
   1143                             int* const percent) {
   1144  const int histo_xsize =
   1145      histogram_bits ? VP8LSubSampleSize(xsize, histogram_bits) : 1;
   1146  const int histo_ysize =
   1147      histogram_bits ? VP8LSubSampleSize(ysize, histogram_bits) : 1;
   1148  const int image_histo_raw_size = histo_xsize * histo_ysize;
   1149  VP8LHistogramSet* const orig_histo =
   1150      VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits);
   1151  // Don't attempt linear bin-partition heuristic for
   1152  // histograms of small sizes (as bin_map will be very sparse) and
   1153  // maximum quality q==100 (to preserve the compression gains at that level).
   1154  const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE;
   1155  int entropy_combine;
   1156  if (orig_histo == NULL) {
   1157    WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1158    goto Error;
   1159  }
   1160 
   1161  // Construct the histograms from backward references.
   1162  HistogramBuild(xsize, histogram_bits, refs, orig_histo);
   1163  HistogramCopyAndAnalyze(orig_histo, image_histo);
   1164  entropy_combine =
   1165      (image_histo->size > entropy_combine_num_bins * 2) && (quality < 100);
   1166 
   1167  if (entropy_combine) {
   1168    const int32_t combine_cost_factor =
   1169        GetCombineCostFactor(image_histo_raw_size, quality);
   1170 
   1171    HistogramAnalyzeEntropyBin(image_histo, low_effort);
   1172    // Collapse histograms with similar entropy.
   1173    HistogramCombineEntropyBin(image_histo, tmp_histo, entropy_combine_num_bins,
   1174                               combine_cost_factor, low_effort);
   1175  }
   1176 
   1177  // Don't combine the histograms using stochastic and greedy heuristics for
   1178  // low-effort compression mode.
   1179  if (!low_effort || !entropy_combine) {
   1180    // cubic ramp between 1 and MAX_HISTO_GREEDY:
   1181    const int threshold_size =
   1182        (int)(1 + DivRound(quality * quality * quality * (MAX_HISTO_GREEDY - 1),
   1183                           100 * 100 * 100));
   1184    int do_greedy;
   1185    if (!HistogramCombineStochastic(image_histo, threshold_size, &do_greedy)) {
   1186      WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1187      goto Error;
   1188    }
   1189    if (do_greedy) {
   1190      if (!HistogramCombineGreedy(image_histo)) {
   1191        WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1192        goto Error;
   1193      }
   1194    }
   1195  }
   1196 
   1197  // Find the optimal map from original histograms to the final ones.
   1198  HistogramRemap(orig_histo, image_histo, histogram_symbols);
   1199 
   1200  if (!WebPReportProgress(pic, *percent + percent_range, percent)) {
   1201    goto Error;
   1202  }
   1203 
   1204 Error:
   1205  VP8LFreeHistogramSet(orig_histo);
   1206  return (pic->error_code == VP8_ENC_OK);
   1207 }