15a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved. 25a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// 35a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// This code is licensed under the same terms as WebM: 45a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Software License Agreement: http://www.webmproject.org/license/software/ 55a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 65a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 75a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// 85a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// main entry for the lossless encoder. 95a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// 105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Author: Vikas Arora (vikaas.arora@gmail.com) 115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// 125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include <assert.h> 145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include <stdio.h> 155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include <stdlib.h> 165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./backward_references.h" 185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./vp8enci.h" 195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./vp8li.h" 205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../dsp/lossless.h" 215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../utils/bit_writer.h" 225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../utils/huffman_encode.h" 235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../utils/utils.h" 245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "webp/format_constants.h" 255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 275a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraextern "C" { 285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif 295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. 315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define MAX_HUFF_IMAGE_SIZE (16 * 1024 * 1024) 325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define MAX_COLORS_FOR_GRAPH 64 335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Palette 365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 375a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int CompareColors(const void* p1, const void* p2) { 385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t a = *(const uint32_t*)p1; 395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t b = *(const uint32_t*)p2; 405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return (a < b) ? -1 : (a > b) ? 1 : 0; 415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, 445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// creates a palette and returns true, else returns false. 455a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int AnalyzeAndCreatePalette(const WebPPicture* const pic, 465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t palette[MAX_PALETTE_SIZE], 475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int* const palette_size) { 485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i, x, y, key; 495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int num_colors = 0; 505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t in_use[MAX_PALETTE_SIZE * 4] = { 0 }; 515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t colors[MAX_PALETTE_SIZE * 4]; 525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora static const uint32_t kHashMul = 0x1e35a7bd; 535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t* argb = pic->argb; 545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int width = pic->width; 555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int height = pic->height; 565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] 575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (y = 0; y < height; ++y) { 595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (x = 0; x < width; ++x) { 605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (argb[x] == last_pix) { 615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora continue; 625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora last_pix = argb[x]; 645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora key = (kHashMul * last_pix) >> PALETTE_KEY_RIGHT_SHIFT; 655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora while (1) { 665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!in_use[key]) { 675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora colors[key] = last_pix; 685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora in_use[key] = 1; 695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++num_colors; 705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (num_colors > MAX_PALETTE_SIZE) { 715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else if (colors[key] == last_pix) { 755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // The color is already there. 765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Some other color sits there. 795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Do linear conflict resolution. 805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++key; 815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora key &= (MAX_PALETTE_SIZE * 4 - 1); // key mask for 1K buffer. 825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora argb += pic->argb_stride; 865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // TODO(skal): could we reuse in_use[] to speed up ApplyPalette()? 895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora num_colors = 0; 905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < (int)(sizeof(in_use) / sizeof(in_use[0])); ++i) { 915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (in_use[i]) { 925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora palette[num_colors] = colors[i]; 935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++num_colors; 945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora qsort(palette, num_colors, sizeof(*palette), CompareColors); 985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora *palette_size = num_colors; 995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 1005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 1015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1025a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int AnalyzeEntropy(const uint32_t* argb, 1035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height, int argb_stride, 1045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora double* const nonpredicted_bits, 1055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora double* const predicted_bits) { 1065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int x, y; 1075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t* last_line = NULL; 1085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t last_pix = argb[0]; // so we're sure that pix_diff == 0 1095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogram* nonpredicted = NULL; 1115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogram* predicted = 1125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (VP8LHistogram*)malloc(2 * sizeof(*predicted)); 1135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (predicted == NULL) return 0; 1145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora nonpredicted = predicted + 1; 1155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramInit(predicted, 0); 1175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramInit(nonpredicted, 0); 1185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (y = 0; y < height; ++y) { 1195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (x = 0; x < width; ++x) { 1205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t pix = argb[x]; 1215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t pix_diff = VP8LSubPixels(pix, last_pix); 1225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (pix_diff == 0) continue; 1235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (last_line != NULL && pix == last_line[x]) { 1245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora continue; 1255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora last_pix = pix; 1275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora { 1285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix); 1295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff); 1305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramAddSinglePixOrCopy(nonpredicted, &pix_token); 1315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramAddSinglePixOrCopy(predicted, &pix_diff_token); 1325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora last_line = argb; 1355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora argb += argb_stride; 1365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(nonpredicted); 1385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora *predicted_bits = VP8LHistogramEstimateBitsBulk(predicted); 1395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(predicted); 1405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 1415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 1425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1435a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int VP8LEncAnalyze(VP8LEncoder* const enc, WebPImageHint image_hint) { 1445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const pic = enc->pic_; 1455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(pic != NULL && pic->argb != NULL); 1465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_palette_ = 1485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora AnalyzeAndCreatePalette(pic, enc->palette_, &enc->palette_size_); 1495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (image_hint == WEBP_HINT_GRAPH) { 1515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_palette_ && enc->palette_size_ < MAX_COLORS_FOR_GRAPH) { 1525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_palette_ = 0; 1535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!enc->use_palette_) { 1575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (image_hint == WEBP_HINT_PHOTO) { 1585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_predict_ = 1; 1595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_cross_color_ = 1; 1605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 1615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora double non_pred_entropy, pred_entropy; 1625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!AnalyzeEntropy(pic->argb, pic->width, pic->height, pic->argb_stride, 1635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora &non_pred_entropy, &pred_entropy)) { 1645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 1655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (pred_entropy < 0.95 * non_pred_entropy) { 1675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_predict_ = 1; 1685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // TODO(vikasa): Observed some correlation of cross_color transform with 1695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // predict. Need to investigate this further and add separate heuristic 1705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // for setting use_cross_color flag. 1715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_cross_color_ = 1; 1725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 1775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 1785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1795a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int GetHuffBitLengthsAndCodes( 1805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const VP8LHistogramSet* const histogram_image, 1815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* const huffman_codes) { 1825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i, k; 1835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int ok = 1; 1845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint64_t total_length_size = 0; 1855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* mem_buf = NULL; 1865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int histogram_image_size = histogram_image->size; 1875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 1885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Iterate over all histograms and get the aggregate number of codes used. 1895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < histogram_image_size; ++i) { 1905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const VP8LHistogram* const histo = histogram_image->histograms[i]; 1915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* const codes = &huffman_codes[5 * i]; 1925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (k = 0; k < 5; ++k) { 1935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int num_symbols = (k == 0) ? VP8LHistogramNumCodes(histo) 1945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora : (k == 4) ? NUM_DISTANCE_CODES 1955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora : 256; 1965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora codes[k].num_symbols = num_symbols; 1975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora total_length_size += num_symbols; 1985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 1995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Allocate and Set Huffman codes. 2025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora { 2035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint16_t* codes; 2045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t* lengths; 2055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, 2065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora sizeof(*lengths) + sizeof(*codes)); 2075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (mem_buf == NULL) { 2085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = 0; 2095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto End; 2105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora codes = (uint16_t*)mem_buf; 2125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora lengths = (uint8_t*)&codes[total_length_size]; 2135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < 5 * histogram_image_size; ++i) { 2145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int bit_length = huffman_codes[i].num_symbols; 2155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_codes[i].codes = codes; 2165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_codes[i].code_lengths = lengths; 2175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora codes += bit_length; 2185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora lengths += bit_length; 2195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Create Huffman trees. 2235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < histogram_image_size; ++i) { 2245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* const codes = &huffman_codes[5 * i]; 2255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogram* const histo = histogram_image->histograms[i]; 2265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = ok && VP8LCreateHuffmanTree(histo->literal_, 15, codes + 0); 2275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = ok && VP8LCreateHuffmanTree(histo->red_, 15, codes + 1); 2285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = ok && VP8LCreateHuffmanTree(histo->blue_, 15, codes + 2); 2295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = ok && VP8LCreateHuffmanTree(histo->alpha_, 15, codes + 3); 2305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = ok && VP8LCreateHuffmanTree(histo->distance_, 15, codes + 4); 2315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora End: 2345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!ok) free(mem_buf); 2355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return ok; 2365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 2375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2385a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void StoreHuffmanTreeOfHuffmanTreeToBitMask( 2395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { 2405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // RFC 1951 will calm you down if you are worried about this funny sequence. 2415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // This sequence is tuned from that, but more weighted for lower symbol count, 2425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // and more spiking histograms. 2435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { 2445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 2455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora }; 2465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 2475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Throw away trailing zeros: 2485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int codes_to_store = CODE_LENGTH_CODES; 2495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (; codes_to_store > 4; --codes_to_store) { 2505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { 2515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 2525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 4, codes_to_store - 4); 2555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < codes_to_store; ++i) { 2565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 3, code_length_bitdepth[kStorageOrder[i]]); 2575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 2595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2605a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ClearHuffmanTreeIfOnlyOneSymbol( 2615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* const huffman_code) { 2625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int k; 2635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int count = 0; 2645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (k = 0; k < huffman_code->num_symbols; ++k) { 2655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (huffman_code->code_lengths[k] != 0) { 2665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++count; 2675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (count > 1) return; 2685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (k = 0; k < huffman_code->num_symbols; ++k) { 2715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_code->code_lengths[k] = 0; 2725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_code->codes[k] = 0; 2735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 2755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2765a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void StoreHuffmanTreeToBitMask( 2775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw, 2785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeToken* const tokens, const int num_tokens, 2795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeCode* const huffman_code) { 2805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 2815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < num_tokens; ++i) { 2825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int ix = tokens[i].code; 2835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int extra_bits = tokens[i].extra_bits; 2845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]); 2855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora switch (ix) { 2865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora case 16: 2875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 2, extra_bits); 2885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 2895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora case 17: 2905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 3, extra_bits); 2915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 2925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora case 18: 2935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 7, extra_bits); 2945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 2955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 2975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 2985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 2995a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int StoreFullHuffmanCode(VP8LBitWriter* const bw, 3005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeCode* const tree) { 3015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int ok = 0; 3025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; 3035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; 3045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int max_tokens = tree->num_symbols; 3055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int num_tokens; 3065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode huffman_code; 3075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeToken* const tokens = 3085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (HuffmanTreeToken*)WebPSafeMalloc((uint64_t)max_tokens, sizeof(*tokens)); 3095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (tokens == NULL) return 0; 3105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_code.num_symbols = CODE_LENGTH_CODES; 3125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_code.code_lengths = code_length_bitdepth; 3135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_code.codes = code_length_bitdepth_symbols; 3145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, 0); 3165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); 3175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora { 3185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int histogram[CODE_LENGTH_CODES] = { 0 }; 3195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 3205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < num_tokens; ++i) { 3215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++histogram[tokens[i].code]; 3225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LCreateHuffmanTree(histogram, 7, &huffman_code)) { 3255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto End; 3265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); 3305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); 3315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora { 3325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int trailing_zero_bits = 0; 3335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int trimmed_length = num_tokens; 3345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int write_trimmed_length; 3355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int length; 3365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i = num_tokens; 3375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora while (i-- > 0) { 3385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int ix = tokens[i].code; 3395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (ix == 0 || ix == 17 || ix == 18) { 3405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora --trimmed_length; // discount trailing zeros 3415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora trailing_zero_bits += code_length_bitdepth[ix]; 3425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (ix == 17) { 3435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora trailing_zero_bits += 3; 3445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else if (ix == 18) { 3455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora trailing_zero_bits += 7; 3465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 3485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 3495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); 3525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora length = write_trimmed_length ? trimmed_length : num_tokens; 3535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, write_trimmed_length); 3545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (write_trimmed_length) { 3555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); 3565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; 3575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 3, nbitpairs - 1); 3585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(trimmed_length >= 2); 3595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2); 3605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); 3625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = 1; 3645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora End: 3655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(tokens); 3665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return ok; 3675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 3685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3695a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int StoreHuffmanCode(VP8LBitWriter* const bw, 3705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeCode* const huffman_code) { 3715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 3725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int count = 0; 3735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int symbols[2] = { 0, 0 }; 3745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int kMaxBits = 8; 3755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int kMaxSymbol = 1 << kMaxBits; 3765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Check whether it's a small tree. 3785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { 3795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (huffman_code->code_lengths[i] != 0) { 3805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (count < 2) symbols[count] = i; 3815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++count; 3825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 3855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (count == 0) { // emit minimal tree for empty cases 3865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 3875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 4, 0x01); 3885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 3895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { 3905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. 3915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, count - 1); 3925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (symbols[0] <= 1) { 3935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, 0); // Code bit for small (1 bit) symbol value. 3945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, symbols[0]); 3955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 3965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, 1); 3975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 8, symbols[0]); 3985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 3995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (count == 2) { 4005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 8, symbols[1]); 4015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 4035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 4045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return StoreFullHuffmanCode(bw, huffman_code); 4055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 4075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4085a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void WriteHuffmanCode(VP8LBitWriter* const bw, 4095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeCode* const code, int index) { 4105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int depth = code->code_lengths[index]; 4115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int symbol = code->codes[index]; 4125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, depth, symbol); 4135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 4145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4155a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void StoreImageToBitMask( 4165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw, int width, int histo_bits, 4175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const VP8LBackwardRefs* const refs, 4185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint16_t* histogram_symbols, 4195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeCode* const huffman_codes) { 4205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // x and y trace the position in the image. 4215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int x = 0; 4225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int y = 0; 4235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; 4245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 4255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < refs->size; ++i) { 4265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const PixOrCopy* const v = &refs->refs[i]; 4275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int histogram_ix = histogram_symbols[histo_bits ? 4285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (y >> histo_bits) * histo_xsize + 4295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (x >> histo_bits) : 0]; 4305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const HuffmanTreeCode* const codes = huffman_codes + 5 * histogram_ix; 4315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (PixOrCopyIsCacheIdx(v)) { 4325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int code = PixOrCopyCacheIdx(v); 4335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int literal_ix = 256 + NUM_LENGTH_CODES + code; 4345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WriteHuffmanCode(bw, codes, literal_ix); 4355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else if (PixOrCopyIsLiteral(v)) { 4365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora static const int order[] = { 1, 2, 0, 3 }; 4375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int k; 4385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (k = 0; k < 4; ++k) { 4395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int code = PixOrCopyLiteral(v, order[k]); 4405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WriteHuffmanCode(bw, codes + k, code); 4415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else { 4435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int bits, n_bits; 4445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int code, distance; 4455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora PrefixEncode(v->len, &code, &n_bits, &bits); 4475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WriteHuffmanCode(bw, codes, 256 + code); 4485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, n_bits, bits); 4495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora distance = PixOrCopyDistance(v); 4515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora PrefixEncode(distance, &code, &n_bits, &bits); 4525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WriteHuffmanCode(bw, codes + 4, code); 4535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, n_bits, bits); 4545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora x += PixOrCopyLength(v); 4565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora while (x >= width) { 4575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora x -= width; 4585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++y; 4595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 4625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 4645a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int EncodeImageNoHuffman(VP8LBitWriter* const bw, 4655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t* const argb, 4665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height, int quality) { 4675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 4685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int ok = 0; 4695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBackwardRefs refs; 4705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } }; 4715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol 4725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramSet* const histogram_image = VP8LAllocateHistogramSet(1, 0); 4735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (histogram_image == NULL) return 0; 4745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Calculate backward references from ARGB image. 4765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LGetBackwardReferences(width, height, argb, quality, 0, 1, &refs)) { 4775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 4785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Build histogram image and symbols from backward references. 4805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramStoreRefs(&refs, histogram_image->histograms[0]); 4815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Create Huffman bit lengths and codes for each histogram image. 4835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(histogram_image->size == 1); 4845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { 4855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 4865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // No color cache, no Huffman image. 4895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, 0); 4905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 4915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Store Huffman codes. 4925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < 5; ++i) { 4935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* const codes = &huffman_codes[i]; 4945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!StoreHuffmanCode(bw, codes)) { 4955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 4965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ClearHuffmanTreeIfOnlyOneSymbol(codes); 4985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 4995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Store actual literals. 5015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora StoreImageToBitMask(bw, width, 0, &refs, histogram_symbols, huffman_codes); 5025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = 1; 5035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 5055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(histogram_image); 5065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LClearBackwardRefs(&refs); 5075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(huffman_codes[0].codes); 5085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return ok; 5095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 5105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5115a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int EncodeImageInternal(VP8LBitWriter* const bw, 5125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t* const argb, 5135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height, int quality, 5145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int cache_bits, int histogram_bits) { 5155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int ok = 0; 5165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int use_2d_locality = 1; 5175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int use_color_cache = (cache_bits > 0); 5185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t histogram_image_xysize = 5195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LSubSampleSize(width, histogram_bits) * 5205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LSubSampleSize(height, histogram_bits); 5215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramSet* histogram_image = 5225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LAllocateHistogramSet(histogram_image_xysize, 0); 5235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int histogram_image_size = 0; 5245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t bit_array_size = 0; 5255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* huffman_codes = NULL; 5265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBackwardRefs refs; 5275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint16_t* const histogram_symbols = 5285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (uint16_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize, 5295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora sizeof(*histogram_symbols)); 5305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(histogram_bits >= MIN_HUFFMAN_BITS); 5315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(histogram_bits <= MAX_HUFFMAN_BITS); 5325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (histogram_image == NULL || histogram_symbols == NULL) goto Error; 5335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Calculate backward references from ARGB image. 5355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LGetBackwardReferences(width, height, argb, quality, cache_bits, 5365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora use_2d_locality, &refs)) { 5375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 5385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Build histogram image and symbols from backward references. 5405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LGetHistoImageSymbols(width, height, &refs, 5415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora quality, histogram_bits, cache_bits, 5425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_image, 5435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_symbols)) { 5445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 5455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Create Huffman bit lengths and codes for each histogram image. 5475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_image_size = histogram_image->size; 5485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora bit_array_size = 5 * histogram_image_size; 5495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, 5505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora sizeof(*huffman_codes)); 5515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (huffman_codes == NULL || 5525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { 5535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 5545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Color Cache parameters. 5575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, use_color_cache); 5585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (use_color_cache) { 5595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 4, cache_bits); 5605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Huffman image + meta huffman. 5635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora { 5645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int write_histogram_image = (histogram_image_size > 1); 5655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, write_histogram_image); 5665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (write_histogram_image) { 5675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t* const histogram_argb = 5685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (uint32_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize, 5695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora sizeof(*histogram_argb)); 5705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int max_index = 0; 5715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t i; 5725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (histogram_argb == NULL) goto Error; 5735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < histogram_image_xysize; ++i) { 5745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int index = histogram_symbols[i] & 0xffff; 5755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_argb[i] = 0xff000000 | (index << 8); 5765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (index >= max_index) { 5775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora max_index = index + 1; 5785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_image_size = max_index; 5815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 3, histogram_bits - 2); 5835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = EncodeImageNoHuffman(bw, histogram_argb, 5845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LSubSampleSize(width, histogram_bits), 5855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LSubSampleSize(height, histogram_bits), 5865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora quality); 5875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(histogram_argb); 5885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!ok) goto Error; 5895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 5915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 5925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Store Huffman codes. 5935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora { 5945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 5955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < 5 * histogram_image_size; ++i) { 5965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora HuffmanTreeCode* const codes = &huffman_codes[i]; 5975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!StoreHuffmanCode(bw, codes)) goto Error; 5985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ClearHuffmanTreeIfOnlyOneSymbol(codes); 5995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Free combined histograms. 6025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(histogram_image); 6035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_image = NULL; 6045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Store actual literals. 6065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora StoreImageToBitMask(bw, width, histogram_bits, &refs, 6075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora histogram_symbols, huffman_codes); 6085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ok = 1; 6095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 6115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!ok) free(histogram_image); 6125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LClearBackwardRefs(&refs); 6145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (huffman_codes != NULL) { 6155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(huffman_codes->codes); 6165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(huffman_codes); 6175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(histogram_symbols); 6195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return ok; 6205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 6215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 6235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Transforms 6245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Check if it would be a good idea to subtract green from red and blue. We 6265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// only impact entropy in red/blue components, don't bother to look at others. 6275a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int EvalAndApplySubtractGreen(VP8LEncoder* const enc, 6285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height, 6295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw) { 6305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!enc->use_palette_) { 6315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i; 6325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t* const argb = enc->argb_; 6335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora double bit_cost_before, bit_cost_after; 6345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogram* const histo = (VP8LHistogram*)malloc(sizeof(*histo)); 6355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (histo == NULL) return 0; 6365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramInit(histo, 1); 6385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < width * height; ++i) { 6395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t c = argb[i]; 6405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++histo->red_[(c >> 16) & 0xff]; 6415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++histo->blue_[(c >> 0) & 0xff]; 6425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora bit_cost_before = VP8LHistogramEstimateBits(histo); 6445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LHistogramInit(histo, 1); 6465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < width * height; ++i) { 6475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t c = argb[i]; 6485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int green = (c >> 8) & 0xff; 6495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++histo->red_[((c >> 16) - green) & 0xff]; 6505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++histo->blue_[((c >> 0) - green) & 0xff]; 6515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora bit_cost_after = VP8LHistogramEstimateBits(histo); 6535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(histo); 6545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Check if subtracting green yields low entropy. 6565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->use_subtract_green_ = (bit_cost_after < bit_cost_before); 6575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_subtract_green_) { 6585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); 6595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 2, SUBTRACT_GREEN); 6605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); 6615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 6645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 6655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6665a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int ApplyPredictFilter(const VP8LEncoder* const enc, 6675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height, int quality, 6685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw) { 6695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int pred_bits = enc->transform_bits_; 6705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int transform_width = VP8LSubSampleSize(width, pred_bits); 6715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int transform_height = VP8LSubSampleSize(height, pred_bits); 6725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_, 6745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->transform_data_); 6755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); 6765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 2, PREDICTOR_TRANSFORM); 6775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(pred_bits >= 2); 6785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 3, pred_bits - 2); 6795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!EncodeImageNoHuffman(bw, enc->transform_data_, 6805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora transform_width, transform_height, quality)) { 6815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 6825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 6835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 6845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 6855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6865a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int ApplyCrossColorFilter(const VP8LEncoder* const enc, 6875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height, int quality, 6885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw) { 6895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int ccolor_transform_bits = enc->transform_bits_; 6905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); 6915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); 6925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int step = (quality == 0) ? 32 : 8; 6935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 6945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LColorSpaceTransform(width, height, ccolor_transform_bits, step, 6955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->argb_, enc->transform_data_); 6965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); 6975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 2, CROSS_COLOR_TRANSFORM); 6985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(ccolor_transform_bits >= 2); 6995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 3, ccolor_transform_bits - 2); 7005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!EncodeImageNoHuffman(bw, enc->transform_data_, 7015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora transform_width, transform_height, quality)) { 7025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 7035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 7055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 7065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 7085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7095a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void PutLE32(uint8_t* const data, uint32_t val) { 7105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora data[0] = (val >> 0) & 0xff; 7115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora data[1] = (val >> 8) & 0xff; 7125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora data[2] = (val >> 16) & 0xff; 7135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora data[3] = (val >> 24) & 0xff; 7145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 7155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7165a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, 7175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t riff_size, size_t vp8l_size) { 7185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { 7195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', 7205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, 7215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora }; 7225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); 7235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); 7245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!pic->writer(riff, sizeof(riff), pic)) { 7255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_ENC_ERROR_BAD_WRITE; 7265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_ENC_OK; 7285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 7295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7305a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int WriteImageSize(const WebPPicture* const pic, 7315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw) { 7325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int width = pic->width - 1; 7335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int height = pic->height - 1; 7345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); 7355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, width); 7375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, VP8L_IMAGE_SIZE_BITS, height); 7385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return !bw->error_; 7395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 7405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7415a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { 7425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, has_alpha); 7435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, VP8L_VERSION_BITS, VP8L_VERSION); 7445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return !bw->error_; 7455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 7465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7475a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WebPEncodingError WriteImage(const WebPPicture* const pic, 7485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw, 7495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t* const coded_size) { 7505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingError err = VP8_ENC_OK; 7515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); 7525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t webpll_size = VP8LBitWriterNumBytes(bw); 7535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; 7545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t pad = vp8l_size & 1; 7555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; 7565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = WriteRiffHeader(pic, riff_size, vp8l_size); 7585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) goto Error; 7595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!pic->writer(webpll_data, webpll_size, pic)) { 7615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_BAD_WRITE; 7625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 7635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (pad) { 7665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint8_t pad_byte[1] = { 0 }; 7675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!pic->writer(pad_byte, 1, pic)) { 7685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_BAD_WRITE; 7695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 7705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora *coded_size = CHUNK_HEADER_SIZE + riff_size; 7735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return VP8_ENC_OK; 7745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 7765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return err; 7775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 7785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 7805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 7815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Allocates the memory for argb (W x H) buffer, 2 rows of context for 7825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// prediction and transform data. 7835a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, 7845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, int height) { 7855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingError err = VP8_ENC_OK; 7865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int tile_size = 1 << enc->transform_bits_; 7875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint64_t image_size = width * height; 7885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint64_t argb_scratch_size = tile_size * width + width; 7895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint64_t transform_data_size = 7905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) * 7915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (uint64_t)VP8LSubSampleSize(height, enc->transform_bits_); 7925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint64_t total_size = 7935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora image_size + argb_scratch_size + transform_data_size; 7945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t* mem = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*mem)); 7955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (mem == NULL) { 7965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 7975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 7985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 7995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->argb_ = mem; 8005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem += image_size; 8015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->argb_scratch_ = mem; 8025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora mem += argb_scratch_size; 8035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->transform_data_ = mem; 8045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->current_width_ = width; 8055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 8075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return err; 8085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 8095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Bundles multiple (2, 4 or 8) pixels into a single pixel. 8115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Returns the new xsize. 8125a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void BundleColorMap(const WebPPicture* const pic, 8135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int xbits, uint32_t* bundled_argb, int xs) { 8145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int y; 8155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int bit_depth = 1 << (3 - xbits); 8165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t code = 0; 8175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t* argb = pic->argb; 8185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int width = pic->width; 8195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int height = pic->height; 8205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (y = 0; y < height; ++y) { 8225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int x; 8235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (x = 0; x < width; ++x) { 8245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int mask = (1 << xbits) - 1; 8255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int xsub = x & mask; 8265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (xsub == 0) { 8275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora code = 0; 8285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // TODO(vikasa): simplify the bundling logic. 8305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora code |= (argb[x] & 0xff00) << (bit_depth * xsub); 8315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora bundled_argb[y * xs + (x >> xbits)] = 0xff000000 | code; 8325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora argb += pic->argb_stride; 8345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 8365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Note: Expects "enc->palette_" to be set properly. 8385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Also, "enc->palette_" will be modified after this call and should not be used 8395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// later. 8405a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WebPEncodingError ApplyPalette(VP8LBitWriter* const bw, 8415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LEncoder* const enc, int quality) { 8425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingError err = VP8_ENC_OK; 8435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int i, x, y; 8445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const pic = enc->pic_; 8455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t* argb = pic->argb; 8465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int width = pic->width; 8475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int height = pic->height; 8485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora uint32_t* const palette = enc->palette_; 8495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int palette_size = enc->palette_size_; 8505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Replace each input pixel by corresponding palette index. 8525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (y = 0; y < height; ++y) { 8535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (x = 0; x < width; ++x) { 8545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const uint32_t pix = argb[x]; 8555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = 0; i < palette_size; ++i) { 8565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (pix == palette[i]) { 8575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora argb[x] = 0xff000000u | (i << 8); 8585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora break; 8595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora argb += pic->argb_stride; 8635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Save palette to bitstream. 8665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, TRANSFORM_PRESENT); 8675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 2, COLOR_INDEXING_TRANSFORM); 8685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora assert(palette_size >= 1); 8695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 8, palette_size - 1); 8705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (i = palette_size - 1; i >= 1; --i) { 8715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); 8725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!EncodeImageNoHuffman(bw, palette, palette_size, 1, quality)) { 8745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_INVALID_CONFIGURATION; 8755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 8765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (palette_size <= 16) { 8795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Image can be packed (multiple pixels per uint32_t). 8805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int xbits = 1; 8815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (palette_size <= 2) { 8825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora xbits = 3; 8835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } else if (palette_size <= 4) { 8845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora xbits = 2; 8855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); 8875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) goto Error; 8885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora BundleColorMap(pic, xbits, enc->argb_, enc->current_width_); 8895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 8905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 8925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return err; 8935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 8945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 8965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 8975a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int GetHistoBits(const WebPConfig* const config, 8985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const pic) { 8995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int width = pic->width; 9005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int height = pic->height; 9015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t hist_size = sizeof(VP8LHistogram); 9025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Make tile size a function of encoding method (Range: 0 to 6). 9035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int histo_bits = 7 - config->method; 9045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora while (1) { 9055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t huff_image_size = VP8LSubSampleSize(width, histo_bits) * 9065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LSubSampleSize(height, histo_bits) * 9075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora hist_size; 9085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; 9095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora ++histo_bits; 9105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : 9125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; 9135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 9145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9155a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void InitEncParams(VP8LEncoder* const enc) { 9165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPConfig* const config = enc->config_; 9175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const picture = enc->pic_; 9185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int method = config->method; 9195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const float quality = config->quality; 9205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->transform_bits_ = (method < 4) ? 5 : (method > 4) ? 3 : 4; 9215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->histo_bits_ = GetHistoBits(config, picture); 9225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->cache_bits_ = (quality <= 25.f) ? 0 : 7; 9235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 9245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 9265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// VP8LEncoder 9275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9285a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, 9295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const picture) { 9305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LEncoder* const enc = (VP8LEncoder*)calloc(1, sizeof(*enc)); 9315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc == NULL) { 9325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 9335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return NULL; 9345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->config_ = config; 9365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->pic_ = picture; 9375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return enc; 9385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 9395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9405a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void VP8LEncoderDelete(VP8LEncoder* enc) { 9415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(enc->argb_); 9425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora free(enc); 9435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 9445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// ----------------------------------------------------------------------------- 9465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Main call 9475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9485a50414796e9a458925c7a13a15055d02406bf43Vikas AroraWebPEncodingError VP8LEncodeStream(const WebPConfig* const config, 9495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const picture, 9505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter* const bw) { 9515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingError err = VP8_ENC_OK; 9525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int quality = (int)config->quality; 9535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int width = picture->width; 9545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int height = picture->height; 9555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LEncoder* const enc = VP8LEncoderNew(config, picture); 9565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const size_t byte_position = VP8LBitWriterNumBytes(bw); 9575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc == NULL) { 9595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 9605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 9615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora InitEncParams(enc); 9645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // --------------------------------------------------------------------------- 9665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Analyze image (entropy, num_palettes etc) 9675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LEncAnalyze(enc, config->image_hint)) { 9695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 9705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 9715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_palette_) { 9745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = ApplyPalette(bw, enc, quality); 9755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) goto Error; 9765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Color cache is disabled for palette. 9775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->cache_bits_ = 0; 9785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // In case image is not packed. 9815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->argb_ == NULL) { 9825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int y; 9835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = AllocateTransformBuffer(enc, width, height); 9845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) goto Error; 9855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora for (y = 0; y < height; ++y) { 9865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora memcpy(enc->argb_ + y * width, 9875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora picture->argb + y * picture->argb_stride, 9885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora width * sizeof(*enc->argb_)); 9895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora enc->current_width_ = width; 9915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 9925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // --------------------------------------------------------------------------- 9945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Apply transforms and write transform data. 9955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 9965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!EvalAndApplySubtractGreen(enc, enc->current_width_, height, bw)) { 9975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 9985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 9995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_predict_) { 10025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!ApplyPredictFilter(enc, enc->current_width_, height, quality, bw)) { 10035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_INVALID_CONFIGURATION; 10045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 10055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_cross_color_) { 10095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!ApplyCrossColorFilter(enc, enc->current_width_, height, quality, bw)) { 10105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_INVALID_CONFIGURATION; 10115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 10125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LWriteBits(bw, 1, !TRANSFORM_PRESENT); // No more transforms. 10165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // --------------------------------------------------------------------------- 10185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Estimate the color cache size. 10195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->cache_bits_ > 0) { 10215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LCalculateEstimateForCacheSize(enc->argb_, enc->current_width_, 10225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora height, &enc->cache_bits_)) { 10235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_INVALID_CONFIGURATION; 10245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 10255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // --------------------------------------------------------------------------- 10295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Encode and write the transformed image. 10305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!EncodeImageInternal(bw, enc->argb_, enc->current_width_, height, 10325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora quality, enc->cache_bits_, enc->histo_bits_)) { 10335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 10345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 10355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (picture->stats != NULL) { 10385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPAuxStats* const stats = picture->stats; 10395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->lossless_features = 0; 10405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_predict_) stats->lossless_features |= 1; 10415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_cross_color_) stats->lossless_features |= 2; 10425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_subtract_green_) stats->lossless_features |= 4; 10435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (enc->use_palette_) stats->lossless_features |= 8; 10445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->histogram_bits = enc->histo_bits_; 10455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->transform_bits = enc->transform_bits_; 10465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->cache_bits = enc->cache_bits_; 10475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->palette_size = enc->palette_size_; 10485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); 10495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 10525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LEncoderDelete(enc); 10535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return err; 10545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 10555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10565a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraint VP8LEncodeImage(const WebPConfig* const config, 10575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const WebPPicture* const picture) { 10585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int width, height; 10595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int has_alpha; 10605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora size_t coded_size; 10615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora int percent = 0; 10625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingError err = VP8_ENC_OK; 10635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriter bw; 10645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (picture == NULL) return 0; 10665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (config == NULL || picture->argb == NULL) { 10685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_NULL_PARAMETER; 10695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingSetError(picture, err); 10705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 10715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora width = picture->width; 10745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora height = picture->height; 10755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!VP8LBitWriterInit(&bw, (width * height) >> 1)) { 10765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 10775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 10785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!WebPReportProgress(picture, 1, &percent)) { 10815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora UserAbort: 10825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_USER_ABORT; 10835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 10845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Reset stats (for pure lossless coding) 10865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (picture->stats != NULL) { 10875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPAuxStats* const stats = picture->stats; 10885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora memset(stats, 0, sizeof(*stats)); 10895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->PSNR[0] = 99.f; 10905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->PSNR[1] = 99.f; 10915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->PSNR[2] = 99.f; 10925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->PSNR[3] = 99.f; 10935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora stats->PSNR[4] = 99.f; 10945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 10955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 10965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Write image size. 10975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!WriteImageSize(picture, &bw)) { 10985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 10995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 11005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 11015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora has_alpha = WebPPictureHasTransparency(picture); 11035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Write the non-trivial Alpha flag and lossless version. 11045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { 11055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8_ENC_ERROR_OUT_OF_MEMORY; 11065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora goto Error; 11075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 11085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort; 11105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Encode main image stream. 11125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = VP8LEncodeStream(config, picture, &bw); 11135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) goto Error; 11145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // TODO(skal): have a fine-grained progress report in VP8LEncodeStream(). 11165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort; 11175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Finish the RIFF chunk. 11195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora err = WriteImage(picture, &bw, &coded_size); 11205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) goto Error; 11215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; 11235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora // Save size. 11255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (picture->stats != NULL) { 11265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora picture->stats->coded_size += (int)coded_size; 11275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora picture->stats->lossless_size = (int)coded_size; 11285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 11295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (picture->extra_info != NULL) { 11315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int mb_w = (width + 15) >> 4; 11325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora const int mb_h = (height + 15) >> 4; 11335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); 11345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 11355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora Error: 11375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY; 11385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora VP8LBitWriterDestroy(&bw); 11395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora if (err != VP8_ENC_OK) { 11405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora WebPEncodingSetError(picture, err); 11415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 0; 11425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora } 11435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora return 1; 11445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} 11455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------ 11475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora 11485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 11495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} // extern "C" 11505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif 1151