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