15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2012 Google Inc. All Rights Reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// main entry for the lossless encoder.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Vikas Arora (vikaas.arora@gmail.com)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./backward_references.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8enci.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./vp8li.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../dsp/lossless.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../utils/bit_writer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../utils/huffman_encode.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../utils/utils.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../webp/format_constants.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PALETTE_KEY_RIGHT_SHIFT   22  // Key for 1K buffer.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_HUFF_IMAGE_SIZE       (16 * 1024 * 1024)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MAX_COLORS_FOR_GRAPH      64
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Palette
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CompareColors(const void* p1, const void* p2) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32_t a = *(const uint32_t*)p1;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32_t b = *(const uint32_t*)p2;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(a != b);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (a < b) ? -1 : 1;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// creates a palette and returns true, else returns false.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int AnalyzeAndCreatePalette(const WebPPicture* const pic,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   uint32_t palette[MAX_PALETTE_SIZE],
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int* const palette_size) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, x, y, key;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_colors = 0;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 };
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t colors[MAX_PALETTE_SIZE * 4];
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const uint32_t kHashMul = 0x1e35a7bd;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32_t* argb = pic->argb;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int width = pic->width;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int height = pic->height;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t last_pix = ~argb[0];   // so we're sure that last_pix != argb[0]
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (y = 0; y < height; ++y) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (x = 0; x < width; ++x) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (argb[x] == last_pix) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_pix = argb[x];
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (1) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!in_use[key]) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          colors[key] = last_pix;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          in_use[key] = 1;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++num_colors;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (num_colors > MAX_PALETTE_SIZE) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 0;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (colors[key] == last_pix) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // The color is already there.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Some other color sits there.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Do linear conflict resolution.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++key;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          key &= (MAX_PALETTE_SIZE * 4 - 1);  // key mask for 1K buffer.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    argb += pic->argb_stride;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(skal): could we reuse in_use[] to speed up EncodePalette()?
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_colors = 0;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (in_use[i]) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      palette[num_colors] = colors[i];
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++num_colors;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  qsort(palette, num_colors, sizeof(*palette), CompareColors);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *palette_size = num_colors;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int AnalyzeEntropy(const uint32_t* argb,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          int width, int height, int argb_stride,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          double* const nonpredicted_bits,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          double* const predicted_bits) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x, y;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32_t* last_line = NULL;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t last_pix = argb[0];    // so we're sure that pix_diff == 0
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHistogramSet* const histo_set = VP8LAllocateHistogramSet(2, 0);
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (histo_set == NULL) return 0;
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (y = 0; y < height; ++y) {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (x = 0; x < width; ++x) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t pix = argb[x];
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t pix_diff = VP8LSubPixels(pix, last_pix);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pix_diff == 0) continue;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (last_line != NULL && pix == last_line[x]) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_pix = pix;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff);
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VP8LHistogramAddSinglePixOrCopy(histo_set->histograms[0], &pix_token);
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        VP8LHistogramAddSinglePixOrCopy(histo_set->histograms[1],
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        &pix_diff_token);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_line = argb;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    argb += argb_stride;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(histo_set->histograms[0]);
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *predicted_bits = VP8LHistogramEstimateBitsBulk(histo_set->histograms[1]);
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LFreeHistogramSet(histo_set);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int AnalyzeAndInit(VP8LEncoder* const enc, WebPImageHint image_hint) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebPPicture* const pic = enc->pic_;
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int width = pic->width;
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int height = pic->height;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int pix_cnt = width * height;
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // we round the block size up, so we're guaranteed to have
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // at max MAX_REFS_BLOCK_PER_IMAGE blocks used:
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(pic != NULL && pic->argb != NULL);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enc->use_palette_ =
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (image_hint == WEBP_HINT_GRAPH) {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      enc->use_palette_ = 0;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!enc->use_palette_) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (image_hint == WEBP_HINT_PHOTO) {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      enc->use_predict_ = 1;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      enc->use_cross_color_ = 1;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double non_pred_entropy, pred_entropy;
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          &non_pred_entropy, &pred_entropy)) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pred_entropy < 0.95 * non_pred_entropy) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enc->use_predict_ = 1;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enc->use_cross_color_ = 1;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0;
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // palette-friendly input typically uses less literals
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  //  -> reduce block size a bit
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enc->use_palette_) refs_block_size /= 2;
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size);
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Returns false in case of memory error.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int GetHuffBitLengthsAndCodes(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const VP8LHistogramSet* const histogram_image,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HuffmanTreeCode* const huffman_codes) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, k;
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int ok = 0;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t total_length_size = 0;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t* mem_buf = NULL;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int histogram_image_size = histogram_image->size;
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int max_num_symbols = 0;
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint8_t* buf_rle = NULL;
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HuffmanTree* huff_tree = NULL;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterate over all histograms and get the aggregate number of codes used.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < histogram_image_size; ++i) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const VP8LHistogram* const histo = histogram_image->histograms[i];
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HuffmanTreeCode* const codes = &huffman_codes[5 * i];
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (k = 0; k < 5; ++k) {
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const int num_symbols =
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) :
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          (k == 4) ? NUM_DISTANCE_CODES : 256;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      codes[k].num_symbols = num_symbols;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_length_size += num_symbols;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate and Set Huffman codes.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16_t* codes;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8_t* lengths;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       sizeof(*lengths) + sizeof(*codes));
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (mem_buf == NULL) goto End;
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    codes = (uint16_t*)mem_buf;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lengths = (uint8_t*)&codes[total_length_size];
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < 5 * histogram_image_size; ++i) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int bit_length = huffman_codes[i].num_symbols;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      huffman_codes[i].codes = codes;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      huffman_codes[i].code_lengths = lengths;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      codes += bit_length;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lengths += bit_length;
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (max_num_symbols < bit_length) {
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        max_num_symbols = bit_length;
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols);
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols,
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           sizeof(*huff_tree));
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (buf_rle == NULL || huff_tree == NULL) goto End;
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create Huffman trees.
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (i = 0; i < histogram_image_size; ++i) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HuffmanTreeCode* const codes = &huffman_codes[5 * i];
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LHistogram* const histo = histogram_image->histograms[i];
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0);
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1);
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2);
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3);
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ok = 1;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) End:
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huff_tree);
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(buf_rle);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ok) {
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(mem_buf);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RFC 1951 will calm you down if you are worried about this funny sequence.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This sequence is tuned from that, but more weighted for lower symbol count,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and more spiking histograms.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Throw away trailing zeros:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int codes_to_store = CODE_LENGTH_CODES;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; codes_to_store > 4; --codes_to_store) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 4, codes_to_store - 4);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < codes_to_store; ++i) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 3, code_length_bitdepth[kStorageOrder[i]]);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ClearHuffmanTreeIfOnlyOneSymbol(
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HuffmanTreeCode* const huffman_code) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int k;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (k = 0; k < huffman_code->num_symbols; ++k) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (huffman_code->code_lengths[k] != 0) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++count;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (count > 1) return;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (k = 0; k < huffman_code->num_symbols; ++k) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    huffman_code->code_lengths[k] = 0;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    huffman_code->codes[k] = 0;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StoreHuffmanTreeToBitMask(
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LBitWriter* const bw,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HuffmanTreeToken* const tokens, const int num_tokens,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HuffmanTreeCode* const huffman_code) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < num_tokens; ++i) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int ix = tokens[i].code;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int extra_bits = tokens[i].extra_bits;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (ix) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 16:
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VP8LWriteBits(bw, 2, extra_bits);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 17:
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VP8LWriteBits(bw, 3, extra_bits);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 18:
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VP8LWriteBits(bw, 7, extra_bits);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// 'huff_tree' and 'tokens' are pre-alloacted buffers.
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void StoreFullHuffmanCode(VP8LBitWriter* const bw,
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 HuffmanTree* const huff_tree,
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 HuffmanTreeToken* const tokens,
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const HuffmanTreeCode* const tree) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int max_tokens = tree->num_symbols;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_tokens;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HuffmanTreeCode huffman_code;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  huffman_code.num_symbols = CODE_LENGTH_CODES;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  huffman_code.code_lengths = code_length_bitdepth;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  huffman_code.codes = code_length_bitdepth_symbols;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, 0);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint32_t histogram[CODE_LENGTH_CODES] = { 0 };
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 };
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_tokens; ++i) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++histogram[tokens[i].code];
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int trailing_zero_bits = 0;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int trimmed_length = num_tokens;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int write_trimmed_length;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int length;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i = num_tokens;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (i-- > 0) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int ix = tokens[i].code;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ix == 0 || ix == 17 || ix == 18) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        --trimmed_length;   // discount trailing zeros
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trailing_zero_bits += code_length_bitdepth[ix];
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ix == 17) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          trailing_zero_bits += 3;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (ix == 18) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          trailing_zero_bits += 7;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    length = write_trimmed_length ? trimmed_length : num_tokens;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 1, write_trimmed_length);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (write_trimmed_length) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 3, nbitpairs - 1);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(trimmed_length >= 2);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// 'huff_tree' and 'tokens' are pre-alloacted buffers.
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void StoreHuffmanCode(VP8LBitWriter* const bw,
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             HuffmanTree* const huff_tree,
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             HuffmanTreeToken* const tokens,
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             const HuffmanTreeCode* const huffman_code) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count = 0;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int symbols[2] = { 0, 0 };
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kMaxBits = 8;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kMaxSymbol = 1 << kMaxBits;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether it's a small tree.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (huffman_code->code_lengths[i] != 0) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (count < 2) symbols[count] = i;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++count;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (count == 0) {   // emit minimal tree for empty cases
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 4, 0x01);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 1, 1);  // Small tree marker to encode 1 or 2 symbols.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 1, count - 1);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (symbols[0] <= 1) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 1, 0);  // Code bit for small (1 bit) symbol value.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 1, symbols[0]);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 1, 1);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 8, symbols[0]);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count == 2) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 8, symbols[1]);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteHuffmanCode(VP8LBitWriter* const bw,
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const HuffmanTreeCode* const code,
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int code_index) {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int depth = code->code_lengths[code_index];
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int symbol = code->codes[code_index];
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, depth, symbol);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static WebPEncodingError StoreImageToBitMask(
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LBitWriter* const bw, int width, int histo_bits,
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LBackwardRefs* const refs,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint16_t* histogram_symbols,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HuffmanTreeCode* const huffman_codes) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // x and y trace the position in the image.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x = 0;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int y = 0;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LRefsCursor c = VP8LRefsCursorInit(refs);
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (VP8LRefsCursorOk(&c)) {
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const PixOrCopy* const v = c.cur_pos;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int histogram_ix = histogram_symbols[histo_bits ?
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               (y >> histo_bits) * histo_xsize +
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               (x >> histo_bits) : 0];
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (PixOrCopyIsCacheIdx(v)) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int code = PixOrCopyCacheIdx(v);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int literal_ix = 256 + NUM_LENGTH_CODES + code;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteHuffmanCode(bw, codes, literal_ix);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (PixOrCopyIsLiteral(v)) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static const int order[] = { 1, 2, 0, 3 };
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int k;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (k = 0; k < 4; ++k) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const int code = PixOrCopyLiteral(v, order[k]);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WriteHuffmanCode(bw, codes + k, code);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int bits, n_bits;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int code, distance;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteHuffmanCode(bw, codes, 256 + code);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, n_bits, bits);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      distance = PixOrCopyDistance(v);
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      VP8LPrefixEncode(distance, &code, &n_bits, &bits);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WriteHuffmanCode(bw, codes + 4, code);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, n_bits, bits);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x += PixOrCopyLength(v);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (x >= width) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      x -= width;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++y;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LRefsCursorNext(&c);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              const uint32_t* const argb,
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              VP8LHashChain* const hash_chain,
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              VP8LBackwardRefs refs_array[2],
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              int width, int height,
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              int quality) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int max_tokens = 0;
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LBackwardRefs* refs;
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HuffmanTreeToken* tokens = NULL;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } };
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint16_t histogram_symbols[1] = { 0 };    // only one tree, one symbol
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0);
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (histogram_image == NULL || huff_tree == NULL) {
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    goto Error;
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calculate backward references from ARGB image.
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, 1,
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   hash_chain, refs_array);
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (refs == NULL) {
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build histogram image and symbols from backward references.
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create Huffman bit lengths and codes for each histogram image.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(histogram_image->size == 1);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No color cache, no Huffman image.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, 0);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Find maximum number of symbols for the huffman tree-set.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 5; ++i) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HuffmanTreeCode* const codes = &huffman_codes[i];
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (max_tokens < codes->num_symbols) {
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      max_tokens = codes->num_symbols;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (tokens == NULL) {
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    goto Error;
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Store Huffman codes.
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (i = 0; i < 5; ++i) {
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    HuffmanTreeCode* const codes = &huffman_codes[i];
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    StoreHuffmanCode(bw, huff_tree, tokens, codes);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearHuffmanTreeIfOnlyOneSymbol(codes);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store actual literals.
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols,
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            huffman_codes);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(tokens);
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huff_tree);
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LFreeHistogramSet(histogram_image);
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huffman_codes[0].codes);
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return err;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw,
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             const uint32_t* const argb,
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             VP8LHashChain* const hash_chain,
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             VP8LBackwardRefs refs_array[2],
5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             int width, int height, int quality,
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             int cache_bits,
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             int histogram_bits) {
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int use_2d_locality = 1;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int use_color_cache = (cache_bits > 0);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint32_t histogram_image_xysize =
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LSubSampleSize(width, histogram_bits) *
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LSubSampleSize(height, histogram_bits);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LHistogramSet* histogram_image =
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8LAllocateHistogramSet(histogram_image_xysize, cache_bits);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int histogram_image_size = 0;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bit_array_size = 0;
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HuffmanTree* huff_tree = NULL;
5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  HuffmanTreeToken* tokens = NULL;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HuffmanTreeCode* huffman_codes = NULL;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBackwardRefs refs;
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LBackwardRefs* best_refs;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16_t* const histogram_symbols =
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (uint16_t*)WebPSafeMalloc(histogram_image_xysize,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                sizeof(*histogram_symbols));
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(histogram_bits >= MIN_HUFFMAN_BITS);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(histogram_bits <= MAX_HUFFMAN_BITS);
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LBackwardRefsInit(&refs, refs_array[0].block_size_);
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (histogram_image == NULL || histogram_symbols == NULL) {
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LFreeHistogramSet(histogram_image);
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(histogram_symbols);
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // 'best_refs' is the reference to the best backward refs and points to one
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // of refs_array[0] or refs_array[1].
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calculate backward references from ARGB image.
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  best_refs = VP8LGetBackwardReferences(width, height, argb, quality,
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        cache_bits, use_2d_locality,
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        hash_chain, refs_array);
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build histogram image and symbols from backward references.
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!VP8LGetHistoImageSymbols(width, height, &refs,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                quality, histogram_bits, cache_bits,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                histogram_image,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                histogram_symbols)) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create Huffman bit lengths and codes for each histogram image.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  histogram_image_size = histogram_image->size;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bit_array_size = 5 * histogram_image_size;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size,
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   sizeof(*huffman_codes));
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (huffman_codes == NULL ||
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Free combined histograms.
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LFreeHistogramSet(histogram_image);
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  histogram_image = NULL;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Color Cache parameters.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, use_color_cache);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (use_color_cache) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 4, cache_bits);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Huffman image + meta huffman.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int write_histogram_image = (histogram_image_size > 1);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LWriteBits(bw, 1, write_histogram_image);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (write_histogram_image) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32_t* const histogram_argb =
6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          (uint32_t*)WebPSafeMalloc(histogram_image_xysize,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    sizeof(*histogram_argb));
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int max_index = 0;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32_t i;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (histogram_argb == NULL) goto Error;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < histogram_image_xysize; ++i) {
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const int symbol_index = histogram_symbols[i] & 0xffff;
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        histogram_argb[i] = 0xff000000 | (symbol_index << 8);
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (symbol_index >= max_index) {
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          max_index = symbol_index + 1;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      histogram_image_size = max_index;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 3, histogram_bits - 2);
6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array,
6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 VP8LSubSampleSize(width, histogram_bits),
6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 VP8LSubSampleSize(height, histogram_bits),
6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 quality);
6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      WebPSafeFree(histogram_argb);
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (err != VP8_ENC_OK) goto Error;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store Huffman codes.
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int max_tokens = 0;
6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES,
6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             sizeof(*huff_tree));
6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (huff_tree == NULL) goto Error;
6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Find maximum number of symbols for the huffman tree-set.
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (i = 0; i < 5 * histogram_image_size; ++i) {
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      HuffmanTreeCode* const codes = &huffman_codes[i];
6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (max_tokens < codes->num_symbols) {
6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        max_tokens = codes->num_symbols;
6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
6685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
6695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens,
6705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                               sizeof(*tokens));
6715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (tokens == NULL) goto Error;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < 5 * histogram_image_size; ++i) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HuffmanTreeCode* const codes = &huffman_codes[i];
6745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      StoreHuffmanCode(bw, huff_tree, tokens, codes);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ClearHuffmanTreeIfOnlyOneSymbol(codes);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store actual literals.
6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  err = StoreImageToBitMask(bw, width, histogram_bits, &refs,
6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            histogram_symbols, huffman_codes);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(tokens);
6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(huff_tree);
6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LFreeHistogramSet(histogram_image);
6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LBackwardRefsClear(&refs);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (huffman_codes != NULL) {
6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(huffman_codes->codes);
6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(huffman_codes);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(histogram_symbols);
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return err;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Transforms
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check if it would be a good idea to subtract green from red and blue. We
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only impact entropy in red/blue components, don't bother to look at others.
7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static WebPEncodingError EvalAndApplySubtractGreen(VP8LEncoder* const enc,
7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                   int width, int height,
7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                   VP8LBitWriter* const bw) {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!enc->use_palette_) {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint32_t* const argb = enc->argb_;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double bit_cost_before, bit_cost_after;
7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Allocate histogram with cache_bits = 1.
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LHistogram* const histo = VP8LAllocateHistogram(1);
7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (histo == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < width * height; ++i) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t c = argb[i];
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++histo->red_[(c >> 16) & 0xff];
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++histo->blue_[(c >> 0) & 0xff];
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bit_cost_before = VP8LHistogramEstimateBits(histo);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VP8LHistogramInit(histo, 1);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < width * height; ++i) {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint32_t c = argb[i];
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int green = (c >> 8) & 0xff;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++histo->red_[((c >> 16) - green) & 0xff];
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++histo->blue_[((c >> 0) - green) & 0xff];
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bit_cost_after = VP8LHistogramEstimateBits(histo);
7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LFreeHistogram(histo);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if subtracting green yields low entropy.
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enc->use_subtract_green_ = (bit_cost_after < bit_cost_before);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enc->use_subtract_green_) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LWriteBits(bw, 2, SUBTRACT_GREEN);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return VP8_ENC_OK;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            int width, int height, int quality,
7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            VP8LBitWriter* const bw) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int pred_bits = enc->transform_bits_;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int transform_width = VP8LSubSampleSize(width, pred_bits);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int transform_height = VP8LSubSampleSize(height, pred_bits);
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    enc->transform_data_);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(pred_bits >= 2);
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 3, pred_bits - 2);
7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return EncodeImageNoHuffman(bw, enc->transform_data_,
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              (VP8LHashChain*)&enc->hash_chain_,
7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              (VP8LBackwardRefs*)enc->refs_,  // cast const away
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              transform_width, transform_height,
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              quality);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc,
7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                               int width, int height,
7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                               int quality,
7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                               VP8LBitWriter* const bw) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int ccolor_transform_bits = enc->transform_bits_;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality,
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          enc->argb_, enc->transform_data_);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(ccolor_transform_bits >= 2);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return EncodeImageNoHuffman(bw, enc->transform_data_,
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              (VP8LHashChain*)&enc->hash_chain_,
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              (VP8LBackwardRefs*)enc->refs_,  // cast const away
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              transform_width, transform_height,
7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              quality);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         size_t riff_size, size_t vp8l_size) {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE,
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PutLE32(riff + TAG_SIZE, (uint32_t)riff_size);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pic->writer(riff, sizeof(riff), pic)) {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return VP8_ENC_ERROR_BAD_WRITE;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return VP8_ENC_OK;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int WriteImageSize(const WebPPicture* const pic,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          VP8LBitWriter* const bw) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int width = pic->width - 1;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int height = pic->height - 1;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width);
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !bw->error_;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, has_alpha);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !bw->error_;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WebPEncodingError WriteImage(const WebPPicture* const pic,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    VP8LBitWriter* const bw,
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    size_t* const coded_size) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8_t* const webpll_data = VP8LBitWriterFinish(bw);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t webpll_size = VP8LBitWriterNumBytes(bw);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t pad = vp8l_size & 1;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = WriteRiffHeader(pic, riff_size, vp8l_size);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != VP8_ENC_OK) goto Error;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pic->writer(webpll_data, webpll_size, pic)) {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_BAD_WRITE;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pad) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint8_t pad_byte[1] = { 0 };
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pic->writer(pad_byte, 1, pic)) {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      err = VP8_ENC_ERROR_BAD_WRITE;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto Error;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *coded_size = CHUNK_HEADER_SIZE + riff_size;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return VP8_ENC_OK;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return err;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allocates the memory for argb (W x H) buffer, 2 rows of context for
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prediction and transform data.
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 int width, int height) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int tile_size = 1 << enc->transform_bits_;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t image_size = width * height;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t argb_scratch_size = tile_size * width + width;
8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int transform_data_size =
8565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8LSubSampleSize(width, enc->transform_bits_) *
8575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      VP8LSubSampleSize(height, enc->transform_bits_);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64_t total_size =
8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      image_size + argb_scratch_size + (uint64_t)transform_data_size;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem));
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mem == NULL) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->argb_ = mem;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem += image_size;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->argb_scratch_ = mem;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mem += argb_scratch_size;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->transform_data_ = mem;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->current_width_ = width;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return err;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void ApplyPalette(uint32_t* src, uint32_t* dst,
877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         uint32_t src_stride, uint32_t dst_stride,
878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         const uint32_t* palette, int palette_size,
879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         int width, int height, int xbits, uint8_t* row) {
880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int i, x, y;
881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int use_LUT = 1;
882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (i = 0; i < palette_size; ++i) {
883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if ((palette[i] & 0xffff00ffu) != 0) {
884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      use_LUT = 0;
885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (use_LUT) {
8905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint8_t inv_palette[MAX_PALETTE_SIZE] = { 0 };
891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (i = 0; i < palette_size; ++i) {
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const int color = (palette[i] >> 8) & 0xff;
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      inv_palette[color] = i;
894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (y = 0; y < height; ++y) {
896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      for (x = 0; x < width; ++x) {
897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        const int color = (src[x] >> 8) & 0xff;
898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        row[x] = inv_palette[color];
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      VP8LBundleColorMap(row, width, xbits, dst);
901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      src += src_stride;
902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dst += dst_stride;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Use 1 pixel cache for ARGB pixels.
906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    uint32_t last_pix = palette[0];
907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int last_idx = 0;
908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (y = 0; y < height; ++y) {
909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      for (x = 0; x < width; ++x) {
910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        const uint32_t pix = src[x];
911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (pix != last_pix) {
912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          for (i = 0; i < palette_size; ++i) {
913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            if (pix == palette[i]) {
914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              last_idx = i;
915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              last_pix = pix;
916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              break;
917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            }
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          }
919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        row[x] = last_idx;
921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      VP8LBundleColorMap(row, width, xbits, dst);
923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      src += src_stride;
924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dst += dst_stride;
925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Expects "enc->palette_" to be set properly.
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Also, "enc->palette_" will be modified after this call and should not be used
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// later.
932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic WebPEncodingError EncodePalette(VP8LBitWriter* const bw,
933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       VP8LEncoder* const enc, int quality) {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int i;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebPPicture* const pic = enc->pic_;
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint32_t* src = pic->argb;
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint32_t* dst;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int width = pic->width;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int height = pic->height;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t* const palette = enc->palette_;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int palette_size = enc->palette_size_;
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8_t* row = NULL;
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int xbits;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace each input pixel by corresponding palette index.
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is done line by line.
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (palette_size <= 4) {
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    xbits = (palette_size <= 2) ? 3 : 2;
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    xbits = (palette_size <= 16) ? 1 : 0;
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (err != VP8_ENC_OK) goto Error;
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dst = enc->argb_;
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  row = (uint8_t*)WebPSafeMalloc(width, sizeof(*row));
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ApplyPalette(src, dst, pic->argb_stride, enc->current_width_,
962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch               palette, palette_size, width, height, xbits, row);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save palette to bitstream.
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, TRANSFORM_PRESENT);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(palette_size >= 1);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 8, palette_size - 1);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = palette_size - 1; i >= 1; --i) {
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  err = EncodeImageNoHuffman(bw, palette, &enc->hash_chain_, enc->refs_,
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             palette_size, 1, quality);
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WebPSafeFree(row);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return err;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int GetHistoBits(int method, int use_palette, int width, int height) {
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int hist_size = VP8LGetHistogramSize(MAX_COLOR_CACHE_BITS);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make tile size a function of encoding method (Range: 0 to 6).
985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int histo_bits = (use_palette ? 9 : 7) - method;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (1) {
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const int huff_image_size = VP8LSubSampleSize(width, histo_bits) *
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                VP8LSubSampleSize(height, histo_bits);
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((uint64_t)huff_image_size * hist_size <= MAX_HUFF_IMAGE_SIZE) break;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++histo_bits;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS :
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int GetTransformBits(int method, int histo_bits) {
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5;
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits;
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int GetCacheBits(float quality) {
10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return (quality <= 25.f) ? 0 : 7;
10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void FinishEncParams(VP8LEncoder* const enc) {
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WebPConfig* const config = enc->config_;
1007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const WebPPicture* const pic = enc->pic_;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int method = config->method;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const float quality = config->quality;
1010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int use_palette = enc->use_palette_;
1011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  enc->histo_bits_ = GetHistoBits(method, use_palette, pic->width, pic->height);
10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_);
10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  enc->cache_bits_ = GetCacheBits(quality);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VP8LEncoder
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config,
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const WebPPicture* const picture) {
10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc));
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc == NULL) {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->config_ = config;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enc->pic_ = picture;
10285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VP8LDspInit();
10305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return enc;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void VP8LEncoderDelete(VP8LEncoder* enc) {
10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enc != NULL) {
10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LHashChainClear(&enc->hash_chain_);
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LBackwardRefsClear(&enc->refs_[0]);
10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VP8LBackwardRefsClear(&enc->refs_[1]);
10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(enc->argb_);
10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WebPSafeFree(enc);
10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------------------------------------------------------------------
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main call
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const WebPPicture* const picture,
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   VP8LBitWriter* const bw) {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int quality = (int)config->quality;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int width = picture->width;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int height = picture->height;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t byte_position = VP8LBitWriterNumBytes(bw);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc == NULL) {
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ---------------------------------------------------------------------------
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Analyze image (entropy, num_palettes etc)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!AnalyzeAndInit(enc, config->image_hint)) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FinishEncParams(enc);
1071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc->use_palette_) {
1073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    err = EncodePalette(bw, enc, quality);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (err != VP8_ENC_OK) goto Error;
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Color cache is disabled for palette.
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enc->cache_bits_ = 0;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case image is not packed.
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc->argb_ == NULL) {
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int y;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = AllocateTransformBuffer(enc, width, height);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (err != VP8_ENC_OK) goto Error;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (y = 0; y < height; ++y) {
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(enc->argb_ + y * width,
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             picture->argb + y * picture->argb_stride,
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             width * sizeof(*enc->argb_));
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enc->current_width_ = width;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ---------------------------------------------------------------------------
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply transforms and write transform data.
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  err = EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw);
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (err != VP8_ENC_OK) goto Error;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc->use_predict_) {
10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    err = ApplyPredictFilter(enc, enc->current_width_, height, quality, bw);
11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (err != VP8_ENC_OK) goto Error;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc->use_cross_color_) {
11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    err = ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw);
11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (err != VP8_ENC_OK) goto Error;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT);  // No more transforms.
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ---------------------------------------------------------------------------
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Estimate the color cache size.
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enc->cache_bits_ > 0) {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_,
11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           height, quality, &enc->hash_chain_,
11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           &enc->refs_[0], &enc->cache_bits_)) {
11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      err = VP8_ENC_ERROR_OUT_OF_MEMORY;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto Error;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ---------------------------------------------------------------------------
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Encode and write the transformed image.
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_,
11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            enc->current_width_, height, quality,
11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            enc->cache_bits_, enc->histo_bits_);
11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (err != VP8_ENC_OK) goto Error;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (picture->stats != NULL) {
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPAuxStats* const stats = picture->stats;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->lossless_features = 0;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enc->use_predict_) stats->lossless_features |= 1;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enc->use_cross_color_) stats->lossless_features |= 2;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enc->use_subtract_green_) stats->lossless_features |= 4;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enc->use_palette_) stats->lossless_features |= 8;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->histogram_bits = enc->histo_bits_;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->transform_bits = enc->transform_bits_;
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->cache_bits = enc->cache_bits_;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->palette_size = enc->palette_size_;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LEncoderDelete(enc);
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return err;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VP8LEncodeImage(const WebPConfig* const config,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const WebPPicture* const picture) {
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width, height;
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int has_alpha;
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t coded_size;
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int percent = 0;
11555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int initial_size;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebPEncodingError err = VP8_ENC_OK;
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitWriter bw;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (picture == NULL) return 0;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config == NULL || picture->argb == NULL) {
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_NULL_PARAMETER;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPEncodingSetError(picture, err);
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  width = picture->width;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  height = picture->height;
11695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Initialize BitWriter with size corresponding to 16 bpp to photo images and
11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // 8 bpp for graphical images.
11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  initial_size = (config->image_hint == WEBP_HINT_GRAPH) ?
11725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 width * height : width * height * 2;
11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!VP8LBitWriterInit(&bw, initial_size)) {
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WebPReportProgress(picture, 1, &percent)) {
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserAbort:
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_USER_ABORT;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset stats (for pure lossless coding)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (picture->stats != NULL) {
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPAuxStats* const stats = picture->stats;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(stats, 0, sizeof(*stats));
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->PSNR[0] = 99.f;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->PSNR[1] = 99.f;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->PSNR[2] = 99.f;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->PSNR[3] = 99.f;
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stats->PSNR[4] = 99.f;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write image size.
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WriteImageSize(picture, &bw)) {
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_alpha = WebPPictureHasTransparency(picture);
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the non-trivial Alpha flag and lossless version.
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WriteRealAlphaAndVersion(&bw, has_alpha)) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = VP8_ENC_ERROR_OUT_OF_MEMORY;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto Error;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort;
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Encode main image stream.
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = VP8LEncodeStream(config, picture, &bw);
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != VP8_ENC_OK) goto Error;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finish the RIFF chunk.
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = WriteImage(picture, &bw, &coded_size);
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != VP8_ENC_OK) goto Error;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort;
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save size.
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (picture->stats != NULL) {
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    picture->stats->coded_size += (int)coded_size;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    picture->stats->lossless_size = (int)coded_size;
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (picture->extra_info != NULL) {
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int mb_w = (width + 15) >> 4;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int mb_h = (height + 15) >> 4;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info));
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Error:
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY;
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VP8LBitWriterDestroy(&bw);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err != VP8_ENC_OK) {
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebPEncodingSetError(picture, err);
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1245