github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/webp/libwebp/src/enc/vp8l.c (about)

     1  // Copyright 2012 Google Inc. All Rights Reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the COPYING file in the root of the source
     5  // tree. An additional intellectual property rights grant can be found
     6  // in the file PATENTS. All contributing project authors may
     7  // be found in the AUTHORS file in the root of the source tree.
     8  // -----------------------------------------------------------------------------
     9  //
    10  // main entry for the lossless encoder.
    11  //
    12  // Author: Vikas Arora (vikaas.arora@gmail.com)
    13  //
    14  
    15  #include <assert.h>
    16  #include <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    VP8LHistogram* nonpredicted = NULL;
   110    VP8LHistogram* predicted =
   111        (VP8LHistogram*)malloc(2 * sizeof(*predicted));
   112    if (predicted == NULL) return 0;
   113    nonpredicted = predicted + 1;
   114  
   115    VP8LHistogramInit(predicted, 0);
   116    VP8LHistogramInit(nonpredicted, 0);
   117    for (y = 0; y < height; ++y) {
   118      for (x = 0; x < width; ++x) {
   119        const uint32_t pix = argb[x];
   120        const uint32_t pix_diff = VP8LSubPixels(pix, last_pix);
   121        if (pix_diff == 0) continue;
   122        if (last_line != NULL && pix == last_line[x]) {
   123          continue;
   124        }
   125        last_pix = pix;
   126        {
   127          const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix);
   128          const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff);
   129          VP8LHistogramAddSinglePixOrCopy(nonpredicted, &pix_token);
   130          VP8LHistogramAddSinglePixOrCopy(predicted, &pix_diff_token);
   131        }
   132      }
   133      last_line = argb;
   134      argb += argb_stride;
   135    }
   136    *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(nonpredicted);
   137    *predicted_bits = VP8LHistogramEstimateBitsBulk(predicted);
   138    free(predicted);
   139    return 1;
   140  }
   141  
   142  static int VP8LEncAnalyze(VP8LEncoder* const enc, WebPImageHint image_hint) {
   143    const WebPPicture* const pic = enc->pic_;
   144    assert(pic != NULL && pic->argb != NULL);
   145  
   146    enc->use_palette_ =
   147        AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_);
   148  
   149    if (image_hint == WEBP_HINT_GRAPH) {
   150      if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) {
   151        enc->use_palette_ = 0;
   152      }
   153    }
   154  
   155    if (!enc->use_palette_) {
   156      if (image_hint == WEBP_HINT_PHOTO) {
   157        enc->use_predict_ = 1;
   158        enc->use_cross_color_ = 1;
   159      } else {
   160        double non_pred_entropy, pred_entropy;
   161        if (!AnalyzeEntropy(pic->argb, pic->width, pic->height, pic->argb_stride,
   162                            &non_pred_entropy, &pred_entropy)) {
   163          return 0;
   164        }
   165        if (pred_entropy < 0.95 * non_pred_entropy) {
   166          enc->use_predict_ = 1;
   167          enc->use_cross_color_ = 1;
   168        }
   169      }
   170    }
   171  
   172    return 1;
   173  }
   174  
   175  static int GetHuffBitLengthsAndCodes(
   176      const VP8LHistogramSet* const histogram_image,
   177      HuffmanTreeCode* const huffman_codes) {
   178    int i, k;
   179    int ok = 1;
   180    uint64_t total_length_size = 0;
   181    uint8_t* mem_buf = NULL;
   182    const int histogram_image_size = histogram_image->size;
   183  
   184    // Iterate over all histograms and get the aggregate number of codes used.
   185    for (i = 0; i < histogram_image_size; ++i) {
   186      const VP8LHistogram* const histo = histogram_image->histograms[i];
   187      HuffmanTreeCode* const codes = &huffman_codes[5 * i];
   188      for (k = 0; k < 5; ++k) {
   189        const int num_symbols = (k == 0) ? VP8LHistogramNumCodes(histo)
   190                              : (k == 4) ? NUM_DISTANCE_CODES
   191                              : 256;
   192        codes[k].num_symbols = num_symbols;
   193        total_length_size += num_symbols;
   194      }
   195    }
   196  
   197    // Allocate and Set Huffman codes.
   198    {
   199      uint16_t* codes;
   200      uint8_t* lengths;
   201      mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
   202                                         sizeof(*lengths) + sizeof(*codes));
   203      if (mem_buf == NULL) {
   204        ok = 0;
   205        goto End;
   206      }
   207      codes = (uint16_t*)mem_buf;
   208      lengths = (uint8_t*)&codes[total_length_size];
   209      for (i = 0; i < 5 * histogram_image_size; ++i) {
   210        const int bit_length = huffman_codes[i].num_symbols;
   211        huffman_codes[i].codes = codes;
   212        huffman_codes[i].code_lengths = lengths;
   213        codes += bit_length;
   214        lengths += bit_length;
   215      }
   216    }
   217  
   218    // Create Huffman trees.
   219    for (i = 0; ok && (i < histogram_image_size); ++i) {
   220      HuffmanTreeCode* const codes = &huffman_codes[5 * i];
   221      VP8LHistogram* const histo = histogram_image->histograms[i];
   222      ok = ok && VP8LCreateHuffmanTree(histo->literal_, 15, codes + 0);
   223      ok = ok && VP8LCreateHuffmanTree(histo->red_, 15, codes + 1);
   224      ok = ok && VP8LCreateHuffmanTree(histo->blue_, 15, codes + 2);
   225      ok = ok && VP8LCreateHuffmanTree(histo->alpha_, 15, codes + 3);
   226      ok = ok && VP8LCreateHuffmanTree(histo->distance_, 15, codes + 4);
   227    }
   228  
   229   End:
   230    if (!ok) {
   231      free(mem_buf);
   232      // If one VP8LCreateHuffmanTree() above fails, we need to clean up behind.
   233      memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
   234    }
   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,
   410                               int code_index) {
   411    const int depth = code->code_lengths[code_index];
   412    const int symbol = code->codes[code_index];
   413    VP8LWriteBits(bw, depth, symbol);
   414  }
   415  
   416  static void StoreImageToBitMask(
   417      VP8LBitWriter* const bw, int width, int histo_bits,
   418      const VP8LBackwardRefs* const refs,
   419      const uint16_t* histogram_symbols,
   420      const HuffmanTreeCode* const huffman_codes) {
   421    // x and y trace the position in the image.
   422    int x = 0;
   423    int y = 0;
   424    const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
   425    int i;
   426    for (i = 0; i < refs->size; ++i) {
   427      const PixOrCopy* const v = &refs->refs[i];
   428      const int histogram_ix = histogram_symbols[histo_bits ?
   429                                                 (y >> histo_bits) * histo_xsize +
   430                                                 (x >> histo_bits) : 0];
   431      const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix;
   432      if (PixOrCopyIsCacheIdx(v)) {
   433        const int code = PixOrCopyCacheIdx(v);
   434        const int literal_ix = 256 + NUM_LENGTH_CODES + code;
   435        WriteHuffmanCode(bw, codes, literal_ix);
   436      } else if (PixOrCopyIsLiteral(v)) {
   437        static const int order[] = { 1, 2, 0, 3 };
   438        int k;
   439        for (k = 0; k < 4; ++k) {
   440          const int code = PixOrCopyLiteral(v, order[k]);
   441          WriteHuffmanCode(bw, codes + k, code);
   442        }
   443      } else {
   444        int bits, n_bits;
   445        int code, distance;
   446  
   447        VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
   448        WriteHuffmanCode(bw, codes, 256 + code);
   449        VP8LWriteBits(bw, n_bits, bits);
   450  
   451        distance = PixOrCopyDistance(v);
   452        VP8LPrefixEncode(distance, &code, &n_bits, &bits);
   453        WriteHuffmanCode(bw, codes + 4, code);
   454        VP8LWriteBits(bw, n_bits, bits);
   455      }
   456      x += PixOrCopyLength(v);
   457      while (x >= width) {
   458        x -= width;
   459        ++y;
   460      }
   461    }
   462  }
   463  
   464  // Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
   465  static int EncodeImageNoHuffman(VP8LBitWriter* const bw,
   466                                  const uint32_t* const argb,
   467                                  int width, int height, int quality) {
   468    int i;
   469    int ok = 0;
   470    VP8LBackwardRefs refs;
   471    HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } };
   472    const uint16_t histogram_symbols[1] = { 0 };    // only one tree, one symbol
   473    VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0);
   474    if (histogram_image == NULL) return 0;
   475  
   476    // Calculate backward references from ARGB image.
   477    if (!VP8LGetBackwardReferences(width, height, argb, quality, 0, 1, &refs)) {
   478      goto Error;
   479    }
   480    // Build histogram image and symbols from backward references.
   481    VP8LHistogramStoreRefs(&refs, histogram_image->histograms[0]);
   482  
   483    // Create Huffman bit lengths and codes for each histogram image.
   484    assert(histogram_image->size == 1);
   485    if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
   486      goto Error;
   487    }
   488  
   489    // No color cache, no Huffman image.
   490    VP8LWriteBits(bw, 1, 0);
   491  
   492    // Store Huffman codes.
   493    for (i = 0; i < 5; ++i) {
   494      HuffmanTreeCode* const codes = &huffman_codes[i];
   495      if (!StoreHuffmanCode(bw, codes)) {
   496        goto Error;
   497      }
   498      ClearHuffmanTreeIfOnlyOneSymbol(codes);
   499    }
   500  
   501    // Store actual literals.
   502    StoreImageToBitMask(bw, width, 0, &refs, histogram_symbols, huffman_codes);
   503    ok = 1;
   504  
   505   Error:
   506    free(histogram_image);
   507    VP8LClearBackwardRefs(&refs);
   508    free(huffman_codes[0].codes);
   509    return ok;
   510  }
   511  
   512  static int EncodeImageInternal(VP8LBitWriter* const bw,
   513                                 const uint32_t* const argb,
   514                                 int width, int height, int quality,
   515                                 int cache_bits, int histogram_bits) {
   516    int ok = 0;
   517    const int use_2d_locality = 1;
   518    const int use_color_cache = (cache_bits > 0);
   519    const uint32_t histogram_image_xysize =
   520        VP8LSubSampleSize(width, histogram_bits) *
   521        VP8LSubSampleSize(height, histogram_bits);
   522    VP8LHistogramSet* histogram_image =
   523        VP8LAllocateHistogramSet(histogram_image_xysize, 0);
   524    int histogram_image_size = 0;
   525    size_t bit_array_size = 0;
   526    HuffmanTreeCode* huffman_codes = NULL;
   527    VP8LBackwardRefs refs;
   528    uint16_t* const histogram_symbols =
   529        (uint16_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize,
   530                                  sizeof(*histogram_symbols));
   531    assert(histogram_bits >= MIN_HUFFMAN_BITS);
   532    assert(histogram_bits <= MAX_HUFFMAN_BITS);
   533  
   534    if (histogram_image == NULL || histogram_symbols == NULL) {
   535      free(histogram_image);
   536      free(histogram_symbols);
   537      return 0;
   538    }
   539  
   540    // Calculate backward references from ARGB image.
   541    if (!VP8LGetBackwardReferences(width, height, argb, quality, cache_bits,
   542                                   use_2d_locality, &refs)) {
   543      goto Error;
   544    }
   545    // Build histogram image and symbols from backward references.
   546    if (!VP8LGetHistoImageSymbols(width, height, &refs,
   547                                  quality, histogram_bits, cache_bits,
   548                                  histogram_image,
   549                                  histogram_symbols)) {
   550      goto Error;
   551    }
   552    // Create Huffman bit lengths and codes for each histogram image.
   553    histogram_image_size = histogram_image->size;
   554    bit_array_size = 5 * histogram_image_size;
   555    huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
   556                                                     sizeof(*huffman_codes));
   557    if (huffman_codes == NULL ||
   558        !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
   559      goto Error;
   560    }
   561    // Free combined histograms.
   562    free(histogram_image);
   563    histogram_image = NULL;
   564  
   565    // Color Cache parameters.
   566    VP8LWriteBits(bw, 1, use_color_cache);
   567    if (use_color_cache) {
   568      VP8LWriteBits(bw, 4, cache_bits);
   569    }
   570  
   571    // Huffman image + meta huffman.
   572    {
   573      const int write_histogram_image = (histogram_image_size > 1);
   574      VP8LWriteBits(bw, 1, write_histogram_image);
   575      if (write_histogram_image) {
   576        uint32_t* const histogram_argb =
   577            (uint32_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize,
   578                                      sizeof(*histogram_argb));
   579        int max_index = 0;
   580        uint32_t i;
   581        if (histogram_argb == NULL) goto Error;
   582        for (i = 0; i < histogram_image_xysize; ++i) {
   583          const int symbol_index = histogram_symbols[i] & 0xffff;
   584          histogram_argb[i] = 0xff000000 | (symbol_index << 8);
   585          if (symbol_index >= max_index) {
   586            max_index = symbol_index + 1;
   587          }
   588        }
   589        histogram_image_size = max_index;
   590  
   591        VP8LWriteBits(bw, 3, histogram_bits - 2);
   592        ok = EncodeImageNoHuffman(bw, histogram_argb,
   593                                  VP8LSubSampleSize(width, histogram_bits),
   594                                  VP8LSubSampleSize(height, histogram_bits),
   595                                  quality);
   596        free(histogram_argb);
   597        if (!ok) goto Error;
   598      }
   599    }
   600  
   601    // Store Huffman codes.
   602    {
   603      int i;
   604      for (i = 0; i < 5 * histogram_image_size; ++i) {
   605        HuffmanTreeCode* const codes = &huffman_codes[i];
   606        if (!StoreHuffmanCode(bw, codes)) goto Error;
   607        ClearHuffmanTreeIfOnlyOneSymbol(codes);
   608      }
   609    }
   610  
   611    // Store actual literals.
   612    StoreImageToBitMask(bw, width, histogram_bits, &refs,
   613                        histogram_symbols, huffman_codes);
   614    ok = 1;
   615  
   616   Error:
   617    free(histogram_image);
   618  
   619    VP8LClearBackwardRefs(&refs);
   620    if (huffman_codes != NULL) {
   621      free(huffman_codes->codes);
   622      free(huffman_codes);
   623    }
   624    free(histogram_symbols);
   625    return ok;
   626  }
   627  
   628  // -----------------------------------------------------------------------------
   629  // Transforms
   630  
   631  // Check if it would be a good idea to subtract green from red and blue. We
   632  // only impact entropy in red/blue components, don't bother to look at others.
   633  static int EvalAndApplySubtractGreen(VP8LEncoder* const enc,
   634                                       int width, int height,
   635                                       VP8LBitWriter* const bw) {
   636    if (!enc->use_palette_) {
   637      int i;
   638      const uint32_t* const argb = enc->argb_;
   639      double bit_cost_before, bit_cost_after;
   640      VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo));
   641      if (histo == NULL) return 0;
   642  
   643      VP8LHistogramInit(histo, 1);
   644      for (i = 0; i < width * height; ++i) {
   645        const uint32_t c = argb[i];
   646        ++histo->red_[(c >> 16) & 0xff];
   647        ++histo->blue_[(c >> 0) & 0xff];
   648      }
   649      bit_cost_before = VP8LHistogramEstimateBits(histo);
   650  
   651      VP8LHistogramInit(histo, 1);
   652      for (i = 0; i < width * height; ++i) {
   653        const uint32_t c = argb[i];
   654        const int green = (c >> 8) & 0xff;
   655        ++histo->red_[((c >> 16) - green) & 0xff];
   656        ++histo->blue_[((c >> 0) - green) & 0xff];
   657      }
   658      bit_cost_after = VP8LHistogramEstimateBits(histo);
   659      free(histo);
   660  
   661      // Check if subtracting green yields low entropy.
   662      enc->use_subtract_green_ = (bit_cost_after < bit_cost_before);
   663      if (enc->use_subtract_green_) {
   664        VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
   665        VP8LWriteBits(bw, 2, SUBTRACT_GREEN);
   666        VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
   667      }
   668    }
   669    return 1;
   670  }
   671  
   672  static int ApplyPredictFilter(const VP8LEncoder* const enc,
   673                                int width, int height, int quality,
   674                                VP8LBitWriter* const bw) {
   675    const int pred_bits = enc->transform_bits_;
   676    const int transform_width = VP8LSubSampleSize(width, pred_bits);
   677    const int transform_height = VP8LSubSampleSize(height, pred_bits);
   678  
   679    VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
   680                      enc->transform_data_);
   681    VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
   682    VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM);
   683    assert(pred_bits >= 2);
   684    VP8LWriteBits(bw, 3, pred_bits - 2);
   685    if (!EncodeImageNoHuffman(bw, enc->transform_data_,
   686                              transform_width, transform_height, quality)) {
   687      return 0;
   688    }
   689    return 1;
   690  }
   691  
   692  static int ApplyCrossColorFilter(const VP8LEncoder* const enc,
   693                                   int width, int height, int quality,
   694                                   VP8LBitWriter* const bw) {
   695    const int ccolor_transform_bits = enc->transform_bits_;
   696    const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
   697    const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
   698    const int step = (quality < 25) ? 32 : (quality > 50) ? 8 : 16;
   699  
   700    VP8LColorSpaceTransform(width, height, ccolor_transform_bits, step,
   701                            enc->argb_, enc->transform_data_);
   702    VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
   703    VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM);
   704    assert(ccolor_transform_bits >= 2);
   705    VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
   706    if (!EncodeImageNoHuffman(bw, enc->transform_data_,
   707                              transform_width, transform_height, quality)) {
   708      return 0;
   709    }
   710    return 1;
   711  }
   712  
   713  // -----------------------------------------------------------------------------
   714  
   715  static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
   716                                           size_t riff_size, size_t vp8l_size) {
   717    uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
   718      'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
   719      'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE,
   720    };
   721    PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
   722    PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
   723    if (!pic->writer(riff, sizeof(riff), pic)) {
   724      return VP8_ENC_ERROR_BAD_WRITE;
   725    }
   726    return VP8_ENC_OK;
   727  }
   728  
   729  static int WriteImageSize(const WebPPicture* const pic,
   730                            VP8LBitWriter* const bw) {
   731    const int width = pic->width - 1;
   732    const int height = pic->height - 1;
   733    assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
   734  
   735    VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width);
   736    VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height);
   737    return !bw->error_;
   738  }
   739  
   740  static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
   741    VP8LWriteBits(bw, 1, has_alpha);
   742    VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION);
   743    return !bw->error_;
   744  }
   745  
   746  static WebPEncodingError WriteImage(const WebPPicture* const pic,
   747                                      VP8LBitWriter* const bw,
   748                                      size_t* const coded_size) {
   749    WebPEncodingError err = VP8_ENC_OK;
   750    const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
   751    const size_t webpll_size = VP8LBitWriterNumBytes(bw);
   752    const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
   753    const size_t pad = vp8l_size & 1;
   754    const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
   755  
   756    err = WriteRiffHeader(pic, riff_size, vp8l_size);
   757    if (err != VP8_ENC_OK) goto Error;
   758  
   759    if (!pic->writer(webpll_data, webpll_size, pic)) {
   760      err = VP8_ENC_ERROR_BAD_WRITE;
   761      goto Error;
   762    }
   763  
   764    if (pad) {
   765      const uint8_t pad_byte[1] = { 0 };
   766      if (!pic->writer(pad_byte, 1, pic)) {
   767        err = VP8_ENC_ERROR_BAD_WRITE;
   768        goto Error;
   769      }
   770    }
   771    *coded_size = CHUNK_HEADER_SIZE + riff_size;
   772    return VP8_ENC_OK;
   773  
   774   Error:
   775    return err;
   776  }
   777  
   778  // -----------------------------------------------------------------------------
   779  
   780  // Allocates the memory for argb (W x H) buffer, 2 rows of context for
   781  // prediction and transform data.
   782  static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
   783                                                   int width, int height) {
   784    WebPEncodingError err = VP8_ENC_OK;
   785    const int tile_size = 1 << enc->transform_bits_;
   786    const uint64_t image_size = width * height;
   787    const uint64_t argb_scratch_size = tile_size * width + width;
   788    const uint64_t transform_data_size =
   789        (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) *
   790        (uint64_t)VP8LSubSampleSize(height, enc->transform_bits_);
   791    const uint64_t total_size =
   792        image_size + argb_scratch_size + transform_data_size;
   793    uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem));
   794    if (mem == NULL) {
   795      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   796      goto Error;
   797    }
   798    enc->argb_ = mem;
   799    mem += image_size;
   800    enc->argb_scratch_ = mem;
   801    mem += argb_scratch_size;
   802    enc->transform_data_ = mem;
   803    enc->current_width_ = width;
   804  
   805   Error:
   806    return err;
   807  }
   808  
   809  static void ApplyPalette(uint32_t* src, uint32_t* dst,
   810                           uint32_t src_stride, uint32_t dst_stride,
   811                           const uint32_t* palette, int palette_size,
   812                           int width, int height, int xbits, uint8_t* row) {
   813    int i, x, y;
   814    int use_LUT = 1;
   815    for (i = 0; i < palette_size; ++i) {
   816      if ((palette[i] & 0xffff00ffu) != 0) {
   817        use_LUT = 0;
   818        break;
   819      }
   820    }
   821  
   822    if (use_LUT) {
   823      uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 };
   824      for (i = 0; i < palette_size; ++i) {
   825        const int color = (palette[i] >> 8) & 0xff;
   826        inv_palette[color] = i;
   827      }
   828      for (y = 0; y < height; ++y) {
   829        for (x = 0; x < width; ++x) {
   830          const int color = (src[x] >> 8) & 0xff;
   831          row[x] = inv_palette[color];
   832        }
   833        VP8LBundleColorMap(row, width, xbits, dst);
   834        src += src_stride;
   835        dst += dst_stride;
   836      }
   837    } else {
   838      // Use 1 pixel cache for ARGB pixels.
   839      uint32_t last_pix = palette[0];
   840      int last_idx = 0;
   841      for (y = 0; y < height; ++y) {
   842        for (x = 0; x < width; ++x) {
   843          const uint32_t pix = src[x];
   844          if (pix != last_pix) {
   845            for (i = 0; i < palette_size; ++i) {
   846              if (pix == palette[i]) {
   847                last_idx = i;
   848                last_pix = pix;
   849                break;
   850              }
   851            }
   852          }
   853          row[x] = last_idx;
   854        }
   855        VP8LBundleColorMap(row, width, xbits, dst);
   856        src += src_stride;
   857        dst += dst_stride;
   858      }
   859    }
   860  }
   861  
   862  // Note: Expects "enc->palette_" to be set properly.
   863  // Also, "enc->palette_" will be modified after this call and should not be used
   864  // later.
   865  static WebPEncodingError EncodePalette(VP8LBitWriter* const bw,
   866                                         VP8LEncoder* const enc, int quality) {
   867    WebPEncodingError err = VP8_ENC_OK;
   868    int i;
   869    const WebPPicture* const pic = enc->pic_;
   870    uint32_t* src = pic->argb;
   871    uint32_t* dst;
   872    const int width = pic->width;
   873    const int height = pic->height;
   874    uint32_t* const palette = enc->palette_;
   875    const int palette_size = enc->palette_size_;
   876    uint8_t* row = NULL;
   877    int xbits;
   878  
   879    // Replace each input pixel by corresponding palette index.
   880    // This is done line by line.
   881    if (palette_size <= 4) {
   882      xbits = (palette_size <= 2) ? 3 : 2;
   883    } else {
   884      xbits = (palette_size <= 16) ? 1 : 0;
   885    }
   886  
   887    err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
   888    if (err != VP8_ENC_OK) goto Error;
   889    dst = enc->argb_;
   890  
   891    row = (uint8_t*)WebPSafeMalloc((uint64_t)width, sizeof(*row));
   892    if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
   893  
   894    ApplyPalette(src, dst, pic->argb_stride, enc->current_width_,
   895                 palette, palette_size, width, height, xbits, row);
   896  
   897    // Save palette to bitstream.
   898    VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
   899    VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM);
   900    assert(palette_size >= 1);
   901    VP8LWriteBits(bw, 8, palette_size - 1);
   902    for (i = palette_size - 1; i >= 1; --i) {
   903      palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
   904    }
   905    if (!EncodeImageNoHuffman(bw, palette, palette_size, 1, quality)) {
   906      err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
   907      goto Error;
   908    }
   909  
   910   Error:
   911    free(row);
   912    return err;
   913  }
   914  
   915  // -----------------------------------------------------------------------------
   916  
   917  static int GetHistoBits(int method, int use_palette, int width, int height) {
   918    const uint64_t hist_size = sizeof(VP8LHistogram);
   919    // Make tile size a function of encoding method (Range: 0 to 6).
   920    int histo_bits = (use_palette ? 9 : 7) - method;
   921    while (1) {
   922      const uint64_t huff_image_size = VP8LSubSampleSize(width, histo_bits) *
   923                                       VP8LSubSampleSize(height, histo_bits) *
   924                                       hist_size;
   925      if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break;
   926      ++histo_bits;
   927    }
   928    return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
   929           (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
   930  }
   931  
   932  static void FinishEncParams(VP8LEncoder* const enc) {
   933    const WebPConfig* const config = enc->config_;
   934    const WebPPicture* const pic = enc->pic_;
   935    const int method = config->method;
   936    const float quality = config->quality;
   937    const int use_palette = enc->use_palette_;
   938    enc->transform_bits_ = (method < 4) ? 5 : (method > 4) ? 3 : 4;
   939    enc->histo_bits_ = GetHistoBits(method, use_palette, pic->width, pic->height);
   940    enc->cache_bits_ = (quality <= 25.f) ? 0 : 7;
   941  }
   942  
   943  // -----------------------------------------------------------------------------
   944  // VP8LEncoder
   945  
   946  static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
   947                                     const WebPPicture* const picture) {
   948    VP8LEncoder* const enc = (VP8LEncoder*)calloc(1, sizeof(*enc));
   949    if (enc == NULL) {
   950      WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
   951      return NULL;
   952    }
   953    enc->config_ = config;
   954    enc->pic_ = picture;
   955  
   956    VP8LDspInit();
   957  
   958    return enc;
   959  }
   960  
   961  static void VP8LEncoderDelete(VP8LEncoder* enc) {
   962    free(enc->argb_);
   963    free(enc);
   964  }
   965  
   966  // -----------------------------------------------------------------------------
   967  // Main call
   968  
   969  WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
   970                                     const WebPPicture* const picture,
   971                                     VP8LBitWriter* const bw) {
   972    WebPEncodingError err = VP8_ENC_OK;
   973    const int quality = (int)config->quality;
   974    const int width = picture->width;
   975    const int height = picture->height;
   976    VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
   977    const size_t byte_position = VP8LBitWriterNumBytes(bw);
   978  
   979    if (enc == NULL) {
   980      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   981      goto Error;
   982    }
   983  
   984    // ---------------------------------------------------------------------------
   985    // Analyze image (entropy, num_palettes etc)
   986  
   987    if (!VP8LEncAnalyze(enc, config->image_hint)) {
   988      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
   989      goto Error;
   990    }
   991  
   992    FinishEncParams(enc);
   993  
   994    if (enc->use_palette_) {
   995      err = EncodePalette(bw, enc, quality);
   996      if (err != VP8_ENC_OK) goto Error;
   997      // Color cache is disabled for palette.
   998      enc->cache_bits_ = 0;
   999    }
  1000  
  1001    // In case image is not packed.
  1002    if (enc->argb_ == NULL) {
  1003      int y;
  1004      err = AllocateTransformBuffer(enc, width, height);
  1005      if (err != VP8_ENC_OK) goto Error;
  1006      for (y = 0; y < height; ++y) {
  1007        memcpy(enc->argb_ + y * width,
  1008               picture->argb + y * picture->argb_stride,
  1009               width * sizeof(*enc->argb_));
  1010      }
  1011      enc->current_width_ = width;
  1012    }
  1013  
  1014    // ---------------------------------------------------------------------------
  1015    // Apply transforms and write transform data.
  1016  
  1017    if (!EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw)) {
  1018      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
  1019      goto Error;
  1020    }
  1021  
  1022    if (enc->use_predict_) {
  1023      if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, bw)) {
  1024        err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
  1025        goto Error;
  1026      }
  1027    }
  1028  
  1029    if (enc->use_cross_color_) {
  1030      if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw)) {
  1031        err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
  1032        goto Error;
  1033      }
  1034    }
  1035  
  1036    VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT);  // No more transforms.
  1037  
  1038    // ---------------------------------------------------------------------------
  1039    // Estimate the color cache size.
  1040  
  1041    if (enc->cache_bits_ > 0) {
  1042      if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_,
  1043                                             height, &enc->cache_bits_)) {
  1044        err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
  1045        goto Error;
  1046      }
  1047    }
  1048  
  1049    // ---------------------------------------------------------------------------
  1050    // Encode and write the transformed image.
  1051  
  1052    if (!EncodeImageInternal(bw, enc->argb_, enc->current_width_, height,
  1053                             quality, enc->cache_bits_, enc->histo_bits_)) {
  1054      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
  1055      goto Error;
  1056    }
  1057  
  1058    if (picture->stats != NULL) {
  1059      WebPAuxStats* const stats = picture->stats;
  1060      stats->lossless_features = 0;
  1061      if (enc->use_predict_) stats->lossless_features |= 1;
  1062      if (enc->use_cross_color_) stats->lossless_features |= 2;
  1063      if (enc->use_subtract_green_) stats->lossless_features |= 4;
  1064      if (enc->use_palette_) stats->lossless_features |= 8;
  1065      stats->histogram_bits = enc->histo_bits_;
  1066      stats->transform_bits = enc->transform_bits_;
  1067      stats->cache_bits = enc->cache_bits_;
  1068      stats->palette_size = enc->palette_size_;
  1069      stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position);
  1070    }
  1071  
  1072   Error:
  1073    VP8LEncoderDelete(enc);
  1074    return err;
  1075  }
  1076  
  1077  int VP8LEncodeImage(const WebPConfig* const config,
  1078                      const WebPPicture* const picture) {
  1079    int width, height;
  1080    int has_alpha;
  1081    size_t coded_size;
  1082    int percent = 0;
  1083    WebPEncodingError err = VP8_ENC_OK;
  1084    VP8LBitWriter bw;
  1085  
  1086    if (picture == NULL) return 0;
  1087  
  1088    if (config == NULL || picture->argb == NULL) {
  1089      err = VP8_ENC_ERROR_NULL_PARAMETER;
  1090      WebPEncodingSetError(picture, err);
  1091      return 0;
  1092    }
  1093  
  1094    width = picture->width;
  1095    height = picture->height;
  1096    if (!VP8LBitWriterInit(&bw, (width * height) >> 1)) {
  1097      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
  1098      goto Error;
  1099    }
  1100  
  1101    if (!WebPReportProgress(picture, 1, &percent)) {
  1102   UserAbort:
  1103      err = VP8_ENC_ERROR_USER_ABORT;
  1104      goto Error;
  1105    }
  1106    // Reset stats (for pure lossless coding)
  1107    if (picture->stats != NULL) {
  1108      WebPAuxStats* const stats = picture->stats;
  1109      memset(stats, 0, sizeof(*stats));
  1110      stats->PSNR[0] = 99.f;
  1111      stats->PSNR[1] = 99.f;
  1112      stats->PSNR[2] = 99.f;
  1113      stats->PSNR[3] = 99.f;
  1114      stats->PSNR[4] = 99.f;
  1115    }
  1116  
  1117    // Write image size.
  1118    if (!WriteImageSize(picture, &bw)) {
  1119      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
  1120      goto Error;
  1121    }
  1122  
  1123    has_alpha = WebPPictureHasTransparency(picture);
  1124    // Write the non-trivial Alpha flag and lossless version.
  1125    if (!WriteRealAlphaAndVersion(&bw, has_alpha)) {
  1126      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
  1127      goto Error;
  1128    }
  1129  
  1130    if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort;
  1131  
  1132    // Encode main image stream.
  1133    err = VP8LEncodeStream(config, picture, &bw);
  1134    if (err != VP8_ENC_OK) goto Error;
  1135  
  1136    // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
  1137    if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort;
  1138  
  1139    // Finish the RIFF chunk.
  1140    err = WriteImage(picture, &bw, &coded_size);
  1141    if (err != VP8_ENC_OK) goto Error;
  1142  
  1143    if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort;
  1144  
  1145    // Save size.
  1146    if (picture->stats != NULL) {
  1147      picture->stats->coded_size += (int)coded_size;
  1148      picture->stats->lossless_size = (int)coded_size;
  1149    }
  1150  
  1151    if (picture->extra_info != NULL) {
  1152      const int mb_w = (width + 15) >> 4;
  1153      const int mb_h = (height + 15) >> 4;
  1154      memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info));
  1155    }
  1156  
  1157   Error:
  1158    if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
  1159    VP8LBitWriterDestroy(&bw);
  1160    if (err != VP8_ENC_OK) {
  1161      WebPEncodingSetError(picture, err);
  1162      return 0;
  1163    }
  1164    return 1;
  1165  }
  1166  
  1167  //------------------------------------------------------------------------------
  1168