go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

vp8l_enc.c (71847B)


      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 // main entry for the lossless encoder.
     11 //
     12 // Author: Vikas Arora (vikaas.arora@gmail.com)
     13 //
     14 
     15 #include <assert.h>
     16 #include <stdlib.h>
     17 #include <string.h>
     18 
     19 #include "src/dsp/lossless.h"
     20 #include "src/dsp/lossless_common.h"
     21 #include "src/enc/backward_references_enc.h"
     22 #include "src/enc/histogram_enc.h"
     23 #include "src/enc/vp8i_enc.h"
     24 #include "src/enc/vp8li_enc.h"
     25 #include "src/utils/bit_writer_utils.h"
     26 #include "src/utils/huffman_encode_utils.h"
     27 #include "src/utils/palette.h"
     28 #include "src/utils/thread_utils.h"
     29 #include "src/utils/utils.h"
     30 #include "src/webp/encode.h"
     31 #include "src/webp/format_constants.h"
     32 #include "src/webp/types.h"
     33 
     34 // Maximum number of histogram images (sub-blocks).
     35 #define MAX_HUFF_IMAGE_SIZE       2600
     36 #define MAX_HUFFMAN_BITS (MIN_HUFFMAN_BITS + (1 << NUM_HUFFMAN_BITS) - 1)
     37 // Empirical value for which it becomes too computationally expensive to
     38 // compute the best predictor image.
     39 #define MAX_PREDICTOR_IMAGE_SIZE (1 << 14)
     40 
     41 // -----------------------------------------------------------------------------
     42 // Palette
     43 
     44 // These five modes are evaluated and their respective entropy is computed.
     45 typedef enum {
     46   kDirect = 0,
     47   kSpatial = 1,
     48   kSubGreen = 2,
     49   kSpatialSubGreen = 3,
     50   kPalette = 4,
     51   kPaletteAndSpatial = 5,
     52   kNumEntropyIx = 6
     53 } EntropyIx;
     54 
     55 typedef enum {
     56   kHistoAlpha = 0,
     57   kHistoAlphaPred,
     58   kHistoGreen,
     59   kHistoGreenPred,
     60   kHistoRed,
     61   kHistoRedPred,
     62   kHistoBlue,
     63   kHistoBluePred,
     64   kHistoRedSubGreen,
     65   kHistoRedPredSubGreen,
     66   kHistoBlueSubGreen,
     67   kHistoBluePredSubGreen,
     68   kHistoPalette,
     69   kHistoTotal  // Must be last.
     70 } HistoIx;
     71 
     72 
     73 #define NUM_BUCKETS 256
     74 
     75 typedef uint32_t HistogramBuckets[NUM_BUCKETS];
     76 
     77 // Keeping track of histograms, indexed by HistoIx.
     78 // Ideally, this would just be a struct with meaningful fields, but the
     79 // calculation of `entropy_comp` uses the index. One refactoring at a time :)
     80 typedef struct {
     81   HistogramBuckets category[kHistoTotal];
     82 } Histograms;
     83 
     84 static void AddSingleSubGreen(uint32_t p,
     85                               HistogramBuckets r, HistogramBuckets b) {
     86   const int green = (int)p >> 8;  // The upper bits are masked away later.
     87   ++r[(((int)p >> 16) - green) & 0xff];
     88   ++b[(((int)p >>  0) - green) & 0xff];
     89 }
     90 
     91 static void AddSingle(uint32_t p,
     92                       HistogramBuckets a, HistogramBuckets r,
     93                       HistogramBuckets g, HistogramBuckets b) {
     94   ++a[(p >> 24) & 0xff];
     95   ++r[(p >> 16) & 0xff];
     96   ++g[(p >>  8) & 0xff];
     97   ++b[(p >>  0) & 0xff];
     98 }
     99 
    100 static WEBP_INLINE uint8_t HashPix(uint32_t pix) {
    101   // Note that masking with 0xffffffffu is for preventing an
    102   // 'unsigned int overflow' warning. Doesn't impact the compiled code.
    103   return ((((uint64_t)pix + (pix >> 19)) * 0x39c5fba7ull) & 0xffffffffu) >> 24;
    104 }
    105 
    106 static int AnalyzeEntropy(const uint32_t* argb,
    107                           int width, int height, int argb_stride,
    108                           int use_palette,
    109                           int palette_size, int transform_bits,
    110                           EntropyIx* const min_entropy_ix,
    111                           int* const red_and_blue_always_zero) {
    112   Histograms* histo;
    113 
    114   if (use_palette && palette_size <= 16) {
    115     // In the case of small palettes, we pack 2, 4 or 8 pixels together. In
    116     // practice, small palettes are better than any other transform.
    117     *min_entropy_ix = kPalette;
    118     *red_and_blue_always_zero = 1;
    119     return 1;
    120   }
    121 
    122   histo = (Histograms*)WebPSafeCalloc(1, sizeof(*histo));
    123   if (histo != NULL) {
    124     int i, x, y;
    125     const uint32_t* prev_row = NULL;
    126     const uint32_t* curr_row = argb;
    127     uint32_t pix_prev = argb[0];  // Skip the first pixel.
    128     for (y = 0; y < height; ++y) {
    129       for (x = 0; x < width; ++x) {
    130         const uint32_t pix = curr_row[x];
    131         const uint32_t pix_diff = VP8LSubPixels(pix, pix_prev);
    132         pix_prev = pix;
    133         if ((pix_diff == 0) || (prev_row != NULL && pix == prev_row[x])) {
    134           continue;
    135         }
    136         AddSingle(pix,
    137                   histo->category[kHistoAlpha],
    138                   histo->category[kHistoRed],
    139                   histo->category[kHistoGreen],
    140                   histo->category[kHistoBlue]);
    141         AddSingle(pix_diff,
    142                   histo->category[kHistoAlphaPred],
    143                   histo->category[kHistoRedPred],
    144                   histo->category[kHistoGreenPred],
    145                   histo->category[kHistoBluePred]);
    146         AddSingleSubGreen(pix,
    147                           histo->category[kHistoRedSubGreen],
    148                           histo->category[kHistoBlueSubGreen]);
    149         AddSingleSubGreen(pix_diff,
    150                           histo->category[kHistoRedPredSubGreen],
    151                           histo->category[kHistoBluePredSubGreen]);
    152         {
    153           // Approximate the palette by the entropy of the multiplicative hash.
    154           const uint8_t hash = HashPix(pix);
    155           ++histo->category[kHistoPalette][hash];
    156         }
    157       }
    158       prev_row = curr_row;
    159       curr_row += argb_stride;
    160     }
    161     {
    162       uint64_t entropy_comp[kHistoTotal];
    163       uint64_t entropy[kNumEntropyIx];
    164       int k;
    165       int last_mode_to_analyze = use_palette ? kPalette : kSpatialSubGreen;
    166       int j;
    167       // Let's add one zero to the predicted histograms. The zeros are removed
    168       // too efficiently by the pix_diff == 0 comparison, at least one of the
    169       // zeros is likely to exist.
    170       ++histo->category[kHistoRedPredSubGreen][0];
    171       ++histo->category[kHistoBluePredSubGreen][0];
    172       ++histo->category[kHistoRedPred][0];
    173       ++histo->category[kHistoGreenPred][0];
    174       ++histo->category[kHistoBluePred][0];
    175       ++histo->category[kHistoAlphaPred][0];
    176 
    177       for (j = 0; j < kHistoTotal; ++j) {
    178         entropy_comp[j] = VP8LBitsEntropy(histo->category[j], NUM_BUCKETS);
    179       }
    180       entropy[kDirect] = entropy_comp[kHistoAlpha] +
    181           entropy_comp[kHistoRed] +
    182           entropy_comp[kHistoGreen] +
    183           entropy_comp[kHistoBlue];
    184       entropy[kSpatial] = entropy_comp[kHistoAlphaPred] +
    185           entropy_comp[kHistoRedPred] +
    186           entropy_comp[kHistoGreenPred] +
    187           entropy_comp[kHistoBluePred];
    188       entropy[kSubGreen] = entropy_comp[kHistoAlpha] +
    189           entropy_comp[kHistoRedSubGreen] +
    190           entropy_comp[kHistoGreen] +
    191           entropy_comp[kHistoBlueSubGreen];
    192       entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] +
    193           entropy_comp[kHistoRedPredSubGreen] +
    194           entropy_comp[kHistoGreenPred] +
    195           entropy_comp[kHistoBluePredSubGreen];
    196       entropy[kPalette] = entropy_comp[kHistoPalette];
    197 
    198       // When including transforms, there is an overhead in bits from
    199       // storing them. This overhead is small but matters for small images.
    200       // For spatial, there are 14 transformations.
    201       entropy[kSpatial] += (uint64_t)VP8LSubSampleSize(width, transform_bits) *
    202                            VP8LSubSampleSize(height, transform_bits) *
    203                            VP8LFastLog2(14);
    204       // For color transforms: 24 as only 3 channels are considered in a
    205       // ColorTransformElement.
    206       entropy[kSpatialSubGreen] +=
    207           (uint64_t)VP8LSubSampleSize(width, transform_bits) *
    208           VP8LSubSampleSize(height, transform_bits) * VP8LFastLog2(24);
    209       // For palettes, add the cost of storing the palette.
    210       // We empirically estimate the cost of a compressed entry as 8 bits.
    211       // The palette is differential-coded when compressed hence a much
    212       // lower cost than sizeof(uint32_t)*8.
    213       entropy[kPalette] += (palette_size * 8ull) << LOG_2_PRECISION_BITS;
    214 
    215       *min_entropy_ix = kDirect;
    216       for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) {
    217         if (entropy[*min_entropy_ix] > entropy[k]) {
    218           *min_entropy_ix = (EntropyIx)k;
    219         }
    220       }
    221       assert((int)*min_entropy_ix <= last_mode_to_analyze);
    222       *red_and_blue_always_zero = 1;
    223       // Let's check if the histogram of the chosen entropy mode has
    224       // non-zero red and blue values. If all are zero, we can later skip
    225       // the cross color optimization.
    226       {
    227         static const uint8_t kHistoPairs[5][2] = {
    228           { kHistoRed, kHistoBlue },
    229           { kHistoRedPred, kHistoBluePred },
    230           { kHistoRedSubGreen, kHistoBlueSubGreen },
    231           { kHistoRedPredSubGreen, kHistoBluePredSubGreen },
    232           { kHistoRed, kHistoBlue }
    233         };
    234         const HistogramBuckets* const red_histo =
    235             &histo->category[kHistoPairs[*min_entropy_ix][0]];
    236         const HistogramBuckets* const blue_histo =
    237             &histo->category[kHistoPairs[*min_entropy_ix][1]];
    238         for (i = 1; i < NUM_BUCKETS; ++i) {
    239           if (((*red_histo)[i] | (*blue_histo)[i]) != 0) {
    240             *red_and_blue_always_zero = 0;
    241             break;
    242           }
    243         }
    244       }
    245     }
    246     WebPSafeFree(histo);
    247     return 1;
    248   } else {
    249     return 0;
    250   }
    251 }
    252 
    253 // Clamp histogram and transform bits.
    254 static int ClampBits(int width, int height, int bits, int min_bits,
    255                      int max_bits, int image_size_max) {
    256   int image_size;
    257   bits = (bits < min_bits) ? min_bits : (bits > max_bits) ? max_bits : bits;
    258   image_size = VP8LSubSampleSize(width, bits) * VP8LSubSampleSize(height, bits);
    259   while (bits < max_bits && image_size > image_size_max) {
    260     ++bits;
    261     image_size =
    262         VP8LSubSampleSize(width, bits) * VP8LSubSampleSize(height, bits);
    263   }
    264   // In case the bits reduce the image too much, choose the smallest value
    265   // setting the histogram image size to 1.
    266   while (bits > min_bits && image_size == 1) {
    267     image_size = VP8LSubSampleSize(width, bits - 1) *
    268                  VP8LSubSampleSize(height, bits - 1);
    269     if (image_size != 1) break;
    270     --bits;
    271   }
    272   return bits;
    273 }
    274 
    275 static int GetHistoBits(int method, int use_palette, int width, int height) {
    276   // Make tile size a function of encoding method (Range: 0 to 6).
    277   const int histo_bits = (use_palette ? 9 : 7) - method;
    278   return ClampBits(width, height, histo_bits, MIN_HUFFMAN_BITS,
    279                    MAX_HUFFMAN_BITS, MAX_HUFF_IMAGE_SIZE);
    280 }
    281 
    282 static int GetTransformBits(int method, int histo_bits) {
    283   const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5;
    284   const int res =
    285       (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits;
    286   assert(res <= MAX_TRANSFORM_BITS);
    287   return res;
    288 }
    289 
    290 // Set of parameters to be used in each iteration of the cruncher.
    291 #define CRUNCH_SUBCONFIGS_MAX 2
    292 typedef struct {
    293   int lz77;
    294   int do_no_cache;
    295 } CrunchSubConfig;
    296 typedef struct {
    297   int entropy_idx;
    298   PaletteSorting palette_sorting_type;
    299   CrunchSubConfig sub_configs[CRUNCH_SUBCONFIGS_MAX];
    300   int sub_configs_size;
    301 } CrunchConfig;
    302 
    303 // +2 because we add a palette sorting configuration for kPalette and
    304 // kPaletteAndSpatial.
    305 #define CRUNCH_CONFIGS_MAX (kNumEntropyIx + 2 * kPaletteSortingNum)
    306 
    307 static int EncoderAnalyze(VP8LEncoder* const enc,
    308                           CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX],
    309                           int* const crunch_configs_size,
    310                           int* const red_and_blue_always_zero) {
    311   const WebPPicture* const pic = enc->pic;
    312   const int width = pic->width;
    313   const int height = pic->height;
    314   const WebPConfig* const config = enc->config;
    315   const int method = config->method;
    316   const int low_effort = (config->method == 0);
    317   int i;
    318   int use_palette, transform_bits;
    319   int n_lz77s;
    320   // If set to 0, analyze the cache with the computed cache value. If 1, also
    321   // analyze with no-cache.
    322   int do_no_cache = 0;
    323   assert(pic != NULL && pic->argb != NULL);
    324 
    325   // Check whether a palette is possible.
    326   enc->palette_size = GetColorPalette(pic, enc->palette_sorted);
    327   use_palette = (enc->palette_size <= MAX_PALETTE_SIZE);
    328   if (!use_palette) {
    329     enc->palette_size = 0;
    330   }
    331 
    332   // Empirical bit sizes.
    333   enc->histo_bits = GetHistoBits(method, use_palette,
    334                                  pic->width, pic->height);
    335   transform_bits = GetTransformBits(method, enc->histo_bits);
    336   enc->predictor_transform_bits = transform_bits;
    337   enc->cross_color_transform_bits = transform_bits;
    338 
    339   if (low_effort) {
    340     // AnalyzeEntropy is somewhat slow.
    341     crunch_configs[0].entropy_idx = use_palette ? kPalette : kSpatialSubGreen;
    342     crunch_configs[0].palette_sorting_type =
    343         use_palette ? kSortedDefault : kUnusedPalette;
    344     n_lz77s = 1;
    345     *crunch_configs_size = 1;
    346   } else {
    347     EntropyIx min_entropy_ix;
    348     // Try out multiple LZ77 on images with few colors.
    349     n_lz77s = (enc->palette_size > 0 && enc->palette_size <= 16) ? 2 : 1;
    350     if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette,
    351                         enc->palette_size, transform_bits, &min_entropy_ix,
    352                         red_and_blue_always_zero)) {
    353       return 0;
    354     }
    355     if (method == 6 && config->quality == 100) {
    356       do_no_cache = 1;
    357       // Go brute force on all transforms.
    358       *crunch_configs_size = 0;
    359       for (i = 0; i < kNumEntropyIx; ++i) {
    360         // We can only apply kPalette or kPaletteAndSpatial if we can indeed use
    361         // a palette.
    362         if ((i != kPalette && i != kPaletteAndSpatial) || use_palette) {
    363           assert(*crunch_configs_size < CRUNCH_CONFIGS_MAX);
    364           if (use_palette && (i == kPalette || i == kPaletteAndSpatial)) {
    365             int sorting_method;
    366             for (sorting_method = 0; sorting_method < kPaletteSortingNum;
    367                  ++sorting_method) {
    368               const PaletteSorting typed_sorting_method =
    369                   (PaletteSorting)sorting_method;
    370               // TODO(vrabaud) kSortedDefault should be tested. It is omitted
    371               // for now for backward compatibility.
    372               if (typed_sorting_method == kUnusedPalette ||
    373                   typed_sorting_method == kSortedDefault) {
    374                 continue;
    375               }
    376               crunch_configs[(*crunch_configs_size)].entropy_idx = i;
    377               crunch_configs[(*crunch_configs_size)].palette_sorting_type =
    378                   typed_sorting_method;
    379               ++*crunch_configs_size;
    380             }
    381           } else {
    382             crunch_configs[(*crunch_configs_size)].entropy_idx = i;
    383             crunch_configs[(*crunch_configs_size)].palette_sorting_type =
    384                 kUnusedPalette;
    385             ++*crunch_configs_size;
    386           }
    387         }
    388       }
    389     } else {
    390       // Only choose the guessed best transform.
    391       *crunch_configs_size = 1;
    392       crunch_configs[0].entropy_idx = min_entropy_ix;
    393       crunch_configs[0].palette_sorting_type =
    394           use_palette ? kMinimizeDelta : kUnusedPalette;
    395       if (config->quality >= 75 && method == 5) {
    396         // Test with and without color cache.
    397         do_no_cache = 1;
    398         // If we have a palette, also check in combination with spatial.
    399         if (min_entropy_ix == kPalette) {
    400           *crunch_configs_size = 2;
    401           crunch_configs[1].entropy_idx = kPaletteAndSpatial;
    402           crunch_configs[1].palette_sorting_type = kMinimizeDelta;
    403         }
    404       }
    405     }
    406   }
    407   // Fill in the different LZ77s.
    408   assert(n_lz77s <= CRUNCH_SUBCONFIGS_MAX);
    409   for (i = 0; i < *crunch_configs_size; ++i) {
    410     int j;
    411     for (j = 0; j < n_lz77s; ++j) {
    412       assert(j < CRUNCH_SUBCONFIGS_MAX);
    413       crunch_configs[i].sub_configs[j].lz77 =
    414           (j == 0) ? kLZ77Standard | kLZ77RLE : kLZ77Box;
    415       crunch_configs[i].sub_configs[j].do_no_cache = do_no_cache;
    416     }
    417     crunch_configs[i].sub_configs_size = n_lz77s;
    418   }
    419   return 1;
    420 }
    421 
    422 static int EncoderInit(VP8LEncoder* const enc) {
    423   const WebPPicture* const pic = enc->pic;
    424   const int width = pic->width;
    425   const int height = pic->height;
    426   const int pix_cnt = width * height;
    427   // we round the block size up, so we're guaranteed to have
    428   // at most MAX_REFS_BLOCK_PER_IMAGE blocks used:
    429   const int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1;
    430   int i;
    431   if (!VP8LHashChainInit(&enc->hash_chain, pix_cnt)) return 0;
    432 
    433   for (i = 0; i < 4; ++i) VP8LBackwardRefsInit(&enc->refs[i], refs_block_size);
    434 
    435   return 1;
    436 }
    437 
    438 // Returns false in case of memory error.
    439 static int GetHuffBitLengthsAndCodes(
    440     const VP8LHistogramSet* const histogram_image,
    441     HuffmanTreeCode* const huffman_codes) {
    442   int i, k;
    443   int ok = 0;
    444   uint64_t total_length_size = 0;
    445   uint8_t* mem_buf = NULL;
    446   const int histogram_image_size = histogram_image->size;
    447   int max_num_symbols = 0;
    448   uint8_t* buf_rle = NULL;
    449   HuffmanTree* huff_tree = NULL;
    450 
    451   // Iterate over all histograms and get the aggregate number of codes used.
    452   for (i = 0; i < histogram_image_size; ++i) {
    453     const VP8LHistogram* const histo = histogram_image->histograms[i];
    454     HuffmanTreeCode* const codes = &huffman_codes[5 * i];
    455     assert(histo != NULL);
    456     for (k = 0; k < 5; ++k) {
    457       const int num_symbols =
    458           (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits) :
    459           (k == 4) ? NUM_DISTANCE_CODES : 256;
    460       codes[k].num_symbols = num_symbols;
    461       total_length_size += num_symbols;
    462     }
    463   }
    464 
    465   // Allocate and Set Huffman codes.
    466   {
    467     uint16_t* codes;
    468     uint8_t* lengths;
    469     mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
    470                                        sizeof(*lengths) + sizeof(*codes));
    471     if (mem_buf == NULL) goto End;
    472 
    473     codes = (uint16_t*)mem_buf;
    474     lengths = (uint8_t*)&codes[total_length_size];
    475     for (i = 0; i < 5 * histogram_image_size; ++i) {
    476       const int bit_length = huffman_codes[i].num_symbols;
    477       huffman_codes[i].codes = codes;
    478       huffman_codes[i].code_lengths = lengths;
    479       codes += bit_length;
    480       lengths += bit_length;
    481       if (max_num_symbols < bit_length) {
    482         max_num_symbols = bit_length;
    483       }
    484     }
    485   }
    486 
    487   buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols);
    488   huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols,
    489                                            sizeof(*huff_tree));
    490   if (buf_rle == NULL || huff_tree == NULL) goto End;
    491 
    492   // Create Huffman trees.
    493   for (i = 0; i < histogram_image_size; ++i) {
    494     HuffmanTreeCode* const codes = &huffman_codes[5 * i];
    495     VP8LHistogram* const histo = histogram_image->histograms[i];
    496     VP8LCreateHuffmanTree(histo->literal, 15, buf_rle, huff_tree, codes + 0);
    497     VP8LCreateHuffmanTree(histo->red, 15, buf_rle, huff_tree, codes + 1);
    498     VP8LCreateHuffmanTree(histo->blue, 15, buf_rle, huff_tree, codes + 2);
    499     VP8LCreateHuffmanTree(histo->alpha, 15, buf_rle, huff_tree, codes + 3);
    500     VP8LCreateHuffmanTree(histo->distance, 15, buf_rle, huff_tree, codes + 4);
    501   }
    502   ok = 1;
    503  End:
    504   WebPSafeFree(huff_tree);
    505   WebPSafeFree(buf_rle);
    506   if (!ok) {
    507     WebPSafeFree(mem_buf);
    508     memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
    509   }
    510   return ok;
    511 }
    512 
    513 static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
    514     VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) {
    515   // RFC 1951 will calm you down if you are worried about this funny sequence.
    516   // This sequence is tuned from that, but more weighted for lower symbol count,
    517   // and more spiking histograms.
    518   static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = {
    519     17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    520   };
    521   int i;
    522   // Throw away trailing zeros:
    523   int codes_to_store = CODE_LENGTH_CODES;
    524   for (; codes_to_store > 4; --codes_to_store) {
    525     if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
    526       break;
    527     }
    528   }
    529   VP8LPutBits(bw, codes_to_store - 4, 4);
    530   for (i = 0; i < codes_to_store; ++i) {
    531     VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3);
    532   }
    533 }
    534 
    535 static void ClearHuffmanTreeIfOnlyOneSymbol(
    536     HuffmanTreeCode* const huffman_code) {
    537   int k;
    538   int count = 0;
    539   for (k = 0; k < huffman_code->num_symbols; ++k) {
    540     if (huffman_code->code_lengths[k] != 0) {
    541       ++count;
    542       if (count > 1) return;
    543     }
    544   }
    545   for (k = 0; k < huffman_code->num_symbols; ++k) {
    546     huffman_code->code_lengths[k] = 0;
    547     huffman_code->codes[k] = 0;
    548   }
    549 }
    550 
    551 static void StoreHuffmanTreeToBitMask(
    552     VP8LBitWriter* const bw,
    553     const HuffmanTreeToken* const tokens, const int num_tokens,
    554     const HuffmanTreeCode* const huffman_code) {
    555   int i;
    556   for (i = 0; i < num_tokens; ++i) {
    557     const int ix = tokens[i].code;
    558     const int extra_bits = tokens[i].extra_bits;
    559     VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]);
    560     switch (ix) {
    561       case 16:
    562         VP8LPutBits(bw, extra_bits, 2);
    563         break;
    564       case 17:
    565         VP8LPutBits(bw, extra_bits, 3);
    566         break;
    567       case 18:
    568         VP8LPutBits(bw, extra_bits, 7);
    569         break;
    570     }
    571   }
    572 }
    573 
    574 // 'huff_tree' and 'tokens' are pre-alloacted buffers.
    575 static void StoreFullHuffmanCode(VP8LBitWriter* const bw,
    576                                  HuffmanTree* const huff_tree,
    577                                  HuffmanTreeToken* const tokens,
    578                                  const HuffmanTreeCode* const tree) {
    579   uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
    580   uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
    581   const int max_tokens = tree->num_symbols;
    582   int num_tokens;
    583   HuffmanTreeCode huffman_code;
    584   huffman_code.num_symbols = CODE_LENGTH_CODES;
    585   huffman_code.code_lengths = code_length_bitdepth;
    586   huffman_code.codes = code_length_bitdepth_symbols;
    587 
    588   VP8LPutBits(bw, 0, 1);
    589   num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
    590   {
    591     uint32_t histogram[CODE_LENGTH_CODES] = { 0 };
    592     uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 };
    593     int i;
    594     for (i = 0; i < num_tokens; ++i) {
    595       ++histogram[tokens[i].code];
    596     }
    597 
    598     VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
    599   }
    600 
    601   StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth);
    602   ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code);
    603   {
    604     int trailing_zero_bits = 0;
    605     int trimmed_length = num_tokens;
    606     int write_trimmed_length;
    607     int length;
    608     int i = num_tokens;
    609     while (i-- > 0) {
    610       const int ix = tokens[i].code;
    611       if (ix == 0 || ix == 17 || ix == 18) {
    612         --trimmed_length;   // discount trailing zeros
    613         trailing_zero_bits += code_length_bitdepth[ix];
    614         if (ix == 17) {
    615           trailing_zero_bits += 3;
    616         } else if (ix == 18) {
    617           trailing_zero_bits += 7;
    618         }
    619       } else {
    620         break;
    621       }
    622     }
    623     write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12);
    624     length = write_trimmed_length ? trimmed_length : num_tokens;
    625     VP8LPutBits(bw, write_trimmed_length, 1);
    626     if (write_trimmed_length) {
    627       if (trimmed_length == 2) {
    628         VP8LPutBits(bw, 0, 3 + 2);     // nbitpairs=1, trimmed_length=2
    629       } else {
    630         const int nbits = BitsLog2Floor(trimmed_length - 2);
    631         const int nbitpairs = nbits / 2 + 1;
    632         assert(trimmed_length > 2);
    633         assert(nbitpairs - 1 < 8);
    634         VP8LPutBits(bw, nbitpairs - 1, 3);
    635         VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2);
    636       }
    637     }
    638     StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
    639   }
    640 }
    641 
    642 // 'huff_tree' and 'tokens' are pre-alloacted buffers.
    643 static void StoreHuffmanCode(VP8LBitWriter* const bw,
    644                              HuffmanTree* const huff_tree,
    645                              HuffmanTreeToken* const tokens,
    646                              const HuffmanTreeCode* const huffman_code) {
    647   int i;
    648   int count = 0;
    649   int symbols[2] = { 0, 0 };
    650   const int kMaxBits = 8;
    651   const int kMaxSymbol = 1 << kMaxBits;
    652 
    653   // Check whether it's a small tree.
    654   for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) {
    655     if (huffman_code->code_lengths[i] != 0) {
    656       if (count < 2) symbols[count] = i;
    657       ++count;
    658     }
    659   }
    660 
    661   if (count == 0) {   // emit minimal tree for empty cases
    662     // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
    663     VP8LPutBits(bw, 0x01, 4);
    664   } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
    665     VP8LPutBits(bw, 1, 1);  // Small tree marker to encode 1 or 2 symbols.
    666     VP8LPutBits(bw, count - 1, 1);
    667     if (symbols[0] <= 1) {
    668       VP8LPutBits(bw, 0, 1);  // Code bit for small (1 bit) symbol value.
    669       VP8LPutBits(bw, symbols[0], 1);
    670     } else {
    671       VP8LPutBits(bw, 1, 1);
    672       VP8LPutBits(bw, symbols[0], 8);
    673     }
    674     if (count == 2) {
    675       VP8LPutBits(bw, symbols[1], 8);
    676     }
    677   } else {
    678     StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
    679   }
    680 }
    681 
    682 static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw,
    683                              const HuffmanTreeCode* const code,
    684                              int code_index) {
    685   const int depth = code->code_lengths[code_index];
    686   const int symbol = code->codes[code_index];
    687   VP8LPutBits(bw, symbol, depth);
    688 }
    689 
    690 static WEBP_INLINE void WriteHuffmanCodeWithExtraBits(
    691     VP8LBitWriter* const bw,
    692     const HuffmanTreeCode* const code,
    693     int code_index,
    694     int bits,
    695     int n_bits) {
    696   const int depth = code->code_lengths[code_index];
    697   const int symbol = code->codes[code_index];
    698   VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits);
    699 }
    700 
    701 static int StoreImageToBitMask(VP8LBitWriter* const bw, int width,
    702                                int histo_bits,
    703                                const VP8LBackwardRefs* const refs,
    704                                const uint32_t* histogram_symbols,
    705                                const HuffmanTreeCode* const huffman_codes,
    706                                const WebPPicture* const pic) {
    707   const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
    708   const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits);
    709   // x and y trace the position in the image.
    710   int x = 0;
    711   int y = 0;
    712   int tile_x = x & tile_mask;
    713   int tile_y = y & tile_mask;
    714   int histogram_ix = (histogram_symbols[0] >> 8) & 0xffff;
    715   const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix;
    716   VP8LRefsCursor c = VP8LRefsCursorInit(refs);
    717   while (VP8LRefsCursorOk(&c)) {
    718     const PixOrCopy* const v = c.cur_pos;
    719     if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) {
    720       tile_x = x & tile_mask;
    721       tile_y = y & tile_mask;
    722       histogram_ix = (histogram_symbols[(y >> histo_bits) * histo_xsize +
    723                                         (x >> histo_bits)] >>
    724                       8) &
    725                      0xffff;
    726       codes = huffman_codes + 5 * histogram_ix;
    727     }
    728     if (PixOrCopyIsLiteral(v)) {
    729       static const uint8_t order[] = { 1, 2, 0, 3 };
    730       int k;
    731       for (k = 0; k < 4; ++k) {
    732         const int code = PixOrCopyLiteral(v, order[k]);
    733         WriteHuffmanCode(bw, codes + k, code);
    734       }
    735     } else if (PixOrCopyIsCacheIdx(v)) {
    736       const int code = PixOrCopyCacheIdx(v);
    737       const int literal_ix = 256 + NUM_LENGTH_CODES + code;
    738       WriteHuffmanCode(bw, codes, literal_ix);
    739     } else {
    740       int bits, n_bits;
    741       int code;
    742 
    743       const int distance = PixOrCopyDistance(v);
    744       VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
    745       WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits);
    746 
    747       // Don't write the distance with the extra bits code since
    748       // the distance can be up to 18 bits of extra bits, and the prefix
    749       // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits.
    750       VP8LPrefixEncode(distance, &code, &n_bits, &bits);
    751       WriteHuffmanCode(bw, codes + 4, code);
    752       VP8LPutBits(bw, bits, n_bits);
    753     }
    754     x += PixOrCopyLength(v);
    755     while (x >= width) {
    756       x -= width;
    757       ++y;
    758     }
    759     VP8LRefsCursorNext(&c);
    760   }
    761   if (bw->error) {
    762     return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    763   }
    764   return 1;
    765 }
    766 
    767 // Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31.
    768 // pic and percent are for progress.
    769 static int EncodeImageNoHuffman(VP8LBitWriter* const bw,
    770                                 const uint32_t* const argb,
    771                                 VP8LHashChain* const hash_chain,
    772                                 VP8LBackwardRefs* const refs_array, int width,
    773                                 int height, int quality, int low_effort,
    774                                 const WebPPicture* const pic, int percent_range,
    775                                 int* const percent) {
    776   int i;
    777   int max_tokens = 0;
    778   VP8LBackwardRefs* refs;
    779   HuffmanTreeToken* tokens = NULL;
    780   HuffmanTreeCode huffman_codes[5] = {{0, NULL, NULL}};
    781   const uint32_t histogram_symbols[1] = {0};  // only one tree, one symbol
    782   int cache_bits = 0;
    783   VP8LHistogramSet* histogram_image = NULL;
    784   HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
    785       3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
    786   if (huff_tree == NULL) {
    787     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    788     goto Error;
    789   }
    790 
    791   // Calculate backward references from ARGB image.
    792   if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, low_effort,
    793                          pic, percent_range / 2, percent)) {
    794     goto Error;
    795   }
    796   if (!VP8LGetBackwardReferences(width, height, argb, quality, /*low_effort=*/0,
    797                                  kLZ77Standard | kLZ77RLE, cache_bits,
    798                                  /*do_no_cache=*/0, hash_chain, refs_array,
    799                                  &cache_bits, pic,
    800                                  percent_range - percent_range / 2, percent)) {
    801     goto Error;
    802   }
    803   refs = &refs_array[0];
    804   histogram_image = VP8LAllocateHistogramSet(1, cache_bits);
    805   if (histogram_image == NULL) {
    806     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    807     goto Error;
    808   }
    809   VP8LHistogramSetClear(histogram_image);
    810 
    811   // Build histogram image and symbols from backward references.
    812   VP8LHistogramStoreRefs(refs, /*distance_modifier=*/NULL,
    813                          /*distance_modifier_arg0=*/0,
    814                          histogram_image->histograms[0]);
    815 
    816   // Create Huffman bit lengths and codes for each histogram image.
    817   assert(histogram_image->size == 1);
    818   if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
    819     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    820     goto Error;
    821   }
    822 
    823   // No color cache, no Huffman image.
    824   VP8LPutBits(bw, 0, 1);
    825 
    826   // Find maximum number of symbols for the huffman tree-set.
    827   for (i = 0; i < 5; ++i) {
    828     HuffmanTreeCode* const codes = &huffman_codes[i];
    829     if (max_tokens < codes->num_symbols) {
    830       max_tokens = codes->num_symbols;
    831     }
    832   }
    833 
    834   tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
    835   if (tokens == NULL) {
    836     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    837     goto Error;
    838   }
    839 
    840   // Store Huffman codes.
    841   for (i = 0; i < 5; ++i) {
    842     HuffmanTreeCode* const codes = &huffman_codes[i];
    843     StoreHuffmanCode(bw, huff_tree, tokens, codes);
    844     ClearHuffmanTreeIfOnlyOneSymbol(codes);
    845   }
    846 
    847   // Store actual literals.
    848   if (!StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, huffman_codes,
    849                            pic)) {
    850     goto Error;
    851   }
    852 
    853  Error:
    854   WebPSafeFree(tokens);
    855   WebPSafeFree(huff_tree);
    856   VP8LFreeHistogramSet(histogram_image);
    857   WebPSafeFree(huffman_codes[0].codes);
    858   return (pic->error_code == VP8_ENC_OK);
    859 }
    860 
    861 // pic and percent are for progress.
    862 static int EncodeImageInternal(
    863     VP8LBitWriter* const bw, const uint32_t* const argb,
    864     VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[4], int width,
    865     int height, int quality, int low_effort, const CrunchConfig* const config,
    866     int* cache_bits, int histogram_bits_in, size_t init_byte_position,
    867     int* const hdr_size, int* const data_size, const WebPPicture* const pic,
    868     int percent_range, int* const percent) {
    869   const uint32_t histogram_image_xysize =
    870       VP8LSubSampleSize(width, histogram_bits_in) *
    871       VP8LSubSampleSize(height, histogram_bits_in);
    872   int remaining_percent = percent_range;
    873   int percent_start = *percent;
    874   VP8LHistogramSet* histogram_image = NULL;
    875   VP8LHistogram* tmp_histo = NULL;
    876   uint32_t i, histogram_image_size = 0;
    877   size_t bit_array_size = 0;
    878   HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
    879       3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
    880   HuffmanTreeToken* tokens = NULL;
    881   HuffmanTreeCode* huffman_codes = NULL;
    882   uint32_t* const histogram_argb = (uint32_t*)WebPSafeMalloc(
    883       histogram_image_xysize, sizeof(*histogram_argb));
    884   int sub_configs_idx;
    885   int cache_bits_init, write_histogram_image;
    886   VP8LBitWriter bw_init = *bw, bw_best;
    887   int hdr_size_tmp;
    888   VP8LHashChain hash_chain_histogram;  // histogram image hash chain
    889   size_t bw_size_best = ~(size_t)0;
    890   assert(histogram_bits_in >= MIN_HUFFMAN_BITS);
    891   assert(histogram_bits_in <= MAX_HUFFMAN_BITS);
    892   assert(hdr_size != NULL);
    893   assert(data_size != NULL);
    894 
    895   memset(&hash_chain_histogram, 0, sizeof(hash_chain_histogram));
    896   if (!VP8LBitWriterInit(&bw_best, 0)) {
    897     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    898     goto Error;
    899   }
    900 
    901   // Make sure we can allocate the different objects.
    902   if (huff_tree == NULL || histogram_argb == NULL ||
    903       !VP8LHashChainInit(&hash_chain_histogram, histogram_image_xysize)) {
    904     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    905     goto Error;
    906   }
    907 
    908   percent_range = remaining_percent / 5;
    909   if (!VP8LHashChainFill(hash_chain, quality, argb, width, height,
    910                          low_effort, pic, percent_range, percent)) {
    911     goto Error;
    912   }
    913   percent_start += percent_range;
    914   remaining_percent -= percent_range;
    915 
    916   // If the value is different from zero, it has been set during the palette
    917   // analysis.
    918   cache_bits_init = (*cache_bits == 0) ? MAX_COLOR_CACHE_BITS : *cache_bits;
    919   // If several iterations will happen, clone into bw_best.
    920   if ((config->sub_configs_size > 1 || config->sub_configs[0].do_no_cache) &&
    921       !VP8LBitWriterClone(bw, &bw_best)) {
    922     WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    923     goto Error;
    924   }
    925 
    926   for (sub_configs_idx = 0; sub_configs_idx < config->sub_configs_size;
    927        ++sub_configs_idx) {
    928     const CrunchSubConfig* const sub_config =
    929         &config->sub_configs[sub_configs_idx];
    930     int cache_bits_best, i_cache;
    931     int i_remaining_percent = remaining_percent / config->sub_configs_size;
    932     int i_percent_range = i_remaining_percent / 4;
    933     i_remaining_percent -= i_percent_range;
    934 
    935     if (!VP8LGetBackwardReferences(
    936             width, height, argb, quality, low_effort, sub_config->lz77,
    937             cache_bits_init, sub_config->do_no_cache, hash_chain,
    938             &refs_array[0], &cache_bits_best, pic, i_percent_range, percent)) {
    939       goto Error;
    940     }
    941 
    942     for (i_cache = 0; i_cache < (sub_config->do_no_cache ? 2 : 1); ++i_cache) {
    943       const int cache_bits_tmp = (i_cache == 0) ? cache_bits_best : 0;
    944       int histogram_bits = histogram_bits_in;
    945       // Speed-up: no need to study the no-cache case if it was already studied
    946       // in i_cache == 0.
    947       if (i_cache == 1 && cache_bits_best == 0) break;
    948 
    949       // Reset the bit writer for this iteration.
    950       VP8LBitWriterReset(&bw_init, bw);
    951 
    952       // Build histogram image and symbols from backward references.
    953       histogram_image =
    954           VP8LAllocateHistogramSet(histogram_image_xysize, cache_bits_tmp);
    955       tmp_histo = VP8LAllocateHistogram(cache_bits_tmp);
    956       if (histogram_image == NULL || tmp_histo == NULL) {
    957         WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    958         goto Error;
    959       }
    960 
    961       i_percent_range = i_remaining_percent / 3;
    962       i_remaining_percent -= i_percent_range;
    963       if (!VP8LGetHistoImageSymbols(
    964               width, height, &refs_array[i_cache], quality, low_effort,
    965               histogram_bits, cache_bits_tmp, histogram_image, tmp_histo,
    966               histogram_argb, pic, i_percent_range, percent)) {
    967         goto Error;
    968       }
    969       // Create Huffman bit lengths and codes for each histogram image.
    970       histogram_image_size = histogram_image->size;
    971       bit_array_size = 5 * histogram_image_size;
    972       huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
    973                                                        sizeof(*huffman_codes));
    974       // Note: some histogram_image entries may point to tmp_histos[], so the
    975       // latter need to outlive the following call to
    976       // GetHuffBitLengthsAndCodes().
    977       if (huffman_codes == NULL ||
    978           !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
    979         WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
    980         goto Error;
    981       }
    982       // Free combined histograms.
    983       VP8LFreeHistogramSet(histogram_image);
    984       histogram_image = NULL;
    985 
    986       // Free scratch histograms.
    987       VP8LFreeHistogram(tmp_histo);
    988       tmp_histo = NULL;
    989 
    990       // Color Cache parameters.
    991       if (cache_bits_tmp > 0) {
    992         VP8LPutBits(bw, 1, 1);
    993         VP8LPutBits(bw, cache_bits_tmp, 4);
    994       } else {
    995         VP8LPutBits(bw, 0, 1);
    996       }
    997 
    998       // Huffman image + meta huffman.
    999       histogram_image_size = 0;
   1000       for (i = 0; i < histogram_image_xysize; ++i) {
   1001         if (histogram_argb[i] >= histogram_image_size) {
   1002           histogram_image_size = histogram_argb[i] + 1;
   1003         }
   1004         histogram_argb[i] <<= 8;
   1005       }
   1006 
   1007       write_histogram_image = (histogram_image_size > 1);
   1008       VP8LPutBits(bw, write_histogram_image, 1);
   1009       if (write_histogram_image) {
   1010         VP8LOptimizeSampling(histogram_argb, width, height, histogram_bits_in,
   1011                              MAX_HUFFMAN_BITS, &histogram_bits);
   1012         VP8LPutBits(bw, histogram_bits - 2, 3);
   1013         i_percent_range = i_remaining_percent / 2;
   1014         i_remaining_percent -= i_percent_range;
   1015         if (!EncodeImageNoHuffman(
   1016                 bw, histogram_argb, &hash_chain_histogram, &refs_array[2],
   1017                 VP8LSubSampleSize(width, histogram_bits),
   1018                 VP8LSubSampleSize(height, histogram_bits), quality, low_effort,
   1019                 pic, i_percent_range, percent)) {
   1020           goto Error;
   1021         }
   1022       }
   1023 
   1024       // Store Huffman codes.
   1025       {
   1026         int max_tokens = 0;
   1027         // Find maximum number of symbols for the huffman tree-set.
   1028         for (i = 0; i < 5 * histogram_image_size; ++i) {
   1029           HuffmanTreeCode* const codes = &huffman_codes[i];
   1030           if (max_tokens < codes->num_symbols) {
   1031             max_tokens = codes->num_symbols;
   1032           }
   1033         }
   1034         tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
   1035         if (tokens == NULL) {
   1036           WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1037           goto Error;
   1038         }
   1039         for (i = 0; i < 5 * histogram_image_size; ++i) {
   1040           HuffmanTreeCode* const codes = &huffman_codes[i];
   1041           StoreHuffmanCode(bw, huff_tree, tokens, codes);
   1042           ClearHuffmanTreeIfOnlyOneSymbol(codes);
   1043         }
   1044       }
   1045       // Store actual literals.
   1046       hdr_size_tmp = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position);
   1047       if (!StoreImageToBitMask(bw, width, histogram_bits, &refs_array[i_cache],
   1048                                histogram_argb, huffman_codes, pic)) {
   1049         goto Error;
   1050       }
   1051       // Keep track of the smallest image so far.
   1052       if (VP8LBitWriterNumBytes(bw) < bw_size_best) {
   1053         bw_size_best = VP8LBitWriterNumBytes(bw);
   1054         *cache_bits = cache_bits_tmp;
   1055         *hdr_size = hdr_size_tmp;
   1056         *data_size =
   1057             (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size);
   1058         VP8LBitWriterSwap(bw, &bw_best);
   1059       }
   1060       WebPSafeFree(tokens);
   1061       tokens = NULL;
   1062       if (huffman_codes != NULL) {
   1063         WebPSafeFree(huffman_codes->codes);
   1064         WebPSafeFree(huffman_codes);
   1065         huffman_codes = NULL;
   1066       }
   1067     }
   1068   }
   1069   VP8LBitWriterSwap(bw, &bw_best);
   1070 
   1071   if (!WebPReportProgress(pic, percent_start + remaining_percent, percent)) {
   1072     goto Error;
   1073   }
   1074 
   1075  Error:
   1076   WebPSafeFree(tokens);
   1077   WebPSafeFree(huff_tree);
   1078   VP8LFreeHistogramSet(histogram_image);
   1079   VP8LFreeHistogram(tmp_histo);
   1080   VP8LHashChainClear(&hash_chain_histogram);
   1081   if (huffman_codes != NULL) {
   1082     WebPSafeFree(huffman_codes->codes);
   1083     WebPSafeFree(huffman_codes);
   1084   }
   1085   WebPSafeFree(histogram_argb);
   1086   VP8LBitWriterWipeOut(&bw_best);
   1087   return (pic->error_code == VP8_ENC_OK);
   1088 }
   1089 
   1090 // -----------------------------------------------------------------------------
   1091 // Transforms
   1092 
   1093 static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height,
   1094                                VP8LBitWriter* const bw) {
   1095   VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
   1096   VP8LPutBits(bw, SUBTRACT_GREEN_TRANSFORM, 2);
   1097   VP8LSubtractGreenFromBlueAndRed(enc->argb, width * height);
   1098 }
   1099 
   1100 static int ApplyPredictFilter(VP8LEncoder* const enc, int width, int height,
   1101                               int quality, int low_effort,
   1102                               int used_subtract_green, VP8LBitWriter* const bw,
   1103                               int percent_range, int* const percent,
   1104                               int* const best_bits) {
   1105   const int near_lossless_strength =
   1106       enc->use_palette ? 100 : enc->config->near_lossless;
   1107   const int max_bits = ClampBits(width, height, enc->predictor_transform_bits,
   1108                                  MIN_TRANSFORM_BITS, MAX_TRANSFORM_BITS,
   1109                                  MAX_PREDICTOR_IMAGE_SIZE);
   1110   const int min_bits = ClampBits(
   1111       width, height,
   1112       max_bits - 2 * (enc->config->method > 4 ? enc->config->method - 4 : 0),
   1113       MIN_TRANSFORM_BITS, MAX_TRANSFORM_BITS, MAX_PREDICTOR_IMAGE_SIZE);
   1114 
   1115   if (!VP8LResidualImage(width, height, min_bits, max_bits, low_effort,
   1116                          enc->argb, enc->argb_scratch, enc->transform_data,
   1117                          near_lossless_strength, enc->config->exact,
   1118                          used_subtract_green, enc->pic, percent_range / 2,
   1119                          percent, best_bits)) {
   1120     return 0;
   1121   }
   1122   VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
   1123   VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
   1124   assert(*best_bits >= MIN_TRANSFORM_BITS && *best_bits <= MAX_TRANSFORM_BITS);
   1125   VP8LPutBits(bw, *best_bits - MIN_TRANSFORM_BITS, NUM_TRANSFORM_BITS);
   1126   return EncodeImageNoHuffman(
   1127       bw, enc->transform_data, &enc->hash_chain, &enc->refs[0],
   1128       VP8LSubSampleSize(width, *best_bits),
   1129       VP8LSubSampleSize(height, *best_bits), quality, low_effort, enc->pic,
   1130       percent_range - percent_range / 2, percent);
   1131 }
   1132 
   1133 static int ApplyCrossColorFilter(VP8LEncoder* const enc, int width, int height,
   1134                                  int quality, int low_effort,
   1135                                  VP8LBitWriter* const bw, int percent_range,
   1136                                  int* const percent, int* const best_bits) {
   1137   const int min_bits = enc->cross_color_transform_bits;
   1138 
   1139   if (!VP8LColorSpaceTransform(width, height, min_bits, quality, enc->argb,
   1140                                enc->transform_data, enc->pic, percent_range / 2,
   1141                                percent, best_bits)) {
   1142     return 0;
   1143   }
   1144   VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
   1145   VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2);
   1146   assert(*best_bits >= MIN_TRANSFORM_BITS && *best_bits <= MAX_TRANSFORM_BITS);
   1147   VP8LPutBits(bw, *best_bits - MIN_TRANSFORM_BITS, NUM_TRANSFORM_BITS);
   1148   return EncodeImageNoHuffman(
   1149       bw, enc->transform_data, &enc->hash_chain, &enc->refs[0],
   1150       VP8LSubSampleSize(width, *best_bits),
   1151       VP8LSubSampleSize(height, *best_bits), quality, low_effort, enc->pic,
   1152       percent_range - percent_range / 2, percent);
   1153 }
   1154 
   1155 // -----------------------------------------------------------------------------
   1156 
   1157 static int WriteRiffHeader(const WebPPicture* const pic, size_t riff_size,
   1158                            size_t vp8l_size) {
   1159   uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
   1160     'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
   1161     'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE,
   1162   };
   1163   PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
   1164   PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
   1165   return pic->writer(riff, sizeof(riff), pic);
   1166 }
   1167 
   1168 static int WriteImageSize(const WebPPicture* const pic,
   1169                           VP8LBitWriter* const bw) {
   1170   const int width = pic->width - 1;
   1171   const int height = pic->height - 1;
   1172   assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
   1173 
   1174   VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS);
   1175   VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS);
   1176   return !bw->error;
   1177 }
   1178 
   1179 static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
   1180   VP8LPutBits(bw, has_alpha, 1);
   1181   VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS);
   1182   return !bw->error;
   1183 }
   1184 
   1185 static int WriteImage(const WebPPicture* const pic, VP8LBitWriter* const bw,
   1186                       size_t* const coded_size) {
   1187   const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
   1188   const size_t webpll_size = VP8LBitWriterNumBytes(bw);
   1189   const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
   1190   const size_t pad = vp8l_size & 1;
   1191   const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
   1192   *coded_size = 0;
   1193 
   1194   if (bw->error) {
   1195     return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1196   }
   1197 
   1198   if (!WriteRiffHeader(pic, riff_size, vp8l_size) ||
   1199       !pic->writer(webpll_data, webpll_size, pic)) {
   1200     return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
   1201   }
   1202 
   1203   if (pad) {
   1204     const uint8_t pad_byte[1] = { 0 };
   1205     if (!pic->writer(pad_byte, 1, pic)) {
   1206       return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
   1207     }
   1208   }
   1209   *coded_size = CHUNK_HEADER_SIZE + riff_size;
   1210   return 1;
   1211 }
   1212 
   1213 // -----------------------------------------------------------------------------
   1214 
   1215 static void ClearTransformBuffer(VP8LEncoder* const enc) {
   1216   WebPSafeFree(enc->transform_mem);
   1217   enc->transform_mem = NULL;
   1218   enc->transform_mem_size = 0;
   1219 }
   1220 
   1221 // Allocates the memory for argb (W x H) buffer, 2 rows of context for
   1222 // prediction and transform data.
   1223 // Flags influencing the memory allocated:
   1224 //  enc->transform_bits
   1225 //  enc->use_predict, enc->use_cross_color
   1226 static int AllocateTransformBuffer(VP8LEncoder* const enc, int width,
   1227                                    int height) {
   1228   const uint64_t image_size = (uint64_t)width * height;
   1229   // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra
   1230   // pixel in each, plus 2 regular scanlines of bytes.
   1231   // TODO(skal): Clean up by using arithmetic in bytes instead of words.
   1232   const uint64_t argb_scratch_size =
   1233       enc->use_predict ? (width + 1) * 2 + (width * 2 + sizeof(uint32_t) - 1) /
   1234                                                sizeof(uint32_t)
   1235                         : 0;
   1236   const uint64_t transform_data_size =
   1237       (enc->use_predict || enc->use_cross_color)
   1238           ? (uint64_t)VP8LSubSampleSize(width, MIN_TRANSFORM_BITS) *
   1239                 VP8LSubSampleSize(height, MIN_TRANSFORM_BITS)
   1240           : 0;
   1241   const uint64_t max_alignment_in_words =
   1242       (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t);
   1243   const uint64_t mem_size = image_size + max_alignment_in_words +
   1244                             argb_scratch_size + max_alignment_in_words +
   1245                             transform_data_size;
   1246   uint32_t* mem = enc->transform_mem;
   1247   if (mem == NULL || mem_size > enc->transform_mem_size) {
   1248     ClearTransformBuffer(enc);
   1249     mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem));
   1250     if (mem == NULL) {
   1251       return WebPEncodingSetError(enc->pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1252     }
   1253     enc->transform_mem = mem;
   1254     enc->transform_mem_size = (size_t)mem_size;
   1255     enc->argb_content = kEncoderNone;
   1256   }
   1257   enc->argb = mem;
   1258   mem = (uint32_t*)WEBP_ALIGN(mem + image_size);
   1259   enc->argb_scratch = mem;
   1260   mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size);
   1261   enc->transform_data = mem;
   1262 
   1263   enc->current_width = width;
   1264   return 1;
   1265 }
   1266 
   1267 static int MakeInputImageCopy(VP8LEncoder* const enc) {
   1268   const WebPPicture* const picture = enc->pic;
   1269   const int width = picture->width;
   1270   const int height = picture->height;
   1271 
   1272   if (!AllocateTransformBuffer(enc, width, height)) return 0;
   1273   if (enc->argb_content == kEncoderARGB) return 1;
   1274 
   1275   {
   1276     uint32_t* dst = enc->argb;
   1277     const uint32_t* src = picture->argb;
   1278     int y;
   1279     for (y = 0; y < height; ++y) {
   1280       memcpy(dst, src, width * sizeof(*dst));
   1281       dst += width;
   1282       src += picture->argb_stride;
   1283     }
   1284   }
   1285   enc->argb_content = kEncoderARGB;
   1286   assert(enc->current_width == width);
   1287   return 1;
   1288 }
   1289 
   1290 // -----------------------------------------------------------------------------
   1291 
   1292 #define APPLY_PALETTE_GREEDY_MAX 4
   1293 
   1294 static WEBP_INLINE uint32_t SearchColorGreedy(const uint32_t palette[],
   1295                                               int palette_size,
   1296                                               uint32_t color) {
   1297   (void)palette_size;
   1298   assert(palette_size < APPLY_PALETTE_GREEDY_MAX);
   1299   assert(3 == APPLY_PALETTE_GREEDY_MAX - 1);
   1300   if (color == palette[0]) return 0;
   1301   if (color == palette[1]) return 1;
   1302   if (color == palette[2]) return 2;
   1303   return 3;
   1304 }
   1305 
   1306 static WEBP_INLINE uint32_t ApplyPaletteHash0(uint32_t color) {
   1307   // Focus on the green color.
   1308   return (color >> 8) & 0xff;
   1309 }
   1310 
   1311 #define PALETTE_INV_SIZE_BITS 11
   1312 #define PALETTE_INV_SIZE (1 << PALETTE_INV_SIZE_BITS)
   1313 
   1314 static WEBP_INLINE uint32_t ApplyPaletteHash1(uint32_t color) {
   1315   // Forget about alpha.
   1316   return ((uint32_t)((color & 0x00ffffffu) * 4222244071ull)) >>
   1317          (32 - PALETTE_INV_SIZE_BITS);
   1318 }
   1319 
   1320 static WEBP_INLINE uint32_t ApplyPaletteHash2(uint32_t color) {
   1321   // Forget about alpha.
   1322   return ((uint32_t)((color & 0x00ffffffu) * ((1ull << 31) - 1))) >>
   1323          (32 - PALETTE_INV_SIZE_BITS);
   1324 }
   1325 
   1326 // Use 1 pixel cache for ARGB pixels.
   1327 #define APPLY_PALETTE_FOR(COLOR_INDEX) do {         \
   1328   uint32_t prev_pix = palette[0];                   \
   1329   uint32_t prev_idx = 0;                            \
   1330   for (y = 0; y < height; ++y) {                    \
   1331     for (x = 0; x < width; ++x) {                   \
   1332       const uint32_t pix = src[x];                  \
   1333       if (pix != prev_pix) {                        \
   1334         prev_idx = COLOR_INDEX;                     \
   1335         prev_pix = pix;                             \
   1336       }                                             \
   1337       tmp_row[x] = prev_idx;                        \
   1338     }                                               \
   1339     VP8LBundleColorMap(tmp_row, width, xbits, dst); \
   1340     src += src_stride;                              \
   1341     dst += dst_stride;                              \
   1342   }                                                 \
   1343 } while (0)
   1344 
   1345 // Remap argb values in src[] to packed palettes entries in dst[]
   1346 // using 'row' as a temporary buffer of size 'width'.
   1347 // We assume that all src[] values have a corresponding entry in the palette.
   1348 // Note: src[] can be the same as dst[]
   1349 static int ApplyPalette(const uint32_t* src, uint32_t src_stride, uint32_t* dst,
   1350                         uint32_t dst_stride, const uint32_t* palette,
   1351                         int palette_size, int width, int height, int xbits,
   1352                         const WebPPicture* const pic) {
   1353   // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be
   1354   // made to work in-place.
   1355   uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row));
   1356   int x, y;
   1357 
   1358   if (tmp_row == NULL) {
   1359     return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1360   }
   1361 
   1362   if (palette_size < APPLY_PALETTE_GREEDY_MAX) {
   1363     APPLY_PALETTE_FOR(SearchColorGreedy(palette, palette_size, pix));
   1364   } else {
   1365     int i, j;
   1366     uint16_t buffer[PALETTE_INV_SIZE];
   1367     uint32_t (*const hash_functions[])(uint32_t) = {
   1368         ApplyPaletteHash0, ApplyPaletteHash1, ApplyPaletteHash2
   1369     };
   1370 
   1371     // Try to find a perfect hash function able to go from a color to an index
   1372     // within 1 << PALETTE_INV_SIZE_BITS in order to build a hash map to go
   1373     // from color to index in palette.
   1374     for (i = 0; i < 3; ++i) {
   1375       int use_LUT = 1;
   1376       // Set each element in buffer to max uint16_t.
   1377       memset(buffer, 0xff, sizeof(buffer));
   1378       for (j = 0; j < palette_size; ++j) {
   1379         const uint32_t ind = hash_functions[i](palette[j]);
   1380         if (buffer[ind] != 0xffffu) {
   1381           use_LUT = 0;
   1382           break;
   1383         } else {
   1384           buffer[ind] = j;
   1385         }
   1386       }
   1387       if (use_LUT) break;
   1388     }
   1389 
   1390     if (i == 0) {
   1391       APPLY_PALETTE_FOR(buffer[ApplyPaletteHash0(pix)]);
   1392     } else if (i == 1) {
   1393       APPLY_PALETTE_FOR(buffer[ApplyPaletteHash1(pix)]);
   1394     } else if (i == 2) {
   1395       APPLY_PALETTE_FOR(buffer[ApplyPaletteHash2(pix)]);
   1396     } else {
   1397       uint32_t idx_map[MAX_PALETTE_SIZE];
   1398       uint32_t palette_sorted[MAX_PALETTE_SIZE];
   1399       PrepareMapToPalette(palette, palette_size, palette_sorted, idx_map);
   1400       APPLY_PALETTE_FOR(
   1401           idx_map[SearchColorNoIdx(palette_sorted, pix, palette_size)]);
   1402     }
   1403   }
   1404   WebPSafeFree(tmp_row);
   1405   return 1;
   1406 }
   1407 #undef APPLY_PALETTE_FOR
   1408 #undef PALETTE_INV_SIZE_BITS
   1409 #undef PALETTE_INV_SIZE
   1410 #undef APPLY_PALETTE_GREEDY_MAX
   1411 
   1412 // Note: Expects "enc->palette" to be set properly.
   1413 static int MapImageFromPalette(VP8LEncoder* const enc) {
   1414   const WebPPicture* const pic = enc->pic;
   1415   const int width = pic->width;
   1416   const int height = pic->height;
   1417   const uint32_t* const palette = enc->palette;
   1418   const int palette_size = enc->palette_size;
   1419   int xbits;
   1420 
   1421   // Replace each input pixel by corresponding palette index.
   1422   // This is done line by line.
   1423   if (palette_size <= 4) {
   1424     xbits = (palette_size <= 2) ? 3 : 2;
   1425   } else {
   1426     xbits = (palette_size <= 16) ? 1 : 0;
   1427   }
   1428 
   1429   if (!AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height)) {
   1430     return 0;
   1431   }
   1432   if (!ApplyPalette(pic->argb, pic->argb_stride, enc->argb,
   1433                     enc->current_width, palette, palette_size, width, height,
   1434                     xbits, pic)) {
   1435     return 0;
   1436   }
   1437   enc->argb_content = kEncoderPalette;
   1438   return 1;
   1439 }
   1440 
   1441 // Save palette[] to bitstream.
   1442 static int EncodePalette(VP8LBitWriter* const bw, int low_effort,
   1443                          VP8LEncoder* const enc, int percent_range,
   1444                          int* const percent) {
   1445   int i;
   1446   uint32_t tmp_palette[MAX_PALETTE_SIZE];
   1447   const int palette_size = enc->palette_size;
   1448   const uint32_t* const palette = enc->palette;
   1449   // If the last element is 0, do not store it and count on automatic palette
   1450   // 0-filling. This can only happen if there is no pixel packing, hence if
   1451   // there are strictly more than 16 colors (after 0 is removed).
   1452   const uint32_t encoded_palette_size =
   1453       (enc->palette[palette_size - 1] == 0 && palette_size > 17)
   1454           ? palette_size - 1
   1455           : palette_size;
   1456   VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
   1457   VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2);
   1458   assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE);
   1459   VP8LPutBits(bw, encoded_palette_size - 1, 8);
   1460   for (i = encoded_palette_size - 1; i >= 1; --i) {
   1461     tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
   1462   }
   1463   tmp_palette[0] = palette[0];
   1464   return EncodeImageNoHuffman(
   1465       bw, tmp_palette, &enc->hash_chain, &enc->refs[0], encoded_palette_size,
   1466       1, /*quality=*/20, low_effort, enc->pic, percent_range, percent);
   1467 }
   1468 
   1469 // -----------------------------------------------------------------------------
   1470 // VP8LEncoder
   1471 
   1472 static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
   1473                                    const WebPPicture* const picture) {
   1474   VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc));
   1475   if (enc == NULL) {
   1476     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1477     return NULL;
   1478   }
   1479   enc->config = config;
   1480   enc->pic = picture;
   1481   enc->argb_content = kEncoderNone;
   1482 
   1483   VP8LEncDspInit();
   1484 
   1485   return enc;
   1486 }
   1487 
   1488 static void VP8LEncoderDelete(VP8LEncoder* enc) {
   1489   if (enc != NULL) {
   1490     int i;
   1491     VP8LHashChainClear(&enc->hash_chain);
   1492     for (i = 0; i < 4; ++i) VP8LBackwardRefsClear(&enc->refs[i]);
   1493     ClearTransformBuffer(enc);
   1494     WebPSafeFree(enc);
   1495   }
   1496 }
   1497 
   1498 // -----------------------------------------------------------------------------
   1499 // Main call
   1500 
   1501 typedef struct {
   1502   const WebPConfig* config;
   1503   const WebPPicture* picture;
   1504   VP8LBitWriter* bw;
   1505   VP8LEncoder* enc;
   1506   CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX];
   1507   int num_crunch_configs;
   1508   int red_and_blue_always_zero;
   1509   WebPAuxStats* stats;
   1510 } StreamEncodeContext;
   1511 
   1512 static int EncodeStreamHook(void* input, void* data2) {
   1513   StreamEncodeContext* const params = (StreamEncodeContext*)input;
   1514   const WebPConfig* const config = params->config;
   1515   const WebPPicture* const picture = params->picture;
   1516   VP8LBitWriter* const bw = params->bw;
   1517   VP8LEncoder* const enc = params->enc;
   1518   const CrunchConfig* const crunch_configs = params->crunch_configs;
   1519   const int num_crunch_configs = params->num_crunch_configs;
   1520   const int red_and_blue_always_zero = params->red_and_blue_always_zero;
   1521 #if !defined(WEBP_DISABLE_STATS)
   1522   WebPAuxStats* const stats = params->stats;
   1523 #endif
   1524   const int quality = (int)config->quality;
   1525   const int low_effort = (config->method == 0);
   1526 #if (WEBP_NEAR_LOSSLESS == 1)
   1527   const int width = picture->width;
   1528 #endif
   1529   const int height = picture->height;
   1530   const size_t byte_position = VP8LBitWriterNumBytes(bw);
   1531   int percent = 2;  // for WebPProgressHook
   1532 #if (WEBP_NEAR_LOSSLESS == 1)
   1533   int use_near_lossless = 0;
   1534 #endif
   1535   int hdr_size = 0;
   1536   int data_size = 0;
   1537   int idx;
   1538   size_t best_size = ~(size_t)0;
   1539   VP8LBitWriter bw_init = *bw, bw_best;
   1540   (void)data2;
   1541 
   1542   if (!VP8LBitWriterInit(&bw_best, 0) ||
   1543       (num_crunch_configs > 1 && !VP8LBitWriterClone(bw, &bw_best))) {
   1544     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1545     goto Error;
   1546   }
   1547 
   1548   for (idx = 0; idx < num_crunch_configs; ++idx) {
   1549     const int entropy_idx = crunch_configs[idx].entropy_idx;
   1550     int remaining_percent = 97 / num_crunch_configs, percent_range;
   1551     int predictor_transform_bits = 0, cross_color_transform_bits = 0;
   1552     enc->use_palette =
   1553         (entropy_idx == kPalette) || (entropy_idx == kPaletteAndSpatial);
   1554     enc->use_subtract_green =
   1555         (entropy_idx == kSubGreen) || (entropy_idx == kSpatialSubGreen);
   1556     enc->use_predict = (entropy_idx == kSpatial) ||
   1557                        (entropy_idx == kSpatialSubGreen) ||
   1558                        (entropy_idx == kPaletteAndSpatial);
   1559     // When using a palette, R/B==0, hence no need to test for cross-color.
   1560     if (low_effort || enc->use_palette) {
   1561       enc->use_cross_color = 0;
   1562     } else {
   1563       enc->use_cross_color = red_and_blue_always_zero ? 0 : enc->use_predict;
   1564     }
   1565     // Reset any parameter in the encoder that is set in the previous iteration.
   1566     enc->cache_bits = 0;
   1567     VP8LBackwardRefsClear(&enc->refs[0]);
   1568     VP8LBackwardRefsClear(&enc->refs[1]);
   1569 
   1570 #if (WEBP_NEAR_LOSSLESS == 1)
   1571     // Apply near-lossless preprocessing.
   1572     use_near_lossless = (config->near_lossless < 100) && !enc->use_palette &&
   1573                         !enc->use_predict;
   1574     if (use_near_lossless) {
   1575       if (!AllocateTransformBuffer(enc, width, height)) goto Error;
   1576       if ((enc->argb_content != kEncoderNearLossless) &&
   1577           !VP8ApplyNearLossless(picture, config->near_lossless, enc->argb)) {
   1578         WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1579         goto Error;
   1580       }
   1581       enc->argb_content = kEncoderNearLossless;
   1582     } else {
   1583       enc->argb_content = kEncoderNone;
   1584     }
   1585 #else
   1586     enc->argb_content = kEncoderNone;
   1587 #endif
   1588 
   1589     // Encode palette
   1590     if (enc->use_palette) {
   1591       if (!PaletteSort(crunch_configs[idx].palette_sorting_type, enc->pic,
   1592                        enc->palette_sorted, enc->palette_size,
   1593                        enc->palette)) {
   1594         WebPEncodingSetError(enc->pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1595         goto Error;
   1596       }
   1597       percent_range = remaining_percent / 4;
   1598       if (!EncodePalette(bw, low_effort, enc, percent_range, &percent)) {
   1599         goto Error;
   1600       }
   1601       remaining_percent -= percent_range;
   1602       if (!MapImageFromPalette(enc)) goto Error;
   1603       // If using a color cache, do not have it bigger than the number of
   1604       // colors.
   1605       if (enc->palette_size < (1 << MAX_COLOR_CACHE_BITS)) {
   1606         enc->cache_bits = BitsLog2Floor(enc->palette_size) + 1;
   1607       }
   1608     }
   1609     // In case image is not packed.
   1610     if (enc->argb_content != kEncoderNearLossless &&
   1611         enc->argb_content != kEncoderPalette) {
   1612       if (!MakeInputImageCopy(enc)) goto Error;
   1613     }
   1614 
   1615     // -------------------------------------------------------------------------
   1616     // Apply transforms and write transform data.
   1617 
   1618     if (enc->use_subtract_green) {
   1619       ApplySubtractGreen(enc, enc->current_width, height, bw);
   1620     }
   1621 
   1622     if (enc->use_predict) {
   1623       percent_range = remaining_percent / 3;
   1624       if (!ApplyPredictFilter(enc, enc->current_width, height, quality,
   1625                               low_effort, enc->use_subtract_green, bw,
   1626                               percent_range, &percent,
   1627                               &predictor_transform_bits)) {
   1628         goto Error;
   1629       }
   1630       remaining_percent -= percent_range;
   1631     }
   1632 
   1633     if (enc->use_cross_color) {
   1634       percent_range = remaining_percent / 2;
   1635       if (!ApplyCrossColorFilter(enc, enc->current_width, height, quality,
   1636                                  low_effort, bw, percent_range, &percent,
   1637                                  &cross_color_transform_bits)) {
   1638         goto Error;
   1639       }
   1640       remaining_percent -= percent_range;
   1641     }
   1642 
   1643     VP8LPutBits(bw, !TRANSFORM_PRESENT, 1);  // No more transforms.
   1644 
   1645     // -------------------------------------------------------------------------
   1646     // Encode and write the transformed image.
   1647     if (!EncodeImageInternal(
   1648             bw, enc->argb, &enc->hash_chain, enc->refs, enc->current_width,
   1649             height, quality, low_effort, &crunch_configs[idx],
   1650             &enc->cache_bits, enc->histo_bits, byte_position, &hdr_size,
   1651             &data_size, picture, remaining_percent, &percent)) {
   1652       goto Error;
   1653     }
   1654 
   1655     // If we are better than what we already have.
   1656     if (VP8LBitWriterNumBytes(bw) < best_size) {
   1657       best_size = VP8LBitWriterNumBytes(bw);
   1658       // Store the BitWriter.
   1659       VP8LBitWriterSwap(bw, &bw_best);
   1660 #if !defined(WEBP_DISABLE_STATS)
   1661       // Update the stats.
   1662       if (stats != NULL) {
   1663         stats->lossless_features = 0;
   1664         if (enc->use_predict) stats->lossless_features |= 1;
   1665         if (enc->use_cross_color) stats->lossless_features |= 2;
   1666         if (enc->use_subtract_green) stats->lossless_features |= 4;
   1667         if (enc->use_palette) stats->lossless_features |= 8;
   1668         stats->histogram_bits = enc->histo_bits;
   1669         stats->transform_bits = predictor_transform_bits;
   1670         stats->cross_color_transform_bits = cross_color_transform_bits;
   1671         stats->cache_bits = enc->cache_bits;
   1672         stats->palette_size = enc->palette_size;
   1673         stats->lossless_size = (int)(best_size - byte_position);
   1674         stats->lossless_hdr_size = hdr_size;
   1675         stats->lossless_data_size = data_size;
   1676       }
   1677 #endif
   1678     }
   1679     // Reset the bit writer for the following iteration if any.
   1680     if (num_crunch_configs > 1) VP8LBitWriterReset(&bw_init, bw);
   1681   }
   1682   VP8LBitWriterSwap(&bw_best, bw);
   1683 
   1684  Error:
   1685   VP8LBitWriterWipeOut(&bw_best);
   1686   // The hook should return false in case of error.
   1687   return (params->picture->error_code == VP8_ENC_OK);
   1688 }
   1689 
   1690 int VP8LEncodeStream(const WebPConfig* const config,
   1691                      const WebPPicture* const picture,
   1692                      VP8LBitWriter* const bw_main) {
   1693   VP8LEncoder* const enc_main = VP8LEncoderNew(config, picture);
   1694   VP8LEncoder* enc_side = NULL;
   1695   CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX];
   1696   int num_crunch_configs_main, num_crunch_configs_side = 0;
   1697   int idx;
   1698   int red_and_blue_always_zero = 0;
   1699   WebPWorker worker_main, worker_side;
   1700   StreamEncodeContext params_main, params_side;
   1701   // The main thread uses picture->stats, the side thread uses stats_side.
   1702   WebPAuxStats stats_side;
   1703   VP8LBitWriter bw_side;
   1704   WebPPicture picture_side;
   1705   const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface();
   1706   int ok_main;
   1707 
   1708   if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) {
   1709     VP8LEncoderDelete(enc_main);
   1710     return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1711   }
   1712 
   1713   // Avoid "garbage value" error from Clang's static analysis tool.
   1714   if (!WebPPictureInit(&picture_side)) {
   1715     goto Error;
   1716   }
   1717 
   1718   // Analyze image (entropy, num_palettes etc)
   1719   if (!EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main,
   1720                       &red_and_blue_always_zero) ||
   1721       !EncoderInit(enc_main)) {
   1722     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1723     goto Error;
   1724   }
   1725 
   1726   // Split the configs between the main and side threads (if any).
   1727   if (config->thread_level > 0) {
   1728     num_crunch_configs_side = num_crunch_configs_main / 2;
   1729     for (idx = 0; idx < num_crunch_configs_side; ++idx) {
   1730       params_side.crunch_configs[idx] =
   1731           crunch_configs[num_crunch_configs_main - num_crunch_configs_side +
   1732                          idx];
   1733     }
   1734     params_side.num_crunch_configs = num_crunch_configs_side;
   1735   }
   1736   num_crunch_configs_main -= num_crunch_configs_side;
   1737   for (idx = 0; idx < num_crunch_configs_main; ++idx) {
   1738     params_main.crunch_configs[idx] = crunch_configs[idx];
   1739   }
   1740   params_main.num_crunch_configs = num_crunch_configs_main;
   1741 
   1742   // Fill in the parameters for the thread workers.
   1743   {
   1744     const int params_size = (num_crunch_configs_side > 0) ? 2 : 1;
   1745     for (idx = 0; idx < params_size; ++idx) {
   1746       // Create the parameters for each worker.
   1747       WebPWorker* const worker = (idx == 0) ? &worker_main : &worker_side;
   1748       StreamEncodeContext* const param =
   1749           (idx == 0) ? &params_main : &params_side;
   1750       param->config = config;
   1751       param->red_and_blue_always_zero = red_and_blue_always_zero;
   1752       if (idx == 0) {
   1753         param->picture = picture;
   1754         param->stats = picture->stats;
   1755         param->bw = bw_main;
   1756         param->enc = enc_main;
   1757       } else {
   1758         // Create a side picture (error_code is not thread-safe).
   1759         if (!WebPPictureView(picture, /*left=*/0, /*top=*/0, picture->width,
   1760                              picture->height, &picture_side)) {
   1761           assert(0);
   1762         }
   1763         picture_side.progress_hook = NULL;  // Progress hook is not thread-safe.
   1764         param->picture = &picture_side;  // No need to free a view afterwards.
   1765         param->stats = (picture->stats == NULL) ? NULL : &stats_side;
   1766         // Create a side bit writer.
   1767         if (!VP8LBitWriterClone(bw_main, &bw_side)) {
   1768           WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1769           goto Error;
   1770         }
   1771         param->bw = &bw_side;
   1772         // Create a side encoder.
   1773         enc_side = VP8LEncoderNew(config, &picture_side);
   1774         if (enc_side == NULL || !EncoderInit(enc_side)) {
   1775           WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1776           goto Error;
   1777         }
   1778         // Copy the values that were computed for the main encoder.
   1779         enc_side->histo_bits = enc_main->histo_bits;
   1780         enc_side->predictor_transform_bits =
   1781             enc_main->predictor_transform_bits;
   1782         enc_side->cross_color_transform_bits =
   1783             enc_main->cross_color_transform_bits;
   1784         enc_side->palette_size = enc_main->palette_size;
   1785         memcpy(enc_side->palette, enc_main->palette,
   1786                sizeof(enc_main->palette));
   1787         memcpy(enc_side->palette_sorted, enc_main->palette_sorted,
   1788                sizeof(enc_main->palette_sorted));
   1789         param->enc = enc_side;
   1790       }
   1791       // Create the workers.
   1792       worker_interface->Init(worker);
   1793       worker->data1 = param;
   1794       worker->data2 = NULL;
   1795       worker->hook = EncodeStreamHook;
   1796     }
   1797   }
   1798 
   1799   // Start the second thread if needed.
   1800   if (num_crunch_configs_side != 0) {
   1801     if (!worker_interface->Reset(&worker_side)) {
   1802       WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1803       goto Error;
   1804     }
   1805 #if !defined(WEBP_DISABLE_STATS)
   1806     // This line is here and not in the param initialization above to remove a
   1807     // Clang static analyzer warning.
   1808     if (picture->stats != NULL) {
   1809       memcpy(&stats_side, picture->stats, sizeof(stats_side));
   1810     }
   1811 #endif
   1812     worker_interface->Launch(&worker_side);
   1813   }
   1814   // Execute the main thread.
   1815   worker_interface->Execute(&worker_main);
   1816   ok_main = worker_interface->Sync(&worker_main);
   1817   worker_interface->End(&worker_main);
   1818   if (num_crunch_configs_side != 0) {
   1819     // Wait for the second thread.
   1820     const int ok_side = worker_interface->Sync(&worker_side);
   1821     worker_interface->End(&worker_side);
   1822     if (!ok_main || !ok_side) {
   1823       if (picture->error_code == VP8_ENC_OK) {
   1824         assert(picture_side.error_code != VP8_ENC_OK);
   1825         WebPEncodingSetError(picture, picture_side.error_code);
   1826       }
   1827       goto Error;
   1828     }
   1829     if (VP8LBitWriterNumBytes(&bw_side) < VP8LBitWriterNumBytes(bw_main)) {
   1830       VP8LBitWriterSwap(bw_main, &bw_side);
   1831 #if !defined(WEBP_DISABLE_STATS)
   1832       if (picture->stats != NULL) {
   1833         memcpy(picture->stats, &stats_side, sizeof(*picture->stats));
   1834       }
   1835 #endif
   1836     }
   1837   }
   1838 
   1839  Error:
   1840   VP8LBitWriterWipeOut(&bw_side);
   1841   VP8LEncoderDelete(enc_main);
   1842   VP8LEncoderDelete(enc_side);
   1843   return (picture->error_code == VP8_ENC_OK);
   1844 }
   1845 
   1846 #undef CRUNCH_CONFIGS_MAX
   1847 #undef CRUNCH_SUBCONFIGS_MAX
   1848 
   1849 int VP8LEncodeImage(const WebPConfig* const config,
   1850                     const WebPPicture* const picture) {
   1851   int width, height;
   1852   int has_alpha;
   1853   size_t coded_size;
   1854   int percent = 0;
   1855   int initial_size;
   1856   VP8LBitWriter bw;
   1857 
   1858   if (picture == NULL) return 0;
   1859 
   1860   if (config == NULL || picture->argb == NULL) {
   1861     return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
   1862   }
   1863 
   1864   width = picture->width;
   1865   height = picture->height;
   1866   // Initialize BitWriter with size corresponding to 16 bpp to photo images and
   1867   // 8 bpp for graphical images.
   1868   initial_size = (config->image_hint == WEBP_HINT_GRAPH) ?
   1869       width * height : width * height * 2;
   1870   if (!VP8LBitWriterInit(&bw, initial_size)) {
   1871     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1872     goto Error;
   1873   }
   1874 
   1875   if (!WebPReportProgress(picture, 1, &percent)) {
   1876  UserAbort:
   1877     WebPEncodingSetError(picture, VP8_ENC_ERROR_USER_ABORT);
   1878     goto Error;
   1879   }
   1880   // Reset stats (for pure lossless coding)
   1881   if (picture->stats != NULL) {
   1882     WebPAuxStats* const stats = picture->stats;
   1883     memset(stats, 0, sizeof(*stats));
   1884     stats->PSNR[0] = 99.f;
   1885     stats->PSNR[1] = 99.f;
   1886     stats->PSNR[2] = 99.f;
   1887     stats->PSNR[3] = 99.f;
   1888     stats->PSNR[4] = 99.f;
   1889   }
   1890 
   1891   // Write image size.
   1892   if (!WriteImageSize(picture, &bw)) {
   1893     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1894     goto Error;
   1895   }
   1896 
   1897   has_alpha = WebPPictureHasTransparency(picture);
   1898   // Write the non-trivial Alpha flag and lossless version.
   1899   if (!WriteRealAlphaAndVersion(&bw, has_alpha)) {
   1900     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1901     goto Error;
   1902   }
   1903 
   1904   if (!WebPReportProgress(picture, 2, &percent)) goto UserAbort;
   1905 
   1906   // Encode main image stream.
   1907   if (!VP8LEncodeStream(config, picture, &bw)) goto Error;
   1908 
   1909   if (!WebPReportProgress(picture, 99, &percent)) goto UserAbort;
   1910 
   1911   // Finish the RIFF chunk.
   1912   if (!WriteImage(picture, &bw, &coded_size)) goto Error;
   1913 
   1914   if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort;
   1915 
   1916 #if !defined(WEBP_DISABLE_STATS)
   1917   // Save size.
   1918   if (picture->stats != NULL) {
   1919     picture->stats->coded_size += (int)coded_size;
   1920     picture->stats->lossless_size = (int)coded_size;
   1921   }
   1922 #endif
   1923 
   1924   if (picture->extra_info != NULL) {
   1925     const int mb_w = (width + 15) >> 4;
   1926     const int mb_h = (height + 15) >> 4;
   1927     memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info));
   1928   }
   1929 
   1930  Error:
   1931   if (bw.error) {
   1932     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1933   }
   1934   VP8LBitWriterWipeOut(&bw);
   1935   return (picture->error_code == VP8_ENC_OK);
   1936 }
   1937 
   1938 //------------------------------------------------------------------------------