Home | History | Annotate | Download | only in enc
      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 (at) gmail.com)
     13 //
     14 
     15 #include <assert.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 
     19 #include "./backward_references.h"
     20 #include "./vp8enci.h"
     21 #include "./vp8li.h"
     22 #include "../dsp/lossless.h"
     23 #include "../utils/bit_writer.h"
     24 #include "../utils/huffman_encode.h"
     25 #include "../utils/utils.h"
     26 #include "webp/format_constants.h"
     27 
     28 #define PALETTE_KEY_RIGHT_SHIFT   22  // Key for 1K buffer.
     29 #define MAX_HUFF_IMAGE_SIZE       (16 * 1024 * 1024)
     30 #define MAX_COLORS_FOR_GRAPH      64
     31 
     32 // -----------------------------------------------------------------------------
     33 // Palette
     34 
     35 static int CompareColors(const void* p1, const void* p2) {
     36   const uint32_t a = *(const uint32_t*)p1;
     37   const uint32_t b = *(const uint32_t*)p2;
     38   assert(a != b);
     39   return (a < b) ? -1 : 1;
     40 }
     41 
     42 // If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
     43 // creates a palette and returns true, else returns false.
     44 static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
     45                                    uint32_t palette[MAX_PALETTE_SIZE],
     46                                    int* const palette_size) {
     47   int i, x, y, key;
     48   int num_colors = 0;
     49   uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 };
     50   uint32_t colors[MAX_PALETTE_SIZE * 4];
     51   static const uint32_t kHashMul = 0x1e35a7bd;
     52   const uint32_t* argb = pic->argb;
     53   const int width = pic->width;
     54   const int height = pic->height;
     55   uint32_t last_pix = ~argb[0];   // so we're sure that last_pix != argb[0]
     56 
     57   for (y = 0; y < height; ++y) {
     58     for (x = 0; x < width; ++x) {
     59       if (argb[x] == last_pix) {
     60         continue;
     61       }
     62       last_pix = argb[x];
     63       key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT;
     64       while (1) {
     65         if (!in_use[key]) {
     66           colors[key] = last_pix;
     67           in_use[key] = 1;
     68           ++num_colors;
     69           if (num_colors > MAX_PALETTE_SIZE) {
     70             return 0;
     71           }
     72           break;
     73         } else if (colors[key] == last_pix) {
     74           // The color is already there.
     75           break;
     76         } else {
     77           // Some other color sits there.
     78           // Do linear conflict resolution.
     79           ++key;
     80           key &= (MAX_PALETTE_SIZE * 4 - 1);  // key mask for 1K buffer.
     81         }
     82       }
     83     }
     84     argb += pic->argb_stride;
     85   }
     86 
     87   // TODO(skal): could we reuse in_use[] to speed up EncodePalette()?
     88   num_colors = 0;
     89   for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) {
     90     if (in_use[i]) {
     91       palette[num_colors] = colors[i];
     92       ++num_colors;
     93     }
     94   }
     95 
     96   qsort(palette, num_colors, sizeof(*palette), CompareColors);
     97   *palette_size = num_colors;
     98   return 1;
     99 }
    100 
    101 static int AnalyzeEntropy(const uint32_t* argb,
    102                           int width, int height, int argb_stride,
    103                           double* const nonpredicted_bits,
    104                           double* const predicted_bits) {
    105   int x, y;
    106   const uint32_t* last_line = NULL;
    107   uint32_t last_pix = argb[0];    // so we're sure that pix_diff == 0
    108 
    109   VP8LHistogramSet* const histo_set = VP8LAllocateHistogramSet(2, 0);
    110   if (histo_set == NULL) return 0;
    111 
    112   for (y = 0; y < height; ++y) {
    113     for (x = 0; x < width; ++x) {
    114       const uint32_t pix = argb[x];
    115       const uint32_t pix_diff = VP8LSubPixels(pix, last_pix);
    116       if (pix_diff == 0) continue;
    117       if (last_line != NULL && pix == last_line[x]) {
    118         continue;
    119       }
    120       last_pix = pix;
    121       {
    122         const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix);
    123         const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff);
    124         VP8LHistogramAddSinglePixOrCopy(histo_set->histograms[0], &pix_token);
    125         VP8LHistogramAddSinglePixOrCopy(histo_set->histograms[1],
    126                                         &pix_diff_token);
    127       }
    128     }
    129     last_line = argb;
    130     argb += argb_stride;
    131   }
    132   *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(histo_set->histograms[0]);
    133   *predicted_bits = VP8LHistogramEstimateBitsBulk(histo_set->histograms[1]);
    134   VP8LFreeHistogramSet(histo_set);
    135   return 1;
    136 }
    137 
    138 static int AnalyzeAndInit(VP8LEncoder* const enc, WebPImageHint image_hint) {
    139   const WebPPicture* const pic = enc->pic_;
    140   const int width = pic->width;
    141   const int height = pic->height;
    142   const int pix_cnt = width * height;
    143   // we round the block size up, so we're guaranteed to have
    144   // at max MAX_REFS_BLOCK_PER_IMAGE blocks used:
    145   int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1;
    146   assert(pic != NULL && pic->argb != NULL);
    147 
    148   enc->use_palette_ =
    149       AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_);
    150 
    151   if (image_hint == WEBP_HINT_GRAPH) {
    152     if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) {
    153       enc->use_palette_ = 0;
    154     }
    155   }
    156 
    157   if (!enc->use_palette_) {
    158     if (image_hint == WEBP_HINT_PHOTO) {
    159       enc->use_predict_ = 1;
    160       enc->use_cross_color_ = 1;
    161     } else {
    162       double non_pred_entropy, pred_entropy;
    163       if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
    164                           &non_pred_entropy, &pred_entropy)) {
    165         return 0;
    166       }
    167       if (pred_entropy < 0.95 * non_pred_entropy) {
    168         enc->use_predict_ = 1;
    169         enc->use_cross_color_ = 1;
    170       }
    171     }
    172   }
    173   if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0;
    174 
    175   // palette-friendly input typically uses less literals
    176   //  -> reduce block size a bit
    177   if (enc->use_palette_) refs_block_size /= 2;
    178   VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size);
    179   VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size);
    180 
    181   return 1;
    182 }
    183 
    184 // Returns false in case of memory error.
    185 static int GetHuffBitLengthsAndCodes(
    186     const VP8LHistogramSet* const histogram_image,
    187     HuffmanTreeCode* const huffman_codes) {
    188   int i, k;
    189   int ok = 0;
    190   uint64_t total_length_size = 0;
    191   uint8_t* mem_buf = NULL;
    192   const int histogram_image_size = histogram_image->size;
    193   int max_num_symbols = 0;
    194   uint8_t* buf_rle = NULL;
    195   HuffmanTree* huff_tree = NULL;
    196 
    197   // Iterate over all histograms and get the aggregate number of codes used.
    198   for (i = 0; i < histogram_image_size; ++i) {
    199     const VP8LHistogram* const histo = histogram_image->histograms[i];
    200     HuffmanTreeCode* const codes = &huffman_codes[5 * i];
    201     for (k = 0; k < 5; ++k) {
    202       const int num_symbols =
    203           (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) :
    204           (k == 4) ? NUM_DISTANCE_CODES : 256;
    205       codes[k].num_symbols = num_symbols;
    206       total_length_size += num_symbols;
    207     }
    208   }
    209 
    210   // Allocate and Set Huffman codes.
    211   {
    212     uint16_t* codes;
    213     uint8_t* lengths;
    214     mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
    215                                        sizeof(*lengths) + sizeof(*codes));
    216     if (mem_buf == NULL) goto End;
    217 
    218     codes = (uint16_t*)mem_buf;
    219     lengths = (uint8_t*)&codes[total_length_size];
    220     for (i = 0; i < 5 * histogram_image_size; ++i) {
    221       const int bit_length = huffman_codes[i].num_symbols;
    222       huffman_codes[i].codes = codes;
    223       huffman_codes[i].code_lengths = lengths;
    224       codes += bit_length;
    225       lengths += bit_length;
    226       if (max_num_symbols < bit_length) {
    227         max_num_symbols = bit_length;
    228       }
    229     }
    230   }
    231 
    232   buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols);
    233   huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols,
    234                                            sizeof(*huff_tree));
    235   if (buf_rle == NULL || huff_tree == NULL) goto End;
    236 
    237   // Create Huffman trees.
    238   for (i = 0; i < histogram_image_size; ++i) {
    239     HuffmanTreeCode* const codes = &huffman_codes[5 * i];
    240     VP8LHistogram* const histo = histogram_image->histograms[i];
    241     VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0);
    242     VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1);
    243     VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2);
    244     VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3);
    245     VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4);
    246   }
    247   ok = 1;
    248  End:
    249   WebPSafeFree(huff_tree);
    250   WebPSafeFree(buf_rle);
    251   if (!ok) {
    252     WebPSafeFree(mem_buf);
    253     memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
    254   }
    255   return ok;
    256 }
    257 
    258 static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
    259     VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) {
    260   // RFC 1951 will calm you down if you are worried about this funny sequence.
    261   // This sequence is tuned from that, but more weighted for lower symbol count,
    262   // and more spiking histograms.
    263   static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = {
    264     17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    265   };
    266   int i;
    267   // Throw away trailing zeros:
    268   int codes_to_store = CODE_LENGTH_CODES;
    269   for (; codes_to_store > 4; --codes_to_store) {
    270     if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
    271       break;
    272     }
    273   }
    274   VP8LWriteBits(bw, 4, codes_to_store - 4);
    275   for (i = 0; i < codes_to_store; ++i) {
    276     VP8LWriteBits(bw, 3, code_length_bitdepth[kStorageOrder[i]]);
    277   }
    278 }
    279 
    280 static void ClearHuffmanTreeIfOnlyOneSymbol(
    281     HuffmanTreeCode* const huffman_code) {
    282   int k;
    283   int count = 0;
    284   for (k = 0; k < huffman_code->num_symbols; ++k) {
    285     if (huffman_code->code_lengths[k] != 0) {
    286       ++count;
    287       if (count > 1) return;
    288     }
    289   }
    290   for (k = 0; k < huffman_code->num_symbols; ++k) {
    291     huffman_code->code_lengths[k] = 0;
    292     huffman_code->codes[k] = 0;
    293   }
    294 }
    295 
    296 static void StoreHuffmanTreeToBitMask(
    297     VP8LBitWriter* const bw,
    298     const HuffmanTreeToken* const tokens, const int num_tokens,
    299     const HuffmanTreeCode* const huffman_code) {
    300   int i;
    301   for (i = 0; i < num_tokens; ++i) {
    302     const int ix = tokens[i].code;
    303     const int extra_bits = tokens[i].extra_bits;
    304     VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]);
    305     switch (ix) {
    306       case 16:
    307         VP8LWriteBits(bw, 2, extra_bits);
    308         break;
    309       case 17:
    310         VP8LWriteBits(bw, 3, extra_bits);
    311         break;
    312       case 18:
    313         VP8LWriteBits(bw, 7, extra_bits);
    314         break;
    315     }
    316   }
    317 }
    318 
    319 // 'huff_tree' and 'tokens' are pre-alloacted buffers.
    320 static void StoreFullHuffmanCode(VP8LBitWriter* const bw,
    321                                  HuffmanTree* const huff_tree,
    322                                  HuffmanTreeToken* const tokens,
    323                                  const HuffmanTreeCode* const tree) {
    324   uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
    325   uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
    326   const int max_tokens = tree->num_symbols;
    327   int num_tokens;
    328   HuffmanTreeCode huffman_code;
    329   huffman_code.num_symbols = CODE_LENGTH_CODES;
    330   huffman_code.code_lengths = code_length_bitdepth;
    331   huffman_code.codes = code_length_bitdepth_symbols;
    332 
    333   VP8LWriteBits(bw, 1, 0);
    334   num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
    335   {
    336     uint32_t histogram[CODE_LENGTH_CODES] = { 0 };
    337     uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 };
    338     int i;
    339     for (i = 0; i < num_tokens; ++i) {
    340       ++histogram[tokens[i].code];
    341     }
    342 
    343     VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
    344   }
    345 
    346   StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth);
    347   ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code);
    348   {
    349     int trailing_zero_bits = 0;
    350     int trimmed_length = num_tokens;
    351     int write_trimmed_length;
    352     int length;
    353     int i = num_tokens;
    354     while (i-- > 0) {
    355       const int ix = tokens[i].code;
    356       if (ix == 0 || ix == 17 || ix == 18) {
    357         --trimmed_length;   // discount trailing zeros
    358         trailing_zero_bits += code_length_bitdepth[ix];
    359         if (ix == 17) {
    360           trailing_zero_bits += 3;
    361         } else if (ix == 18) {
    362           trailing_zero_bits += 7;
    363         }
    364       } else {
    365         break;
    366       }
    367     }
    368     write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12);
    369     length = write_trimmed_length ? trimmed_length : num_tokens;
    370     VP8LWriteBits(bw, 1, write_trimmed_length);
    371     if (write_trimmed_length) {
    372       const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1);
    373       const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2;
    374       VP8LWriteBits(bw, 3, nbitpairs - 1);
    375       assert(trimmed_length >= 2);
    376       VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2);
    377     }
    378     StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
    379   }
    380 }
    381 
    382 // 'huff_tree' and 'tokens' are pre-alloacted buffers.
    383 static void StoreHuffmanCode(VP8LBitWriter* const bw,
    384                              HuffmanTree* const huff_tree,
    385                              HuffmanTreeToken* const tokens,
    386                              const HuffmanTreeCode* const huffman_code) {
    387   int i;
    388   int count = 0;
    389   int symbols[2] = { 0, 0 };
    390   const int kMaxBits = 8;
    391   const int kMaxSymbol = 1 << kMaxBits;
    392 
    393   // Check whether it's a small tree.
    394   for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) {
    395     if (huffman_code->code_lengths[i] != 0) {
    396       if (count < 2) symbols[count] = i;
    397       ++count;
    398     }
    399   }
    400 
    401   if (count == 0) {   // emit minimal tree for empty cases
    402     // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
    403     VP8LWriteBits(bw, 4, 0x01);
    404   } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
    405     VP8LWriteBits(bw, 1, 1);  // Small tree marker to encode 1 or 2 symbols.
    406     VP8LWriteBits(bw, 1, count - 1);
    407     if (symbols[0] <= 1) {
    408       VP8LWriteBits(bw, 1, 0);  // Code bit for small (1 bit) symbol value.
    409       VP8LWriteBits(bw, 1, symbols[0]);
    410     } else {
    411       VP8LWriteBits(bw, 1, 1);
    412       VP8LWriteBits(bw, 8, symbols[0]);
    413     }
    414     if (count == 2) {
    415       VP8LWriteBits(bw, 8, symbols[1]);
    416     }
    417   } else {
    418     StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
    419   }
    420 }
    421 
    422 static void WriteHuffmanCode(VP8LBitWriter* const bw,
    423                              const HuffmanTreeCode* const code,
    424                              int code_index) {
    425   const int depth = code->code_lengths[code_index];
    426   const int symbol = code->codes[code_index];
    427   VP8LWriteBits(bw, depth, symbol);
    428 }
    429 
    430 static WebPEncodingError StoreImageToBitMask(
    431     VP8LBitWriter* const bw, int width, int histo_bits,
    432     VP8LBackwardRefs* const refs,
    433     const uint16_t* histogram_symbols,
    434     const HuffmanTreeCode* const huffman_codes) {
    435   // x and y trace the position in the image.
    436   int x = 0;
    437   int y = 0;
    438   const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
    439   VP8LRefsCursor c = VP8LRefsCursorInit(refs);
    440   while (VP8LRefsCursorOk(&c)) {
    441     const PixOrCopy* const v = c.cur_pos;
    442     const int histogram_ix = histogram_symbols[histo_bits ?
    443                                                (y >> histo_bits) * histo_xsize +
    444                                                (x >> histo_bits) : 0];
    445     const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix;
    446     if (PixOrCopyIsCacheIdx(v)) {
    447       const int code = PixOrCopyCacheIdx(v);
    448       const int literal_ix = 256 + NUM_LENGTH_CODES + code;
    449       WriteHuffmanCode(bw, codes, literal_ix);
    450     } else if (PixOrCopyIsLiteral(v)) {
    451       static const int order[] = { 1, 2, 0, 3 };
    452       int k;
    453       for (k = 0; k < 4; ++k) {
    454         const int code = PixOrCopyLiteral(v, order[k]);
    455         WriteHuffmanCode(bw, codes + k, code);
    456       }
    457     } else {
    458       int bits, n_bits;
    459       int code, distance;
    460 
    461       VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
    462       WriteHuffmanCode(bw, codes, 256 + code);
    463       VP8LWriteBits(bw, n_bits, bits);
    464 
    465       distance = PixOrCopyDistance(v);
    466       VP8LPrefixEncode(distance, &code, &n_bits, &bits);
    467       WriteHuffmanCode(bw, codes + 4, code);
    468       VP8LWriteBits(bw, n_bits, bits);
    469     }
    470     x += PixOrCopyLength(v);
    471     while (x >= width) {
    472       x -= width;
    473       ++y;
    474     }
    475     VP8LRefsCursorNext(&c);
    476   }
    477   return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK;
    478 }
    479 
    480 // Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
    481 static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
    482                                               const uint32_t* const argb,
    483                                               VP8LHashChain* const hash_chain,
    484                                               VP8LBackwardRefs refs_array[2],
    485                                               int width, int height,
    486                                               int quality) {
    487   int i;
    488   int max_tokens = 0;
    489   WebPEncodingError err = VP8_ENC_OK;
    490   VP8LBackwardRefs* refs;
    491   HuffmanTreeToken* tokens = NULL;
    492   HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } };
    493   const uint16_t histogram_symbols[1] = { 0 };    // only one tree, one symbol
    494   VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0);
    495   HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
    496         3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
    497   if (histogram_image == NULL || huff_tree == NULL) {
    498     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
    499     goto Error;
    500   }
    501 
    502   // Calculate backward references from ARGB image.
    503   refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, 1,
    504                                    hash_chain, refs_array);
    505   if (refs == NULL) {
    506     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
    507     goto Error;
    508   }
    509   // Build histogram image and symbols from backward references.
    510   VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
    511 
    512   // Create Huffman bit lengths and codes for each histogram image.
    513   assert(histogram_image->size == 1);
    514   if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
    515     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
    516     goto Error;
    517   }
    518 
    519   // No color cache, no Huffman image.
    520   VP8LWriteBits(bw, 1, 0);
    521 
    522   // Find maximum number of symbols for the huffman tree-set.
    523   for (i = 0; i < 5; ++i) {
    524     HuffmanTreeCode* const codes = &huffman_codes[i];
    525     if (max_tokens < codes->num_symbols) {
    526       max_tokens = codes->num_symbols;
    527     }
    528   }
    529 
    530   tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
    531   if (tokens == NULL) {
    532     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
    533     goto Error;
    534   }
    535 
    536   // Store Huffman codes.
    537   for (i = 0; i < 5; ++i) {
    538     HuffmanTreeCode* const codes = &huffman_codes[i];
    539     StoreHuffmanCode(bw, huff_tree, tokens, codes);
    540     ClearHuffmanTreeIfOnlyOneSymbol(codes);
    541   }
    542 
    543   // Store actual literals.
    544   err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols,
    545                             huffman_codes);
    546 
    547  Error:
    548   WebPSafeFree(tokens);
    549   WebPSafeFree(huff_tree);
    550   VP8LFreeHistogramSet(histogram_image);
    551   WebPSafeFree(huffman_codes[0].codes);
    552   return err;
    553 }
    554 
    555 static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw,
    556                                              const uint32_t* const argb,
    557                                              VP8LHashChain* const hash_chain,
    558                                              VP8LBackwardRefs refs_array[2],
    559                                              int width, int height, int quality,
    560                                              int cache_bits,
    561                                              int histogram_bits) {
    562   WebPEncodingError err = VP8_ENC_OK;
    563   const int use_2d_locality = 1;
    564   const int use_color_cache = (cache_bits > 0);
    565   const uint32_t histogram_image_xysize =
    566       VP8LSubSampleSize(width, histogram_bits) *
    567       VP8LSubSampleSize(height, histogram_bits);
    568   VP8LHistogramSet* histogram_image =
    569       VP8LAllocateHistogramSet(histogram_image_xysize, cache_bits);
    570   int histogram_image_size = 0;
    571   size_t bit_array_size = 0;
    572   HuffmanTree* huff_tree = NULL;
    573   HuffmanTreeToken* tokens = NULL;
    574   HuffmanTreeCode* huffman_codes = NULL;
    575   VP8LBackwardRefs refs;
    576   VP8LBackwardRefs* best_refs;
    577   uint16_t* const histogram_symbols =
    578       (uint16_t*)WebPSafeMalloc(histogram_image_xysize,
    579                                 sizeof(*histogram_symbols));
    580   assert(histogram_bits >= MIN_HUFFMAN_BITS);
    581   assert(histogram_bits <= MAX_HUFFMAN_BITS);
    582 
    583   VP8LBackwardRefsInit(&refs, refs_array[0].block_size_);
    584   if (histogram_image == NULL || histogram_symbols == NULL) {
    585     VP8LFreeHistogramSet(histogram_image);
    586     WebPSafeFree(histogram_symbols);
    587     return 0;
    588   }
    589 
    590   // 'best_refs' is the reference to the best backward refs and points to one
    591   // of refs_array[0] or refs_array[1].
    592   // Calculate backward references from ARGB image.
    593   best_refs = VP8LGetBackwardReferences(width, height, argb, quality,
    594                                         cache_bits, use_2d_locality,
    595                                         hash_chain, refs_array);
    596   if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) {
    597     goto Error;
    598   }
    599   // Build histogram image and symbols from backward references.
    600   if (!VP8LGetHistoImageSymbols(width, height, &refs,
    601                                 quality, histogram_bits, cache_bits,
    602                                 histogram_image,
    603                                 histogram_symbols)) {
    604     goto Error;
    605   }
    606   // Create Huffman bit lengths and codes for each histogram image.
    607   histogram_image_size = histogram_image->size;
    608   bit_array_size = 5 * histogram_image_size;
    609   huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
    610                                                    sizeof(*huffman_codes));
    611   if (huffman_codes == NULL ||
    612       !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
    613     goto Error;
    614   }
    615   // Free combined histograms.
    616   VP8LFreeHistogramSet(histogram_image);
    617   histogram_image = NULL;
    618 
    619   // Color Cache parameters.
    620   VP8LWriteBits(bw, 1, use_color_cache);
    621   if (use_color_cache) {
    622     VP8LWriteBits(bw, 4, cache_bits);
    623   }
    624 
    625   // Huffman image + meta huffman.
    626   {
    627     const int write_histogram_image = (histogram_image_size > 1);
    628     VP8LWriteBits(bw, 1, write_histogram_image);
    629     if (write_histogram_image) {
    630       uint32_t* const histogram_argb =
    631           (uint32_t*)WebPSafeMalloc(histogram_image_xysize,
    632                                     sizeof(*histogram_argb));
    633       int max_index = 0;
    634       uint32_t i;
    635       if (histogram_argb == NULL) goto Error;
    636       for (i = 0; i < histogram_image_xysize; ++i) {
    637         const int symbol_index = histogram_symbols[i] & 0xffff;
    638         histogram_argb[i] = 0xff000000 | (symbol_index << 8);
    639         if (symbol_index >= max_index) {
    640           max_index = symbol_index + 1;
    641         }
    642       }
    643       histogram_image_size = max_index;
    644 
    645       VP8LWriteBits(bw, 3, histogram_bits - 2);
    646       err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array,
    647                                  VP8LSubSampleSize(width, histogram_bits),
    648                                  VP8LSubSampleSize(height, histogram_bits),
    649                                  quality);
    650       WebPSafeFree(histogram_argb);
    651       if (err != VP8_ENC_OK) goto Error;
    652     }
    653   }
    654 
    655   // Store Huffman codes.
    656   {
    657     int i;
    658     int max_tokens = 0;
    659     huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES,
    660                                              sizeof(*huff_tree));
    661     if (huff_tree == NULL) goto Error;
    662     // Find maximum number of symbols for the huffman tree-set.
    663     for (i = 0; i < 5 * histogram_image_size; ++i) {
    664       HuffmanTreeCode* const codes = &huffman_codes[i];
    665       if (max_tokens < codes->num_symbols) {
    666         max_tokens = codes->num_symbols;
    667       }
    668     }
    669     tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens,
    670                                                sizeof(*tokens));
    671     if (tokens == NULL) goto Error;
    672     for (i = 0; i < 5 * histogram_image_size; ++i) {
    673       HuffmanTreeCode* const codes = &huffman_codes[i];
    674       StoreHuffmanCode(bw, huff_tree, tokens, codes);
    675       ClearHuffmanTreeIfOnlyOneSymbol(codes);
    676     }
    677   }
    678 
    679   // Store actual literals.
    680   err = StoreImageToBitMask(bw, width, histogram_bits, &refs,
    681                             histogram_symbols, huffman_codes);
    682 
    683  Error:
    684   WebPSafeFree(tokens);
    685   WebPSafeFree(huff_tree);
    686   VP8LFreeHistogramSet(histogram_image);
    687   VP8LBackwardRefsClear(&refs);
    688   if (huffman_codes != NULL) {
    689     WebPSafeFree(huffman_codes->codes);
    690     WebPSafeFree(huffman_codes);
    691   }
    692   WebPSafeFree(histogram_symbols);
    693   return err;
    694 }
    695 
    696 // -----------------------------------------------------------------------------
    697 // Transforms
    698 
    699 // Check if it would be a good idea to subtract green from red and blue. We
    700 // only impact entropy in red/blue components, don't bother to look at others.
    701 static WebPEncodingError EvalAndApplySubtractGreen(VP8LEncoder* const enc,
    702                                                    int width, int height,
    703                                                    VP8LBitWriter* const bw) {
    704   if (!enc->use_palette_) {
    705     int i;
    706     const uint32_t* const argb = enc->argb_;
    707     double bit_cost_before, bit_cost_after;
    708     // Allocate histogram with cache_bits = 1.
    709     VP8LHistogram* const histo = VP8LAllocateHistogram(1);
    710     if (histo == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
    711     for (i = 0; i < width * height; ++i) {
    712       const uint32_t c = argb[i];
    713       ++histo->red_[(c >> 16) & 0xff];
    714       ++histo->blue_[(c >> 0) & 0xff];
    715     }
    716     bit_cost_before = VP8LHistogramEstimateBits(histo);
    717 
    718     VP8LHistogramInit(histo, 1);
    719     for (i = 0; i < width * height; ++i) {
    720       const uint32_t c = argb[i];
    721       const int green = (c >> 8) & 0xff;
    722       ++histo->red_[((c >> 16) - green) & 0xff];
    723       ++histo->blue_[((c >> 0) - green) & 0xff];
    724     }
    725     bit_cost_after = VP8LHistogramEstimateBits(histo);
    726     VP8LFreeHistogram(histo);
    727 
    728     // Check if subtracting green yields low entropy.
    729     enc->use_subtract_green_ = (bit_cost_after < bit_cost_before);
    730     if (enc->use_subtract_green_) {
    731       VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
    732       VP8LWriteBits(bw, 2, SUBTRACT_GREEN);
    733       VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
    734     }
    735   }
    736   return VP8_ENC_OK;
    737 }
    738 
    739 static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
    740                                             int width, int height, int quality,
    741                                             VP8LBitWriter* const bw) {
    742   const int pred_bits = enc->transform_bits_;
    743   const int transform_width = VP8LSubSampleSize(width, pred_bits);
    744   const int transform_height = VP8LSubSampleSize(height, pred_bits);
    745 
    746   VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
    747                     enc->transform_data_);
    748   VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
    749   VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM);
    750   assert(pred_bits >= 2);
    751   VP8LWriteBits(bw, 3, pred_bits - 2);
    752   return EncodeImageNoHuffman(bw, enc->transform_data_,
    753                               (VP8LHashChain*)&enc->hash_chain_,
    754                               (VP8LBackwardRefs*)enc->refs_,  // cast const away
    755                               transform_width, transform_height,
    756                               quality);
    757 }
    758 
    759 static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc,
    760                                                int width, int height,
    761                                                int quality,
    762                                                VP8LBitWriter* const bw) {
    763   const int ccolor_transform_bits = enc->transform_bits_;
    764   const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
    765   const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
    766 
    767   VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality,
    768                           enc->argb_, enc->transform_data_);
    769   VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
    770   VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM);
    771   assert(ccolor_transform_bits >= 2);
    772   VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
    773   return EncodeImageNoHuffman(bw, enc->transform_data_,
    774                               (VP8LHashChain*)&enc->hash_chain_,
    775                               (VP8LBackwardRefs*)enc->refs_,  // cast const away
    776                               transform_width, transform_height,
    777                               quality);
    778 }
    779 
    780 // -----------------------------------------------------------------------------
    781 
    782 static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
    783                                          size_t riff_size, size_t vp8l_size) {
    784   uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
    785     'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
    786     'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE,
    787   };
    788   PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
    789   PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
    790   if (!pic->writer(riff, sizeof(riff), pic)) {
    791     return VP8_ENC_ERROR_BAD_WRITE;
    792   }
    793   return VP8_ENC_OK;
    794 }
    795 
    796 static int WriteImageSize(const WebPPicture* const pic,
    797                           VP8LBitWriter* const bw) {
    798   const int width = pic->width - 1;
    799   const int height = pic->height - 1;
    800   assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
    801 
    802   VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width);
    803   VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height);
    804   return !bw->error_;
    805 }
    806 
    807 static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
    808   VP8LWriteBits(bw, 1, has_alpha);
    809   VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION);
    810   return !bw->error_;
    811 }
    812 
    813 static WebPEncodingError WriteImage(const WebPPicture* const pic,
    814                                     VP8LBitWriter* const bw,
    815                                     size_t* const coded_size) {
    816   WebPEncodingError err = VP8_ENC_OK;
    817   const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
    818   const size_t webpll_size = VP8LBitWriterNumBytes(bw);
    819   const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
    820   const size_t pad = vp8l_size & 1;
    821   const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
    822 
    823   err = WriteRiffHeader(pic, riff_size, vp8l_size);
    824   if (err != VP8_ENC_OK) goto Error;
    825 
    826   if (!pic->writer(webpll_data, webpll_size, pic)) {
    827     err = VP8_ENC_ERROR_BAD_WRITE;
    828     goto Error;
    829   }
    830 
    831   if (pad) {
    832     const uint8_t pad_byte[1] = { 0 };
    833     if (!pic->writer(pad_byte, 1, pic)) {
    834       err = VP8_ENC_ERROR_BAD_WRITE;
    835       goto Error;
    836     }
    837   }
    838   *coded_size = CHUNK_HEADER_SIZE + riff_size;
    839   return VP8_ENC_OK;
    840 
    841  Error:
    842   return err;
    843 }
    844 
    845 // -----------------------------------------------------------------------------
    846 
    847 // Allocates the memory for argb (W x H) buffer, 2 rows of context for
    848 // prediction and transform data.
    849 static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
    850                                                  int width, int height) {
    851   WebPEncodingError err = VP8_ENC_OK;
    852   const int tile_size = 1 << enc->transform_bits_;
    853   const uint64_t image_size = width * height;
    854   const uint64_t argb_scratch_size = tile_size * width + width;
    855   const int transform_data_size =
    856       VP8LSubSampleSize(width, enc->transform_bits_) *
    857       VP8LSubSampleSize(height, enc->transform_bits_);
    858   const uint64_t total_size =
    859       image_size + argb_scratch_size + (uint64_t)transform_data_size;
    860   uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem));
    861   if (mem == NULL) {
    862     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
    863     goto Error;
    864   }
    865   enc->argb_ = mem;
    866   mem += image_size;
    867   enc->argb_scratch_ = mem;
    868   mem += argb_scratch_size;
    869   enc->transform_data_ = mem;
    870   enc->current_width_ = width;
    871 
    872  Error:
    873   return err;
    874 }
    875 
    876 static void ApplyPalette(uint32_t* src, uint32_t* dst,
    877                          uint32_t src_stride, uint32_t dst_stride,
    878                          const uint32_t* palette, int palette_size,
    879                          int width, int height, int xbits, uint8_t* row) {
    880   int i, x, y;
    881   int use_LUT = 1;
    882   for (i = 0; i < palette_size; ++i) {
    883     if ((palette[i] & 0xffff00ffu) != 0) {
    884       use_LUT = 0;
    885       break;
    886     }
    887   }
    888 
    889   if (use_LUT) {
    890     uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 };
    891     for (i = 0; i < palette_size; ++i) {
    892       const int color = (palette[i] >> 8) & 0xff;
    893       inv_palette[color] = i;
    894     }
    895     for (y = 0; y < height; ++y) {
    896       for (x = 0; x < width; ++x) {
    897         const int color = (src[x] >> 8) & 0xff;
    898         row[x] = inv_palette[color];
    899       }
    900       VP8LBundleColorMap(row, width, xbits, dst);
    901       src += src_stride;
    902       dst += dst_stride;
    903     }
    904   } else {
    905     // Use 1 pixel cache for ARGB pixels.
    906     uint32_t last_pix = palette[0];
    907     int last_idx = 0;
    908     for (y = 0; y < height; ++y) {
    909       for (x = 0; x < width; ++x) {
    910         const uint32_t pix = src[x];
    911         if (pix != last_pix) {
    912           for (i = 0; i < palette_size; ++i) {
    913             if (pix == palette[i]) {
    914               last_idx = i;
    915               last_pix = pix;
    916               break;
    917             }
    918           }
    919         }
    920         row[x] = last_idx;
    921       }
    922       VP8LBundleColorMap(row, width, xbits, dst);
    923       src += src_stride;
    924       dst += dst_stride;
    925     }
    926   }
    927 }
    928 
    929 // Note: Expects "enc->palette_" to be set properly.
    930 // Also, "enc->palette_" will be modified after this call and should not be used
    931 // later.
    932 static WebPEncodingError EncodePalette(VP8LBitWriter* const bw,
    933                                        VP8LEncoder* const enc, int quality) {
    934   WebPEncodingError err = VP8_ENC_OK;
    935   int i;
    936   const WebPPicture* const pic = enc->pic_;
    937   uint32_t* src = pic->argb;
    938   uint32_t* dst;
    939   const int width = pic->width;
    940   const int height = pic->height;
    941   uint32_t* const palette = enc->palette_;
    942   const int palette_size = enc->palette_size_;
    943   uint8_t* row = NULL;
    944   int xbits;
    945 
    946   // Replace each input pixel by corresponding palette index.
    947   // This is done line by line.
    948   if (palette_size <= 4) {
    949     xbits = (palette_size <= 2) ? 3 : 2;
    950   } else {
    951     xbits = (palette_size <= 16) ? 1 : 0;
    952   }
    953 
    954   err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
    955   if (err != VP8_ENC_OK) goto Error;
    956   dst = enc->argb_;
    957 
    958   row = (uint8_t*)WebPSafeMalloc(width, sizeof(*row));
    959   if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
    960 
    961   ApplyPalette(src, dst, pic->argb_stride, enc->current_width_,
    962                palette, palette_size, width, height, xbits, row);
    963 
    964   // Save palette to bitstream.
    965   VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
    966   VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM);
    967   assert(palette_size >= 1);
    968   VP8LWriteBits(bw, 8, palette_size - 1);
    969   for (i = palette_size - 1; i >= 1; --i) {
    970     palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
    971   }
    972   err = EncodeImageNoHuffman(bw, palette, &enc->hash_chain_, enc->refs_,
    973                              palette_size, 1, quality);
    974 
    975  Error:
    976   WebPSafeFree(row);
    977   return err;
    978 }
    979 
    980 // -----------------------------------------------------------------------------
    981 
    982 static int GetHistoBits(int method, int use_palette, int width, int height) {
    983   const int hist_size = VP8LGetHistogramSize(MAX_COLOR_CACHE_BITS);
    984   // Make tile size a function of encoding method (Range: 0 to 6).
    985   int histo_bits = (use_palette ? 9 : 7) - method;
    986   while (1) {
    987     const int huff_image_size = VP8LSubSampleSize(width, histo_bits) *
    988                                 VP8LSubSampleSize(height, histo_bits);
    989     if ((uint64_t)huff_image_size * hist_size <= MAX_HUFF_IMAGE_SIZE) break;
    990     ++histo_bits;
    991   }
    992   return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
    993          (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
    994 }
    995 
    996 static int GetTransformBits(int method, int histo_bits) {
    997   const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5;
    998   return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits;
    999 }
   1000 
   1001 static int GetCacheBits(float quality) {
   1002   return (quality <= 25.f) ? 0 : 7;
   1003 }
   1004 
   1005 static void FinishEncParams(VP8LEncoder* const enc) {
   1006   const WebPConfig* const config = enc->config_;
   1007   const WebPPicture* const pic = enc->pic_;
   1008   const int method = config->method;
   1009   const float quality = config->quality;
   1010   const int use_palette = enc->use_palette_;
   1011   enc->histo_bits_ = GetHistoBits(method, use_palette, pic->width, pic->height);
   1012   enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_);
   1013   enc->cache_bits_ = GetCacheBits(quality);
   1014 }
   1015 
   1016 // -----------------------------------------------------------------------------
   1017 // VP8LEncoder
   1018 
   1019 static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
   1020                                    const WebPPicture* const picture) {
   1021   VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc));
   1022   if (enc == NULL) {
   1023     WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   1024     return NULL;
   1025   }
   1026   enc->config_ = config;
   1027   enc->pic_ = picture;
   1028 
   1029   VP8LDspInit();
   1030 
   1031   return enc;
   1032 }
   1033 
   1034 static void VP8LEncoderDelete(VP8LEncoder* enc) {
   1035   if (enc != NULL) {
   1036     VP8LHashChainClear(&enc->hash_chain_);
   1037     VP8LBackwardRefsClear(&enc->refs_[0]);
   1038     VP8LBackwardRefsClear(&enc->refs_[1]);
   1039     WebPSafeFree(enc->argb_);
   1040     WebPSafeFree(enc);
   1041   }
   1042 }
   1043 
   1044 // -----------------------------------------------------------------------------
   1045 // Main call
   1046 
   1047 WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
   1048                                    const WebPPicture* const picture,
   1049                                    VP8LBitWriter* const bw) {
   1050   WebPEncodingError err = VP8_ENC_OK;
   1051   const int quality = (int)config->quality;
   1052   const int width = picture->width;
   1053   const int height = picture->height;
   1054   VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
   1055   const size_t byte_position = VP8LBitWriterNumBytes(bw);
   1056 
   1057   if (enc == NULL) {
   1058     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1059     goto Error;
   1060   }
   1061 
   1062   // ---------------------------------------------------------------------------
   1063   // Analyze image (entropy, num_palettes etc)
   1064 
   1065   if (!AnalyzeAndInit(enc, config->image_hint)) {
   1066     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1067     goto Error;
   1068   }
   1069 
   1070   FinishEncParams(enc);
   1071 
   1072   if (enc->use_palette_) {
   1073     err = EncodePalette(bw, enc, quality);
   1074     if (err != VP8_ENC_OK) goto Error;
   1075     // Color cache is disabled for palette.
   1076     enc->cache_bits_ = 0;
   1077   }
   1078 
   1079   // In case image is not packed.
   1080   if (enc->argb_ == NULL) {
   1081     int y;
   1082     err = AllocateTransformBuffer(enc, width, height);
   1083     if (err != VP8_ENC_OK) goto Error;
   1084     for (y = 0; y < height; ++y) {
   1085       memcpy(enc->argb_ + y * width,
   1086              picture->argb + y * picture->argb_stride,
   1087              width * sizeof(*enc->argb_));
   1088     }
   1089     enc->current_width_ = width;
   1090   }
   1091 
   1092   // ---------------------------------------------------------------------------
   1093   // Apply transforms and write transform data.
   1094 
   1095   err = EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw);
   1096   if (err != VP8_ENC_OK) goto Error;
   1097 
   1098   if (enc->use_predict_) {
   1099     err = ApplyPredictFilter(enc, enc->current_width_, height, quality, bw);
   1100     if (err != VP8_ENC_OK) goto Error;
   1101   }
   1102 
   1103   if (enc->use_cross_color_) {
   1104     err = ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw);
   1105     if (err != VP8_ENC_OK) goto Error;
   1106   }
   1107 
   1108   VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT);  // No more transforms.
   1109 
   1110   // ---------------------------------------------------------------------------
   1111   // Estimate the color cache size.
   1112 
   1113   if (enc->cache_bits_ > 0) {
   1114     if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_,
   1115                                            height, quality, &enc->hash_chain_,
   1116                                            &enc->refs_[0], &enc->cache_bits_)) {
   1117       err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1118       goto Error;
   1119     }
   1120   }
   1121 
   1122   // ---------------------------------------------------------------------------
   1123   // Encode and write the transformed image.
   1124 
   1125   err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_,
   1126                             enc->current_width_, height, quality,
   1127                             enc->cache_bits_, enc->histo_bits_);
   1128   if (err != VP8_ENC_OK) goto Error;
   1129 
   1130   if (picture->stats != NULL) {
   1131     WebPAuxStats* const stats = picture->stats;
   1132     stats->lossless_features = 0;
   1133     if (enc->use_predict_) stats->lossless_features |= 1;
   1134     if (enc->use_cross_color_) stats->lossless_features |= 2;
   1135     if (enc->use_subtract_green_) stats->lossless_features |= 4;
   1136     if (enc->use_palette_) stats->lossless_features |= 8;
   1137     stats->histogram_bits = enc->histo_bits_;
   1138     stats->transform_bits = enc->transform_bits_;
   1139     stats->cache_bits = enc->cache_bits_;
   1140     stats->palette_size = enc->palette_size_;
   1141     stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position);
   1142   }
   1143 
   1144  Error:
   1145   VP8LEncoderDelete(enc);
   1146   return err;
   1147 }
   1148 
   1149 int VP8LEncodeImage(const WebPConfig* const config,
   1150                     const WebPPicture* const picture) {
   1151   int width, height;
   1152   int has_alpha;
   1153   size_t coded_size;
   1154   int percent = 0;
   1155   int initial_size;
   1156   WebPEncodingError err = VP8_ENC_OK;
   1157   VP8LBitWriter bw;
   1158 
   1159   if (picture == NULL) return 0;
   1160 
   1161   if (config == NULL || picture->argb == NULL) {
   1162     err = VP8_ENC_ERROR_NULL_PARAMETER;
   1163     WebPEncodingSetError(picture, err);
   1164     return 0;
   1165   }
   1166 
   1167   width = picture->width;
   1168   height = picture->height;
   1169   // Initialize BitWriter with size corresponding to 16 bpp to photo images and
   1170   // 8 bpp for graphical images.
   1171   initial_size = (config->image_hint == WEBP_HINT_GRAPH) ?
   1172                  width * height : width * height * 2;
   1173   if (!VP8LBitWriterInit(&bw, initial_size)) {
   1174     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1175     goto Error;
   1176   }
   1177 
   1178   if (!WebPReportProgress(picture, 1, &percent)) {
   1179  UserAbort:
   1180     err = VP8_ENC_ERROR_USER_ABORT;
   1181     goto Error;
   1182   }
   1183   // Reset stats (for pure lossless coding)
   1184   if (picture->stats != NULL) {
   1185     WebPAuxStats* const stats = picture->stats;
   1186     memset(stats, 0, sizeof(*stats));
   1187     stats->PSNR[0] = 99.f;
   1188     stats->PSNR[1] = 99.f;
   1189     stats->PSNR[2] = 99.f;
   1190     stats->PSNR[3] = 99.f;
   1191     stats->PSNR[4] = 99.f;
   1192   }
   1193 
   1194   // Write image size.
   1195   if (!WriteImageSize(picture, &bw)) {
   1196     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1197     goto Error;
   1198   }
   1199 
   1200   has_alpha = WebPPictureHasTransparency(picture);
   1201   // Write the non-trivial Alpha flag and lossless version.
   1202   if (!WriteRealAlphaAndVersion(&bw, has_alpha)) {
   1203     err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1204     goto Error;
   1205   }
   1206 
   1207   if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort;
   1208 
   1209   // Encode main image stream.
   1210   err = VP8LEncodeStream(config, picture, &bw);
   1211   if (err != VP8_ENC_OK) goto Error;
   1212 
   1213   // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
   1214   if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort;
   1215 
   1216   // Finish the RIFF chunk.
   1217   err = WriteImage(picture, &bw, &coded_size);
   1218   if (err != VP8_ENC_OK) goto Error;
   1219 
   1220   if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort;
   1221 
   1222   // Save size.
   1223   if (picture->stats != NULL) {
   1224     picture->stats->coded_size += (int)coded_size;
   1225     picture->stats->lossless_size = (int)coded_size;
   1226   }
   1227 
   1228   if (picture->extra_info != NULL) {
   1229     const int mb_w = (width + 15) >> 4;
   1230     const int mb_h = (height + 15) >> 4;
   1231     memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info));
   1232   }
   1233 
   1234  Error:
   1235   if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   1236   VP8LBitWriterDestroy(&bw);
   1237   if (err != VP8_ENC_OK) {
   1238     WebPEncodingSetError(picture, err);
   1239     return 0;
   1240   }
   1241   return 1;
   1242 }
   1243 
   1244 //------------------------------------------------------------------------------
   1245