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