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 }