| OLD | NEW |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Use of this source code is governed by a BSD-style license | 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 | 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 | 5 // tree. An additional intellectual property rights grant can be found |
| 6 // in the file PATENTS. All contributing project authors may | 6 // in the file PATENTS. All contributing project authors may |
| 7 // be found in the AUTHORS file in the root of the source tree. | 7 // be found in the AUTHORS file in the root of the source tree. |
| 8 // ----------------------------------------------------------------------------- | 8 // ----------------------------------------------------------------------------- |
| 9 // | 9 // |
| 10 // Author: Jyrki Alakuijala (jyrki@google.com) | 10 // Author: Jyrki Alakuijala (jyrki@google.com) |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 alpha_cost + distance_cost; | 379 alpha_cost + distance_cost; |
| 380 if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { | 380 if ((alpha_sym | red_sym | blue_sym) == VP8L_NON_TRIVIAL_SYM) { |
| 381 h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; | 381 h->trivial_symbol_ = VP8L_NON_TRIVIAL_SYM; |
| 382 } else { | 382 } else { |
| 383 h->trivial_symbol_ = | 383 h->trivial_symbol_ = |
| 384 ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); | 384 ((uint32_t)alpha_sym << 24) | (red_sym << 16) | (blue_sym << 0); |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 | 387 |
| 388 static int GetBinIdForEntropy(double min, double max, double val) { | 388 static int GetBinIdForEntropy(double min, double max, double val) { |
| 389 const double range = max - min + 1e-6; | 389 const double range = max - min; |
| 390 const double delta = val - min; | 390 if (range > 0.) { |
| 391 return (int)(NUM_PARTITIONS * delta / range); | 391 const double delta = val - min; |
| 392 return (int)((NUM_PARTITIONS - 1e-6) * delta / range); |
| 393 } else { |
| 394 return 0; |
| 395 } |
| 392 } | 396 } |
| 393 | 397 |
| 394 static int GetHistoBinIndexLowEffort( | 398 static int GetHistoBinIndex(const VP8LHistogram* const h, |
| 395 const VP8LHistogram* const h, const DominantCostRange* const c) { | 399 const DominantCostRange* const c, int low_effort) { |
| 396 const int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, | 400 int bin_id = GetBinIdForEntropy(c->literal_min_, c->literal_max_, |
| 397 h->literal_cost_); | 401 h->literal_cost_); |
| 398 assert(bin_id < NUM_PARTITIONS); | 402 assert(bin_id < NUM_PARTITIONS); |
| 403 if (!low_effort) { |
| 404 bin_id = bin_id * NUM_PARTITIONS |
| 405 + GetBinIdForEntropy(c->red_min_, c->red_max_, h->red_cost_); |
| 406 bin_id = bin_id * NUM_PARTITIONS |
| 407 + GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_); |
| 408 assert(bin_id < BIN_SIZE); |
| 409 } |
| 399 return bin_id; | 410 return bin_id; |
| 400 } | 411 } |
| 401 | 412 |
| 402 static int GetHistoBinIndex( | |
| 403 const VP8LHistogram* const h, const DominantCostRange* const c) { | |
| 404 const int bin_id = | |
| 405 GetBinIdForEntropy(c->blue_min_, c->blue_max_, h->blue_cost_) + | |
| 406 NUM_PARTITIONS * GetBinIdForEntropy(c->red_min_, c->red_max_, | |
| 407 h->red_cost_) + | |
| 408 NUM_PARTITIONS * NUM_PARTITIONS * GetBinIdForEntropy(c->literal_min_, | |
| 409 c->literal_max_, | |
| 410 h->literal_cost_); | |
| 411 assert(bin_id < BIN_SIZE); | |
| 412 return bin_id; | |
| 413 } | |
| 414 | |
| 415 // Construct the histograms from backward references. | 413 // Construct the histograms from backward references. |
| 416 static void HistogramBuild( | 414 static void HistogramBuild( |
| 417 int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, | 415 int xsize, int histo_bits, const VP8LBackwardRefs* const backward_refs, |
| 418 VP8LHistogramSet* const image_histo) { | 416 VP8LHistogramSet* const image_histo) { |
| 419 int x = 0, y = 0; | 417 int x = 0, y = 0; |
| 420 const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); | 418 const int histo_xsize = VP8LSubSampleSize(xsize, histo_bits); |
| 421 VP8LHistogram** const histograms = image_histo->histograms; | 419 VP8LHistogram** const histograms = image_histo->histograms; |
| 422 VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); | 420 VP8LRefsCursor c = VP8LRefsCursorInit(backward_refs); |
| 423 assert(histo_bits > 0); | 421 assert(histo_bits > 0); |
| 424 while (VP8LRefsCursorOk(&c)) { | 422 while (VP8LRefsCursorOk(&c)) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 | 460 |
| 463 // Analyze the dominant (literal, red and blue) entropy costs. | 461 // Analyze the dominant (literal, red and blue) entropy costs. |
| 464 for (i = 0; i < histo_size; ++i) { | 462 for (i = 0; i < histo_size; ++i) { |
| 465 VP8LHistogram* const histo = histograms[i]; | 463 VP8LHistogram* const histo = histograms[i]; |
| 466 UpdateDominantCostRange(histo, &cost_range); | 464 UpdateDominantCostRange(histo, &cost_range); |
| 467 } | 465 } |
| 468 | 466 |
| 469 // bin-hash histograms on three of the dominant (literal, red and blue) | 467 // bin-hash histograms on three of the dominant (literal, red and blue) |
| 470 // symbol costs. | 468 // symbol costs. |
| 471 for (i = 0; i < histo_size; ++i) { | 469 for (i = 0; i < histo_size; ++i) { |
| 472 int num_histos; | 470 const VP8LHistogram* const histo = histograms[i]; |
| 473 VP8LHistogram* const histo = histograms[i]; | 471 const int bin_id = GetHistoBinIndex(histo, &cost_range, low_effort); |
| 474 const int16_t bin_id = low_effort ? | |
| 475 (int16_t)GetHistoBinIndexLowEffort(histo, &cost_range) : | |
| 476 (int16_t)GetHistoBinIndex(histo, &cost_range); | |
| 477 const int bin_offset = bin_id * bin_depth; | 472 const int bin_offset = bin_id * bin_depth; |
| 478 // bin_map[n][0] for every bin 'n' maintains the counter for the number of | 473 // bin_map[n][0] for every bin 'n' maintains the counter for the number of |
| 479 // histograms in that bin. | 474 // histograms in that bin. |
| 480 // Get and increment the num_histos in that bin. | 475 // Get and increment the num_histos in that bin. |
| 481 num_histos = ++bin_map[bin_offset]; | 476 const int num_histos = ++bin_map[bin_offset]; |
| 482 assert(bin_offset + num_histos < bin_depth * BIN_SIZE); | 477 assert(bin_offset + num_histos < bin_depth * BIN_SIZE); |
| 483 // Add histogram i'th index at num_histos (last) position in the bin_map. | 478 // Add histogram i'th index at num_histos (last) position in the bin_map. |
| 484 bin_map[bin_offset + num_histos] = i; | 479 bin_map[bin_offset + num_histos] = i; |
| 485 } | 480 } |
| 486 } | 481 } |
| 487 | 482 |
| 488 // Compact the histogram set by removing unused entries. | 483 // Compact the histogram set by removing unused entries. |
| 489 static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { | 484 static void HistogramCompactBins(VP8LHistogramSet* const image_histo) { |
| 490 VP8LHistogram** const histograms = image_histo->histograms; | 485 VP8LHistogram** const histograms = image_histo->histograms; |
| 491 int i, j; | 486 int i, j; |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 | 624 |
| 630 // We cannot add more elements than the capacity. | 625 // We cannot add more elements than the capacity. |
| 631 // The allocation adds an extra element to the official capacity so that | 626 // The allocation adds an extra element to the official capacity so that |
| 632 // histo_queue->queue[histo_queue->max_size] is read/written within bound. | 627 // histo_queue->queue[histo_queue->max_size] is read/written within bound. |
| 633 assert(histo_queue->size <= histo_queue->max_size); | 628 assert(histo_queue->size <= histo_queue->max_size); |
| 634 } | 629 } |
| 635 | 630 |
| 636 // ----------------------------------------------------------------------------- | 631 // ----------------------------------------------------------------------------- |
| 637 | 632 |
| 638 static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, | 633 static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, |
| 639 HistogramPair* const pair, | 634 HistogramPair* const pair) { |
| 640 VP8LHistogram* const histos) { | 635 VP8LHistogram* h1; |
| 636 VP8LHistogram* h2; |
| 637 double sum_cost; |
| 638 |
| 641 if (idx1 > idx2) { | 639 if (idx1 > idx2) { |
| 642 const int tmp = idx2; | 640 const int tmp = idx2; |
| 643 idx2 = idx1; | 641 idx2 = idx1; |
| 644 idx1 = tmp; | 642 idx1 = tmp; |
| 645 } | 643 } |
| 646 pair->idx1 = idx1; | 644 pair->idx1 = idx1; |
| 647 pair->idx2 = idx2; | 645 pair->idx2 = idx2; |
| 648 pair->cost_diff = | 646 h1 = histograms[idx1]; |
| 649 HistogramAddEval(histograms[idx1], histograms[idx2], histos, 0); | 647 h2 = histograms[idx2]; |
| 650 pair->cost_combo = histos->bit_cost_; | 648 sum_cost = h1->bit_cost_ + h2->bit_cost_; |
| 649 pair->cost_combo = 0.; |
| 650 GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo); |
| 651 pair->cost_diff = pair->cost_combo - sum_cost; |
| 651 } | 652 } |
| 652 | 653 |
| 653 // Combines histograms by continuously choosing the one with the highest cost | 654 // Combines histograms by continuously choosing the one with the highest cost |
| 654 // reduction. | 655 // reduction. |
| 655 static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo, | 656 static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { |
| 656 VP8LHistogram* const histos) { | |
| 657 int ok = 0; | 657 int ok = 0; |
| 658 int image_histo_size = image_histo->size; | 658 int image_histo_size = image_histo->size; |
| 659 int i, j; | 659 int i, j; |
| 660 VP8LHistogram** const histograms = image_histo->histograms; | 660 VP8LHistogram** const histograms = image_histo->histograms; |
| 661 // Indexes of remaining histograms. | 661 // Indexes of remaining histograms. |
| 662 int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters)); | 662 int* const clusters = WebPSafeMalloc(image_histo_size, sizeof(*clusters)); |
| 663 // Priority queue of histogram pairs. | 663 // Priority queue of histogram pairs. |
| 664 HistoQueue histo_queue; | 664 HistoQueue histo_queue; |
| 665 | 665 |
| 666 if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) { | 666 if (!HistoQueueInit(&histo_queue, image_histo_size) || clusters == NULL) { |
| 667 goto End; | 667 goto End; |
| 668 } | 668 } |
| 669 | 669 |
| 670 for (i = 0; i < image_histo_size; ++i) { | 670 for (i = 0; i < image_histo_size; ++i) { |
| 671 // Initialize clusters indexes. | 671 // Initialize clusters indexes. |
| 672 clusters[i] = i; | 672 clusters[i] = i; |
| 673 for (j = i + 1; j < image_histo_size; ++j) { | 673 for (j = i + 1; j < image_histo_size; ++j) { |
| 674 // Initialize positions array. | 674 // Initialize positions array. |
| 675 PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size], | 675 PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]); |
| 676 histos); | |
| 677 UpdateQueueFront(&histo_queue); | 676 UpdateQueueFront(&histo_queue); |
| 678 } | 677 } |
| 679 } | 678 } |
| 680 | 679 |
| 681 while (image_histo_size > 1 && histo_queue.size > 0) { | 680 while (image_histo_size > 1 && histo_queue.size > 0) { |
| 682 HistogramPair* copy_to; | 681 HistogramPair* copy_to; |
| 683 const int idx1 = histo_queue.queue[0].idx1; | 682 const int idx1 = histo_queue.queue[0].idx1; |
| 684 const int idx2 = histo_queue.queue[0].idx2; | 683 const int idx2 = histo_queue.queue[0].idx2; |
| 685 VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); | 684 VP8LHistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); |
| 686 histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; | 685 histograms[idx1]->bit_cost_ = histo_queue.queue[0].cost_combo; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 708 } | 707 } |
| 709 SwapHistogramPairs(copy_to, p); | 708 SwapHistogramPairs(copy_to, p); |
| 710 ++copy_to; | 709 ++copy_to; |
| 711 } | 710 } |
| 712 histo_queue.size = (int)(copy_to - histo_queue.queue); | 711 histo_queue.size = (int)(copy_to - histo_queue.queue); |
| 713 | 712 |
| 714 // Push new pairs formed with combined histogram to the queue. | 713 // Push new pairs formed with combined histogram to the queue. |
| 715 for (i = 0; i < image_histo_size; ++i) { | 714 for (i = 0; i < image_histo_size; ++i) { |
| 716 if (clusters[i] != idx1) { | 715 if (clusters[i] != idx1) { |
| 717 PreparePair(histograms, idx1, clusters[i], | 716 PreparePair(histograms, idx1, clusters[i], |
| 718 &histo_queue.queue[histo_queue.size], histos); | 717 &histo_queue.queue[histo_queue.size]); |
| 719 UpdateQueueFront(&histo_queue); | 718 UpdateQueueFront(&histo_queue); |
| 720 } | 719 } |
| 721 } | 720 } |
| 722 } | 721 } |
| 723 // Move remaining histograms to the beginning of the array. | 722 // Move remaining histograms to the beginning of the array. |
| 724 for (i = 0; i < image_histo_size; ++i) { | 723 for (i = 0; i < image_histo_size; ++i) { |
| 725 if (i != clusters[i]) { // swap the two histograms | 724 if (i != clusters[i]) { // swap the two histograms |
| 726 HistogramSwap(&histograms[i], &histograms[clusters[i]]); | 725 HistogramSwap(&histograms[i], &histograms[clusters[i]]); |
| 727 } | 726 } |
| 728 } | 727 } |
| 729 | 728 |
| 730 image_histo->size = image_histo_size; | 729 image_histo->size = image_histo_size; |
| 731 ok = 1; | 730 ok = 1; |
| 732 | 731 |
| 733 End: | 732 End: |
| 734 WebPSafeFree(clusters); | 733 WebPSafeFree(clusters); |
| 735 HistoQueueClear(&histo_queue); | 734 HistoQueueClear(&histo_queue); |
| 736 return ok; | 735 return ok; |
| 737 } | 736 } |
| 738 | 737 |
| 739 static VP8LHistogram* HistogramCombineStochastic( | 738 static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo, |
| 740 VP8LHistogramSet* const image_histo, | 739 VP8LHistogram* tmp_histo, |
| 741 VP8LHistogram* tmp_histo, | 740 VP8LHistogram* best_combo, |
| 742 VP8LHistogram* best_combo, | 741 int quality, int min_cluster_size) { |
| 743 int quality, int min_cluster_size) { | |
| 744 int iter; | 742 int iter; |
| 745 uint32_t seed = 0; | 743 uint32_t seed = 0; |
| 746 int tries_with_no_success = 0; | 744 int tries_with_no_success = 0; |
| 747 int image_histo_size = image_histo->size; | 745 int image_histo_size = image_histo->size; |
| 748 const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; | 746 const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; |
| 749 const int outer_iters = image_histo_size * iter_mult; | 747 const int outer_iters = image_histo_size * iter_mult; |
| 750 const int num_pairs = image_histo_size / 2; | 748 const int num_pairs = image_histo_size / 2; |
| 751 const int num_tries_no_success = outer_iters / 2; | 749 const int num_tries_no_success = outer_iters / 2; |
| 752 VP8LHistogram** const histograms = image_histo->histograms; | 750 VP8LHistogram** const histograms = image_histo->histograms; |
| 753 | 751 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); | 791 HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); |
| 794 histograms[image_histo_size] = NULL; | 792 histograms[image_histo_size] = NULL; |
| 795 } | 793 } |
| 796 tries_with_no_success = 0; | 794 tries_with_no_success = 0; |
| 797 } | 795 } |
| 798 if (++tries_with_no_success >= num_tries_no_success) { | 796 if (++tries_with_no_success >= num_tries_no_success) { |
| 799 break; | 797 break; |
| 800 } | 798 } |
| 801 } | 799 } |
| 802 image_histo->size = image_histo_size; | 800 image_histo->size = image_histo_size; |
| 803 return best_combo; | |
| 804 } | 801 } |
| 805 | 802 |
| 806 // ----------------------------------------------------------------------------- | 803 // ----------------------------------------------------------------------------- |
| 807 // Histogram refinement | 804 // Histogram refinement |
| 808 | 805 |
| 809 // Find the best 'out' histogram for each of the 'in' histograms. | 806 // Find the best 'out' histogram for each of the 'in' histograms. |
| 810 // Note: we assume that out[]->bit_cost_ is already up-to-date. | 807 // Note: we assume that out[]->bit_cost_ is already up-to-date. |
| 811 static void HistogramRemap(const VP8LHistogramSet* const orig_histo, | 808 static void HistogramRemap(const VP8LHistogramSet* const in, |
| 812 const VP8LHistogramSet* const image_histo, | 809 const VP8LHistogramSet* const out, |
| 813 uint16_t* const symbols) { | 810 uint16_t* const symbols) { |
| 814 int i; | 811 int i; |
| 815 VP8LHistogram** const orig_histograms = orig_histo->histograms; | 812 VP8LHistogram** const in_histo = in->histograms; |
| 816 VP8LHistogram** const histograms = image_histo->histograms; | 813 VP8LHistogram** const out_histo = out->histograms; |
| 817 const int orig_histo_size = orig_histo->size; | 814 const int in_size = in->size; |
| 818 const int image_histo_size = image_histo->size; | 815 const int out_size = out->size; |
| 819 if (image_histo_size > 1) { | 816 if (out_size > 1) { |
| 820 for (i = 0; i < orig_histo_size; ++i) { | 817 for (i = 0; i < in_size; ++i) { |
| 821 int best_out = 0; | 818 int best_out = 0; |
| 822 double best_bits = | 819 double best_bits = MAX_COST; |
| 823 HistogramAddThresh(histograms[0], orig_histograms[i], MAX_COST); | |
| 824 int k; | 820 int k; |
| 825 for (k = 1; k < image_histo_size; ++k) { | 821 for (k = 0; k < out_size; ++k) { |
| 826 const double cur_bits = | 822 const double cur_bits = |
| 827 HistogramAddThresh(histograms[k], orig_histograms[i], best_bits); | 823 HistogramAddThresh(out_histo[k], in_histo[i], best_bits); |
| 828 if (cur_bits < best_bits) { | 824 if (k == 0 || cur_bits < best_bits) { |
| 829 best_bits = cur_bits; | 825 best_bits = cur_bits; |
| 830 best_out = k; | 826 best_out = k; |
| 831 } | 827 } |
| 832 } | 828 } |
| 833 symbols[i] = best_out; | 829 symbols[i] = best_out; |
| 834 } | 830 } |
| 835 } else { | 831 } else { |
| 836 assert(image_histo_size == 1); | 832 assert(out_size == 1); |
| 837 for (i = 0; i < orig_histo_size; ++i) { | 833 for (i = 0; i < in_size; ++i) { |
| 838 symbols[i] = 0; | 834 symbols[i] = 0; |
| 839 } | 835 } |
| 840 } | 836 } |
| 841 | 837 |
| 842 // Recompute each out based on raw and symbols. | 838 // Recompute each out based on raw and symbols. |
| 843 for (i = 0; i < image_histo_size; ++i) { | 839 for (i = 0; i < out_size; ++i) { |
| 844 HistogramClear(histograms[i]); | 840 HistogramClear(out_histo[i]); |
| 845 } | 841 } |
| 846 | 842 |
| 847 for (i = 0; i < orig_histo_size; ++i) { | 843 for (i = 0; i < in_size; ++i) { |
| 848 const int idx = symbols[i]; | 844 const int idx = symbols[i]; |
| 849 VP8LHistogramAdd(orig_histograms[i], histograms[idx], histograms[idx]); | 845 VP8LHistogramAdd(in_histo[i], out_histo[idx], out_histo[idx]); |
| 850 } | 846 } |
| 851 } | 847 } |
| 852 | 848 |
| 853 static double GetCombineCostFactor(int histo_size, int quality) { | 849 static double GetCombineCostFactor(int histo_size, int quality) { |
| 854 double combine_cost_factor = 0.16; | 850 double combine_cost_factor = 0.16; |
| 855 if (quality < 90) { | 851 if (quality < 90) { |
| 856 if (histo_size > 256) combine_cost_factor /= 2.; | 852 if (histo_size > 256) combine_cost_factor /= 2.; |
| 857 if (histo_size > 512) combine_cost_factor /= 2.; | 853 if (histo_size > 512) combine_cost_factor /= 2.; |
| 858 if (histo_size > 1024) combine_cost_factor /= 2.; | 854 if (histo_size > 1024) combine_cost_factor /= 2.; |
| 859 if (quality <= 50) combine_cost_factor /= 2.; | 855 if (quality <= 50) combine_cost_factor /= 2.; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 bin_depth, entropy_combine_num_bins, | 909 bin_depth, entropy_combine_num_bins, |
| 914 combine_cost_factor, low_effort); | 910 combine_cost_factor, low_effort); |
| 915 } | 911 } |
| 916 | 912 |
| 917 // Don't combine the histograms using stochastic and greedy heuristics for | 913 // Don't combine the histograms using stochastic and greedy heuristics for |
| 918 // low-effort compression mode. | 914 // low-effort compression mode. |
| 919 if (!low_effort || !entropy_combine) { | 915 if (!low_effort || !entropy_combine) { |
| 920 const float x = quality / 100.f; | 916 const float x = quality / 100.f; |
| 921 // cubic ramp between 1 and MAX_HISTO_GREEDY: | 917 // cubic ramp between 1 and MAX_HISTO_GREEDY: |
| 922 const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); | 918 const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); |
| 923 cur_combo = HistogramCombineStochastic(image_histo, | 919 HistogramCombineStochastic(image_histo, tmp_histos->histograms[0], |
| 924 tmp_histos->histograms[0], | 920 cur_combo, quality, threshold_size); |
| 925 cur_combo, quality, threshold_size); | |
| 926 if ((image_histo->size <= threshold_size) && | 921 if ((image_histo->size <= threshold_size) && |
| 927 !HistogramCombineGreedy(image_histo, cur_combo)) { | 922 !HistogramCombineGreedy(image_histo)) { |
| 928 goto Error; | 923 goto Error; |
| 929 } | 924 } |
| 930 } | 925 } |
| 931 | 926 |
| 932 // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also. | 927 // TODO(vikasa): Optimize HistogramRemap for low-effort compression mode also. |
| 933 // Find the optimal map from original histograms to the final ones. | 928 // Find the optimal map from original histograms to the final ones. |
| 934 HistogramRemap(orig_histo, image_histo, histogram_symbols); | 929 HistogramRemap(orig_histo, image_histo, histogram_symbols); |
| 935 | 930 |
| 936 ok = 1; | 931 ok = 1; |
| 937 | 932 |
| 938 Error: | 933 Error: |
| 939 WebPSafeFree(bin_map); | 934 WebPSafeFree(bin_map); |
| 940 VP8LFreeHistogramSet(orig_histo); | 935 VP8LFreeHistogramSet(orig_histo); |
| 941 return ok; | 936 return ok; |
| 942 } | 937 } |
| OLD | NEW |