1 // Copyright 2012 Google Inc. All Rights Reserved.
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 // -----------------------------------------------------------------------------
10 // main entry for the lossless encoder.
12 // Author: Vikas Arora (vikaas.arora@gmail.com)
19 #include "./backward_references.h"
20 #include "./vp8enci.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"
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
32 // -----------------------------------------------------------------------------
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
;
39 return (a
< b
) ? -1 : 1;
42 // If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
43 // creates a palette and returns true, else returns false.
44 static int AnalyzeAndCreatePalette(const WebPPicture
* const pic
,
45 uint32_t palette
[MAX_PALETTE_SIZE
],
46 int* const palette_size
) {
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]
57 for (y
= 0; y
< height
; ++y
) {
58 for (x
= 0; x
< width
; ++x
) {
59 if (argb
[x
] == last_pix
) {
63 key
= (kHashMul
* last_pix
) >> PALETTE_KEY_RIGHT_SHIFT
;
66 colors
[key
] = last_pix
;
69 if (num_colors
> MAX_PALETTE_SIZE
) {
73 } else if (colors
[key
] == last_pix
) {
74 // The color is already there.
77 // Some other color sits there.
78 // Do linear conflict resolution.
80 key
&= (MAX_PALETTE_SIZE
* 4 - 1); // key mask for 1K buffer.
84 argb
+= pic
->argb_stride
;
87 // TODO(skal): could we reuse in_use[] to speed up EncodePalette()?
89 for (i
= 0; i
< (int)(sizeof(in_use
) / sizeof(in_use
[0])); ++i
) {
91 palette
[num_colors
] = colors
[i
];
96 qsort(palette
, num_colors
, sizeof(*palette
), CompareColors
);
97 *palette_size
= num_colors
;
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
) {
106 const uint32_t* last_line
= NULL
;
107 uint32_t last_pix
= argb
[0]; // so we're sure that pix_diff == 0
109 VP8LHistogram
* nonpredicted
= NULL
;
110 VP8LHistogram
* predicted
=
111 (VP8LHistogram
*)malloc(2 * sizeof(*predicted
));
112 if (predicted
== NULL
) return 0;
113 nonpredicted
= predicted
+ 1;
115 VP8LHistogramInit(predicted
, 0);
116 VP8LHistogramInit(nonpredicted
, 0);
117 for (y
= 0; y
< height
; ++y
) {
118 for (x
= 0; x
< width
; ++x
) {
119 const uint32_t pix
= argb
[x
];
120 const uint32_t pix_diff
= VP8LSubPixels(pix
, last_pix
);
121 if (pix_diff
== 0) continue;
122 if (last_line
!= NULL
&& pix
== last_line
[x
]) {
127 const PixOrCopy pix_token
= PixOrCopyCreateLiteral(pix
);
128 const PixOrCopy pix_diff_token
= PixOrCopyCreateLiteral(pix_diff
);
129 VP8LHistogramAddSinglePixOrCopy(nonpredicted
, &pix_token
);
130 VP8LHistogramAddSinglePixOrCopy(predicted
, &pix_diff_token
);
136 *nonpredicted_bits
= VP8LHistogramEstimateBitsBulk(nonpredicted
);
137 *predicted_bits
= VP8LHistogramEstimateBitsBulk(predicted
);
142 static int VP8LEncAnalyze(VP8LEncoder
* const enc
, WebPImageHint image_hint
) {
143 const WebPPicture
* const pic
= enc
->pic_
;
144 assert(pic
!= NULL
&& pic
->argb
!= NULL
);
147 AnalyzeAndCreatePalette(pic
, enc
->palette_
, &enc
->palette_size_
);
149 if (image_hint
== WEBP_HINT_GRAPH
) {
150 if (enc
->use_palette_
&& enc
->palette_size_
< MAX_COLORS_FOR_GRAPH
) {
151 enc
->use_palette_
= 0;
155 if (!enc
->use_palette_
) {
156 if (image_hint
== WEBP_HINT_PHOTO
) {
157 enc
->use_predict_
= 1;
158 enc
->use_cross_color_
= 1;
160 double non_pred_entropy
, pred_entropy
;
161 if (!AnalyzeEntropy(pic
->argb
, pic
->width
, pic
->height
, pic
->argb_stride
,
162 &non_pred_entropy
, &pred_entropy
)) {
165 if (pred_entropy
< 0.95 * non_pred_entropy
) {
166 enc
->use_predict_
= 1;
167 enc
->use_cross_color_
= 1;
175 static int GetHuffBitLengthsAndCodes(
176 const VP8LHistogramSet
* const histogram_image
,
177 HuffmanTreeCode
* const huffman_codes
) {
180 uint64_t total_length_size
= 0;
181 uint8_t* mem_buf
= NULL
;
182 const int histogram_image_size
= histogram_image
->size
;
184 // Iterate over all histograms and get the aggregate number of codes used.
185 for (i
= 0; i
< histogram_image_size
; ++i
) {
186 const VP8LHistogram
* const histo
= histogram_image
->histograms
[i
];
187 HuffmanTreeCode
* const codes
= &huffman_codes
[5 * i
];
188 for (k
= 0; k
< 5; ++k
) {
189 const int num_symbols
= (k
== 0) ? VP8LHistogramNumCodes(histo
)
190 : (k
== 4) ? NUM_DISTANCE_CODES
192 codes
[k
].num_symbols
= num_symbols
;
193 total_length_size
+= num_symbols
;
197 // Allocate and Set Huffman codes.
201 mem_buf
= (uint8_t*)WebPSafeCalloc(total_length_size
,
202 sizeof(*lengths
) + sizeof(*codes
));
203 if (mem_buf
== NULL
) {
207 codes
= (uint16_t*)mem_buf
;
208 lengths
= (uint8_t*)&codes
[total_length_size
];
209 for (i
= 0; i
< 5 * histogram_image_size
; ++i
) {
210 const int bit_length
= huffman_codes
[i
].num_symbols
;
211 huffman_codes
[i
].codes
= codes
;
212 huffman_codes
[i
].code_lengths
= lengths
;
214 lengths
+= bit_length
;
218 // Create Huffman trees.
219 for (i
= 0; ok
&& (i
< histogram_image_size
); ++i
) {
220 HuffmanTreeCode
* const codes
= &huffman_codes
[5 * i
];
221 VP8LHistogram
* const histo
= histogram_image
->histograms
[i
];
222 ok
= ok
&& VP8LCreateHuffmanTree(histo
->literal_
, 15, codes
+ 0);
223 ok
= ok
&& VP8LCreateHuffmanTree(histo
->red_
, 15, codes
+ 1);
224 ok
= ok
&& VP8LCreateHuffmanTree(histo
->blue_
, 15, codes
+ 2);
225 ok
= ok
&& VP8LCreateHuffmanTree(histo
->alpha_
, 15, codes
+ 3);
226 ok
= ok
&& VP8LCreateHuffmanTree(histo
->distance_
, 15, codes
+ 4);
232 // If one VP8LCreateHuffmanTree() above fails, we need to clean up behind.
233 memset(huffman_codes
, 0, 5 * histogram_image_size
* sizeof(*huffman_codes
));
238 static void StoreHuffmanTreeOfHuffmanTreeToBitMask(
239 VP8LBitWriter
* const bw
, const uint8_t* code_length_bitdepth
) {
240 // RFC 1951 will calm you down if you are worried about this funny sequence.
241 // This sequence is tuned from that, but more weighted for lower symbol count,
242 // and more spiking histograms.
243 static const uint8_t kStorageOrder
[CODE_LENGTH_CODES
] = {
244 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
247 // Throw away trailing zeros:
248 int codes_to_store
= CODE_LENGTH_CODES
;
249 for (; codes_to_store
> 4; --codes_to_store
) {
250 if (code_length_bitdepth
[kStorageOrder
[codes_to_store
- 1]] != 0) {
254 VP8LWriteBits(bw
, 4, codes_to_store
- 4);
255 for (i
= 0; i
< codes_to_store
; ++i
) {
256 VP8LWriteBits(bw
, 3, code_length_bitdepth
[kStorageOrder
[i
]]);
260 static void ClearHuffmanTreeIfOnlyOneSymbol(
261 HuffmanTreeCode
* const huffman_code
) {
264 for (k
= 0; k
< huffman_code
->num_symbols
; ++k
) {
265 if (huffman_code
->code_lengths
[k
] != 0) {
267 if (count
> 1) return;
270 for (k
= 0; k
< huffman_code
->num_symbols
; ++k
) {
271 huffman_code
->code_lengths
[k
] = 0;
272 huffman_code
->codes
[k
] = 0;
276 static void StoreHuffmanTreeToBitMask(
277 VP8LBitWriter
* const bw
,
278 const HuffmanTreeToken
* const tokens
, const int num_tokens
,
279 const HuffmanTreeCode
* const huffman_code
) {
281 for (i
= 0; i
< num_tokens
; ++i
) {
282 const int ix
= tokens
[i
].code
;
283 const int extra_bits
= tokens
[i
].extra_bits
;
284 VP8LWriteBits(bw
, huffman_code
->code_lengths
[ix
], huffman_code
->codes
[ix
]);
287 VP8LWriteBits(bw
, 2, extra_bits
);
290 VP8LWriteBits(bw
, 3, extra_bits
);
293 VP8LWriteBits(bw
, 7, extra_bits
);
299 static int StoreFullHuffmanCode(VP8LBitWriter
* const bw
,
300 const HuffmanTreeCode
* const tree
) {
302 uint8_t code_length_bitdepth
[CODE_LENGTH_CODES
] = { 0 };
303 uint16_t code_length_bitdepth_symbols
[CODE_LENGTH_CODES
] = { 0 };
304 const int max_tokens
= tree
->num_symbols
;
306 HuffmanTreeCode huffman_code
;
307 HuffmanTreeToken
* const tokens
=
308 (HuffmanTreeToken
*)WebPSafeMalloc((uint64_t)max_tokens
, sizeof(*tokens
));
309 if (tokens
== NULL
) return 0;
311 huffman_code
.num_symbols
= CODE_LENGTH_CODES
;
312 huffman_code
.code_lengths
= code_length_bitdepth
;
313 huffman_code
.codes
= code_length_bitdepth_symbols
;
315 VP8LWriteBits(bw
, 1, 0);
316 num_tokens
= VP8LCreateCompressedHuffmanTree(tree
, tokens
, max_tokens
);
318 int histogram
[CODE_LENGTH_CODES
] = { 0 };
320 for (i
= 0; i
< num_tokens
; ++i
) {
321 ++histogram
[tokens
[i
].code
];
324 if (!VP8LCreateHuffmanTree(histogram
, 7, &huffman_code
)) {
329 StoreHuffmanTreeOfHuffmanTreeToBitMask(bw
, code_length_bitdepth
);
330 ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code
);
332 int trailing_zero_bits
= 0;
333 int trimmed_length
= num_tokens
;
334 int write_trimmed_length
;
338 const int ix
= tokens
[i
].code
;
339 if (ix
== 0 || ix
== 17 || ix
== 18) {
340 --trimmed_length
; // discount trailing zeros
341 trailing_zero_bits
+= code_length_bitdepth
[ix
];
343 trailing_zero_bits
+= 3;
344 } else if (ix
== 18) {
345 trailing_zero_bits
+= 7;
351 write_trimmed_length
= (trimmed_length
> 1 && trailing_zero_bits
> 12);
352 length
= write_trimmed_length
? trimmed_length
: num_tokens
;
353 VP8LWriteBits(bw
, 1, write_trimmed_length
);
354 if (write_trimmed_length
) {
355 const int nbits
= VP8LBitsLog2Ceiling(trimmed_length
- 1);
356 const int nbitpairs
= (nbits
== 0) ? 1 : (nbits
+ 1) / 2;
357 VP8LWriteBits(bw
, 3, nbitpairs
- 1);
358 assert(trimmed_length
>= 2);
359 VP8LWriteBits(bw
, nbitpairs
* 2, trimmed_length
- 2);
361 StoreHuffmanTreeToBitMask(bw
, tokens
, length
, &huffman_code
);
369 static int StoreHuffmanCode(VP8LBitWriter
* const bw
,
370 const HuffmanTreeCode
* const huffman_code
) {
373 int symbols
[2] = { 0, 0 };
374 const int kMaxBits
= 8;
375 const int kMaxSymbol
= 1 << kMaxBits
;
377 // Check whether it's a small tree.
378 for (i
= 0; i
< huffman_code
->num_symbols
&& count
< 3; ++i
) {
379 if (huffman_code
->code_lengths
[i
] != 0) {
380 if (count
< 2) symbols
[count
] = i
;
385 if (count
== 0) { // emit minimal tree for empty cases
386 // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0
387 VP8LWriteBits(bw
, 4, 0x01);
389 } else if (count
<= 2 && symbols
[0] < kMaxSymbol
&& symbols
[1] < kMaxSymbol
) {
390 VP8LWriteBits(bw
, 1, 1); // Small tree marker to encode 1 or 2 symbols.
391 VP8LWriteBits(bw
, 1, count
- 1);
392 if (symbols
[0] <= 1) {
393 VP8LWriteBits(bw
, 1, 0); // Code bit for small (1 bit) symbol value.
394 VP8LWriteBits(bw
, 1, symbols
[0]);
396 VP8LWriteBits(bw
, 1, 1);
397 VP8LWriteBits(bw
, 8, symbols
[0]);
400 VP8LWriteBits(bw
, 8, symbols
[1]);
404 return StoreFullHuffmanCode(bw
, huffman_code
);
408 static void WriteHuffmanCode(VP8LBitWriter
* const bw
,
409 const HuffmanTreeCode
* const code
,
411 const int depth
= code
->code_lengths
[code_index
];
412 const int symbol
= code
->codes
[code_index
];
413 VP8LWriteBits(bw
, depth
, symbol
);
416 static void StoreImageToBitMask(
417 VP8LBitWriter
* const bw
, int width
, int histo_bits
,
418 const VP8LBackwardRefs
* const refs
,
419 const uint16_t* histogram_symbols
,
420 const HuffmanTreeCode
* const huffman_codes
) {
421 // x and y trace the position in the image.
424 const int histo_xsize
= histo_bits
? VP8LSubSampleSize(width
, histo_bits
) : 1;
426 for (i
= 0; i
< refs
->size
; ++i
) {
427 const PixOrCopy
* const v
= &refs
->refs
[i
];
428 const int histogram_ix
= histogram_symbols
[histo_bits
?
429 (y
>> histo_bits
) * histo_xsize
+
430 (x
>> histo_bits
) : 0];
431 const HuffmanTreeCode
* const codes
= huffman_codes
+ 5 * histogram_ix
;
432 if (PixOrCopyIsCacheIdx(v
)) {
433 const int code
= PixOrCopyCacheIdx(v
);
434 const int literal_ix
= 256 + NUM_LENGTH_CODES
+ code
;
435 WriteHuffmanCode(bw
, codes
, literal_ix
);
436 } else if (PixOrCopyIsLiteral(v
)) {
437 static const int order
[] = { 1, 2, 0, 3 };
439 for (k
= 0; k
< 4; ++k
) {
440 const int code
= PixOrCopyLiteral(v
, order
[k
]);
441 WriteHuffmanCode(bw
, codes
+ k
, code
);
447 VP8LPrefixEncode(v
->len
, &code
, &n_bits
, &bits
);
448 WriteHuffmanCode(bw
, codes
, 256 + code
);
449 VP8LWriteBits(bw
, n_bits
, bits
);
451 distance
= PixOrCopyDistance(v
);
452 VP8LPrefixEncode(distance
, &code
, &n_bits
, &bits
);
453 WriteHuffmanCode(bw
, codes
+ 4, code
);
454 VP8LWriteBits(bw
, n_bits
, bits
);
456 x
+= PixOrCopyLength(v
);
464 // Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31
465 static int EncodeImageNoHuffman(VP8LBitWriter
* const bw
,
466 const uint32_t* const argb
,
467 int width
, int height
, int quality
) {
470 VP8LBackwardRefs refs
;
471 HuffmanTreeCode huffman_codes
[5] = { { 0, NULL
, NULL
} };
472 const uint16_t histogram_symbols
[1] = { 0 }; // only one tree, one symbol
473 VP8LHistogramSet
* const histogram_image
= VP8LAllocateHistogramSet(1, 0);
474 if (histogram_image
== NULL
) return 0;
476 // Calculate backward references from ARGB image.
477 if (!VP8LGetBackwardReferences(width
, height
, argb
, quality
, 0, 1, &refs
)) {
480 // Build histogram image and symbols from backward references.
481 VP8LHistogramStoreRefs(&refs
, histogram_image
->histograms
[0]);
483 // Create Huffman bit lengths and codes for each histogram image.
484 assert(histogram_image
->size
== 1);
485 if (!GetHuffBitLengthsAndCodes(histogram_image
, huffman_codes
)) {
489 // No color cache, no Huffman image.
490 VP8LWriteBits(bw
, 1, 0);
492 // Store Huffman codes.
493 for (i
= 0; i
< 5; ++i
) {
494 HuffmanTreeCode
* const codes
= &huffman_codes
[i
];
495 if (!StoreHuffmanCode(bw
, codes
)) {
498 ClearHuffmanTreeIfOnlyOneSymbol(codes
);
501 // Store actual literals.
502 StoreImageToBitMask(bw
, width
, 0, &refs
, histogram_symbols
, huffman_codes
);
506 free(histogram_image
);
507 VP8LClearBackwardRefs(&refs
);
508 free(huffman_codes
[0].codes
);
512 static int EncodeImageInternal(VP8LBitWriter
* const bw
,
513 const uint32_t* const argb
,
514 int width
, int height
, int quality
,
515 int cache_bits
, int histogram_bits
) {
517 const int use_2d_locality
= 1;
518 const int use_color_cache
= (cache_bits
> 0);
519 const uint32_t histogram_image_xysize
=
520 VP8LSubSampleSize(width
, histogram_bits
) *
521 VP8LSubSampleSize(height
, histogram_bits
);
522 VP8LHistogramSet
* histogram_image
=
523 VP8LAllocateHistogramSet(histogram_image_xysize
, 0);
524 int histogram_image_size
= 0;
525 size_t bit_array_size
= 0;
526 HuffmanTreeCode
* huffman_codes
= NULL
;
527 VP8LBackwardRefs refs
;
528 uint16_t* const histogram_symbols
=
529 (uint16_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize
,
530 sizeof(*histogram_symbols
));
531 assert(histogram_bits
>= MIN_HUFFMAN_BITS
);
532 assert(histogram_bits
<= MAX_HUFFMAN_BITS
);
534 if (histogram_image
== NULL
|| histogram_symbols
== NULL
) {
535 free(histogram_image
);
536 free(histogram_symbols
);
540 // Calculate backward references from ARGB image.
541 if (!VP8LGetBackwardReferences(width
, height
, argb
, quality
, cache_bits
,
542 use_2d_locality
, &refs
)) {
545 // Build histogram image and symbols from backward references.
546 if (!VP8LGetHistoImageSymbols(width
, height
, &refs
,
547 quality
, histogram_bits
, cache_bits
,
549 histogram_symbols
)) {
552 // Create Huffman bit lengths and codes for each histogram image.
553 histogram_image_size
= histogram_image
->size
;
554 bit_array_size
= 5 * histogram_image_size
;
555 huffman_codes
= (HuffmanTreeCode
*)WebPSafeCalloc(bit_array_size
,
556 sizeof(*huffman_codes
));
557 if (huffman_codes
== NULL
||
558 !GetHuffBitLengthsAndCodes(histogram_image
, huffman_codes
)) {
561 // Free combined histograms.
562 free(histogram_image
);
563 histogram_image
= NULL
;
565 // Color Cache parameters.
566 VP8LWriteBits(bw
, 1, use_color_cache
);
567 if (use_color_cache
) {
568 VP8LWriteBits(bw
, 4, cache_bits
);
571 // Huffman image + meta huffman.
573 const int write_histogram_image
= (histogram_image_size
> 1);
574 VP8LWriteBits(bw
, 1, write_histogram_image
);
575 if (write_histogram_image
) {
576 uint32_t* const histogram_argb
=
577 (uint32_t*)WebPSafeMalloc((uint64_t)histogram_image_xysize
,
578 sizeof(*histogram_argb
));
581 if (histogram_argb
== NULL
) goto Error
;
582 for (i
= 0; i
< histogram_image_xysize
; ++i
) {
583 const int symbol_index
= histogram_symbols
[i
] & 0xffff;
584 histogram_argb
[i
] = 0xff000000 | (symbol_index
<< 8);
585 if (symbol_index
>= max_index
) {
586 max_index
= symbol_index
+ 1;
589 histogram_image_size
= max_index
;
591 VP8LWriteBits(bw
, 3, histogram_bits
- 2);
592 ok
= EncodeImageNoHuffman(bw
, histogram_argb
,
593 VP8LSubSampleSize(width
, histogram_bits
),
594 VP8LSubSampleSize(height
, histogram_bits
),
596 free(histogram_argb
);
601 // Store Huffman codes.
604 for (i
= 0; i
< 5 * histogram_image_size
; ++i
) {
605 HuffmanTreeCode
* const codes
= &huffman_codes
[i
];
606 if (!StoreHuffmanCode(bw
, codes
)) goto Error
;
607 ClearHuffmanTreeIfOnlyOneSymbol(codes
);
611 // Store actual literals.
612 StoreImageToBitMask(bw
, width
, histogram_bits
, &refs
,
613 histogram_symbols
, huffman_codes
);
617 free(histogram_image
);
619 VP8LClearBackwardRefs(&refs
);
620 if (huffman_codes
!= NULL
) {
621 free(huffman_codes
->codes
);
624 free(histogram_symbols
);
628 // -----------------------------------------------------------------------------
631 // Check if it would be a good idea to subtract green from red and blue. We
632 // only impact entropy in red/blue components, don't bother to look at others.
633 static int EvalAndApplySubtractGreen(VP8LEncoder
* const enc
,
634 int width
, int height
,
635 VP8LBitWriter
* const bw
) {
636 if (!enc
->use_palette_
) {
638 const uint32_t* const argb
= enc
->argb_
;
639 double bit_cost_before
, bit_cost_after
;
640 VP8LHistogram
* const histo
= (VP8LHistogram
*)malloc(sizeof(*histo
));
641 if (histo
== NULL
) return 0;
643 VP8LHistogramInit(histo
, 1);
644 for (i
= 0; i
< width
* height
; ++i
) {
645 const uint32_t c
= argb
[i
];
646 ++histo
->red_
[(c
>> 16) & 0xff];
647 ++histo
->blue_
[(c
>> 0) & 0xff];
649 bit_cost_before
= VP8LHistogramEstimateBits(histo
);
651 VP8LHistogramInit(histo
, 1);
652 for (i
= 0; i
< width
* height
; ++i
) {
653 const uint32_t c
= argb
[i
];
654 const int green
= (c
>> 8) & 0xff;
655 ++histo
->red_
[((c
>> 16) - green
) & 0xff];
656 ++histo
->blue_
[((c
>> 0) - green
) & 0xff];
658 bit_cost_after
= VP8LHistogramEstimateBits(histo
);
661 // Check if subtracting green yields low entropy.
662 enc
->use_subtract_green_
= (bit_cost_after
< bit_cost_before
);
663 if (enc
->use_subtract_green_
) {
664 VP8LWriteBits(bw
, 1, TRANSFORM_PRESENT
);
665 VP8LWriteBits(bw
, 2, SUBTRACT_GREEN
);
666 VP8LSubtractGreenFromBlueAndRed(enc
->argb_
, width
* height
);
672 static int ApplyPredictFilter(const VP8LEncoder
* const enc
,
673 int width
, int height
, int quality
,
674 VP8LBitWriter
* const bw
) {
675 const int pred_bits
= enc
->transform_bits_
;
676 const int transform_width
= VP8LSubSampleSize(width
, pred_bits
);
677 const int transform_height
= VP8LSubSampleSize(height
, pred_bits
);
679 VP8LResidualImage(width
, height
, pred_bits
, enc
->argb_
, enc
->argb_scratch_
,
680 enc
->transform_data_
);
681 VP8LWriteBits(bw
, 1, TRANSFORM_PRESENT
);
682 VP8LWriteBits(bw
, 2, PREDICTOR_TRANSFORM
);
683 assert(pred_bits
>= 2);
684 VP8LWriteBits(bw
, 3, pred_bits
- 2);
685 if (!EncodeImageNoHuffman(bw
, enc
->transform_data_
,
686 transform_width
, transform_height
, quality
)) {
692 static int ApplyCrossColorFilter(const VP8LEncoder
* const enc
,
693 int width
, int height
, int quality
,
694 VP8LBitWriter
* const bw
) {
695 const int ccolor_transform_bits
= enc
->transform_bits_
;
696 const int transform_width
= VP8LSubSampleSize(width
, ccolor_transform_bits
);
697 const int transform_height
= VP8LSubSampleSize(height
, ccolor_transform_bits
);
698 const int step
= (quality
< 25) ? 32 : (quality
> 50) ? 8 : 16;
700 VP8LColorSpaceTransform(width
, height
, ccolor_transform_bits
, step
,
701 enc
->argb_
, enc
->transform_data_
);
702 VP8LWriteBits(bw
, 1, TRANSFORM_PRESENT
);
703 VP8LWriteBits(bw
, 2, CROSS_COLOR_TRANSFORM
);
704 assert(ccolor_transform_bits
>= 2);
705 VP8LWriteBits(bw
, 3, ccolor_transform_bits
- 2);
706 if (!EncodeImageNoHuffman(bw
, enc
->transform_data_
,
707 transform_width
, transform_height
, quality
)) {
713 // -----------------------------------------------------------------------------
715 static WebPEncodingError
WriteRiffHeader(const WebPPicture
* const pic
,
716 size_t riff_size
, size_t vp8l_size
) {
717 uint8_t riff
[RIFF_HEADER_SIZE
+ CHUNK_HEADER_SIZE
+ VP8L_SIGNATURE_SIZE
] = {
718 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P',
719 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE
,
721 PutLE32(riff
+ TAG_SIZE
, (uint32_t)riff_size
);
722 PutLE32(riff
+ RIFF_HEADER_SIZE
+ TAG_SIZE
, (uint32_t)vp8l_size
);
723 if (!pic
->writer(riff
, sizeof(riff
), pic
)) {
724 return VP8_ENC_ERROR_BAD_WRITE
;
729 static int WriteImageSize(const WebPPicture
* const pic
,
730 VP8LBitWriter
* const bw
) {
731 const int width
= pic
->width
- 1;
732 const int height
= pic
->height
- 1;
733 assert(width
< WEBP_MAX_DIMENSION
&& height
< WEBP_MAX_DIMENSION
);
735 VP8LWriteBits(bw
, VP8L_IMAGE_SIZE_BITS
, width
);
736 VP8LWriteBits(bw
, VP8L_IMAGE_SIZE_BITS
, height
);
740 static int WriteRealAlphaAndVersion(VP8LBitWriter
* const bw
, int has_alpha
) {
741 VP8LWriteBits(bw
, 1, has_alpha
);
742 VP8LWriteBits(bw
, VP8L_VERSION_BITS
, VP8L_VERSION
);
746 static WebPEncodingError
WriteImage(const WebPPicture
* const pic
,
747 VP8LBitWriter
* const bw
,
748 size_t* const coded_size
) {
749 WebPEncodingError err
= VP8_ENC_OK
;
750 const uint8_t* const webpll_data
= VP8LBitWriterFinish(bw
);
751 const size_t webpll_size
= VP8LBitWriterNumBytes(bw
);
752 const size_t vp8l_size
= VP8L_SIGNATURE_SIZE
+ webpll_size
;
753 const size_t pad
= vp8l_size
& 1;
754 const size_t riff_size
= TAG_SIZE
+ CHUNK_HEADER_SIZE
+ vp8l_size
+ pad
;
756 err
= WriteRiffHeader(pic
, riff_size
, vp8l_size
);
757 if (err
!= VP8_ENC_OK
) goto Error
;
759 if (!pic
->writer(webpll_data
, webpll_size
, pic
)) {
760 err
= VP8_ENC_ERROR_BAD_WRITE
;
765 const uint8_t pad_byte
[1] = { 0 };
766 if (!pic
->writer(pad_byte
, 1, pic
)) {
767 err
= VP8_ENC_ERROR_BAD_WRITE
;
771 *coded_size
= CHUNK_HEADER_SIZE
+ riff_size
;
778 // -----------------------------------------------------------------------------
780 // Allocates the memory for argb (W x H) buffer, 2 rows of context for
781 // prediction and transform data.
782 static WebPEncodingError
AllocateTransformBuffer(VP8LEncoder
* const enc
,
783 int width
, int height
) {
784 WebPEncodingError err
= VP8_ENC_OK
;
785 const int tile_size
= 1 << enc
->transform_bits_
;
786 const uint64_t image_size
= width
* height
;
787 const uint64_t argb_scratch_size
= tile_size
* width
+ width
;
788 const uint64_t transform_data_size
=
789 (uint64_t)VP8LSubSampleSize(width
, enc
->transform_bits_
) *
790 (uint64_t)VP8LSubSampleSize(height
, enc
->transform_bits_
);
791 const uint64_t total_size
=
792 image_size
+ argb_scratch_size
+ transform_data_size
;
793 uint32_t* mem
= (uint32_t*)WebPSafeMalloc(total_size
, sizeof(*mem
));
795 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
800 enc
->argb_scratch_
= mem
;
801 mem
+= argb_scratch_size
;
802 enc
->transform_data_
= mem
;
803 enc
->current_width_
= width
;
809 static void ApplyPalette(uint32_t* src
, uint32_t* dst
,
810 uint32_t src_stride
, uint32_t dst_stride
,
811 const uint32_t* palette
, int palette_size
,
812 int width
, int height
, int xbits
, uint8_t* row
) {
815 for (i
= 0; i
< palette_size
; ++i
) {
816 if ((palette
[i
] & 0xffff00ffu
) != 0) {
823 uint8_t inv_palette
[MAX_PALETTE_SIZE
] = { 0 };
824 for (i
= 0; i
< palette_size
; ++i
) {
825 const int color
= (palette
[i
] >> 8) & 0xff;
826 inv_palette
[color
] = i
;
828 for (y
= 0; y
< height
; ++y
) {
829 for (x
= 0; x
< width
; ++x
) {
830 const int color
= (src
[x
] >> 8) & 0xff;
831 row
[x
] = inv_palette
[color
];
833 VP8LBundleColorMap(row
, width
, xbits
, dst
);
838 // Use 1 pixel cache for ARGB pixels.
839 uint32_t last_pix
= palette
[0];
841 for (y
= 0; y
< height
; ++y
) {
842 for (x
= 0; x
< width
; ++x
) {
843 const uint32_t pix
= src
[x
];
844 if (pix
!= last_pix
) {
845 for (i
= 0; i
< palette_size
; ++i
) {
846 if (pix
== palette
[i
]) {
855 VP8LBundleColorMap(row
, width
, xbits
, dst
);
862 // Note: Expects "enc->palette_" to be set properly.
863 // Also, "enc->palette_" will be modified after this call and should not be used
865 static WebPEncodingError
EncodePalette(VP8LBitWriter
* const bw
,
866 VP8LEncoder
* const enc
, int quality
) {
867 WebPEncodingError err
= VP8_ENC_OK
;
869 const WebPPicture
* const pic
= enc
->pic_
;
870 uint32_t* src
= pic
->argb
;
872 const int width
= pic
->width
;
873 const int height
= pic
->height
;
874 uint32_t* const palette
= enc
->palette_
;
875 const int palette_size
= enc
->palette_size_
;
879 // Replace each input pixel by corresponding palette index.
880 // This is done line by line.
881 if (palette_size
<= 4) {
882 xbits
= (palette_size
<= 2) ? 3 : 2;
884 xbits
= (palette_size
<= 16) ? 1 : 0;
887 err
= AllocateTransformBuffer(enc
, VP8LSubSampleSize(width
, xbits
), height
);
888 if (err
!= VP8_ENC_OK
) goto Error
;
891 row
= (uint8_t*)WebPSafeMalloc((uint64_t)width
, sizeof(*row
));
892 if (row
== NULL
) return VP8_ENC_ERROR_OUT_OF_MEMORY
;
894 ApplyPalette(src
, dst
, pic
->argb_stride
, enc
->current_width_
,
895 palette
, palette_size
, width
, height
, xbits
, row
);
897 // Save palette to bitstream.
898 VP8LWriteBits(bw
, 1, TRANSFORM_PRESENT
);
899 VP8LWriteBits(bw
, 2, COLOR_INDEXING_TRANSFORM
);
900 assert(palette_size
>= 1);
901 VP8LWriteBits(bw
, 8, palette_size
- 1);
902 for (i
= palette_size
- 1; i
>= 1; --i
) {
903 palette
[i
] = VP8LSubPixels(palette
[i
], palette
[i
- 1]);
905 if (!EncodeImageNoHuffman(bw
, palette
, palette_size
, 1, quality
)) {
906 err
= VP8_ENC_ERROR_INVALID_CONFIGURATION
;
915 // -----------------------------------------------------------------------------
917 static int GetHistoBits(int method
, int use_palette
, int width
, int height
) {
918 const uint64_t hist_size
= sizeof(VP8LHistogram
);
919 // Make tile size a function of encoding method (Range: 0 to 6).
920 int histo_bits
= (use_palette
? 9 : 7) - method
;
922 const uint64_t huff_image_size
= VP8LSubSampleSize(width
, histo_bits
) *
923 VP8LSubSampleSize(height
, histo_bits
) *
925 if (huff_image_size
<= MAX_HUFF_IMAGE_SIZE
) break;
928 return (histo_bits
< MIN_HUFFMAN_BITS
) ? MIN_HUFFMAN_BITS
:
929 (histo_bits
> MAX_HUFFMAN_BITS
) ? MAX_HUFFMAN_BITS
: histo_bits
;
932 static void FinishEncParams(VP8LEncoder
* const enc
) {
933 const WebPConfig
* const config
= enc
->config_
;
934 const WebPPicture
* const pic
= enc
->pic_
;
935 const int method
= config
->method
;
936 const float quality
= config
->quality
;
937 const int use_palette
= enc
->use_palette_
;
938 enc
->transform_bits_
= (method
< 4) ? 5 : (method
> 4) ? 3 : 4;
939 enc
->histo_bits_
= GetHistoBits(method
, use_palette
, pic
->width
, pic
->height
);
940 enc
->cache_bits_
= (quality
<= 25.f
) ? 0 : 7;
943 // -----------------------------------------------------------------------------
946 static VP8LEncoder
* VP8LEncoderNew(const WebPConfig
* const config
,
947 const WebPPicture
* const picture
) {
948 VP8LEncoder
* const enc
= (VP8LEncoder
*)calloc(1, sizeof(*enc
));
950 WebPEncodingSetError(picture
, VP8_ENC_ERROR_OUT_OF_MEMORY
);
953 enc
->config_
= config
;
961 static void VP8LEncoderDelete(VP8LEncoder
* enc
) {
966 // -----------------------------------------------------------------------------
969 WebPEncodingError
VP8LEncodeStream(const WebPConfig
* const config
,
970 const WebPPicture
* const picture
,
971 VP8LBitWriter
* const bw
) {
972 WebPEncodingError err
= VP8_ENC_OK
;
973 const int quality
= (int)config
->quality
;
974 const int width
= picture
->width
;
975 const int height
= picture
->height
;
976 VP8LEncoder
* const enc
= VP8LEncoderNew(config
, picture
);
977 const size_t byte_position
= VP8LBitWriterNumBytes(bw
);
980 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
984 // ---------------------------------------------------------------------------
985 // Analyze image (entropy, num_palettes etc)
987 if (!VP8LEncAnalyze(enc
, config
->image_hint
)) {
988 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
992 FinishEncParams(enc
);
994 if (enc
->use_palette_
) {
995 err
= EncodePalette(bw
, enc
, quality
);
996 if (err
!= VP8_ENC_OK
) goto Error
;
997 // Color cache is disabled for palette.
998 enc
->cache_bits_
= 0;
1001 // In case image is not packed.
1002 if (enc
->argb_
== NULL
) {
1004 err
= AllocateTransformBuffer(enc
, width
, height
);
1005 if (err
!= VP8_ENC_OK
) goto Error
;
1006 for (y
= 0; y
< height
; ++y
) {
1007 memcpy(enc
->argb_
+ y
* width
,
1008 picture
->argb
+ y
* picture
->argb_stride
,
1009 width
* sizeof(*enc
->argb_
));
1011 enc
->current_width_
= width
;
1014 // ---------------------------------------------------------------------------
1015 // Apply transforms and write transform data.
1017 if (!EvalAndApplySubtractGreen(enc
, enc
->current_width_
, height
, bw
)) {
1018 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
1022 if (enc
->use_predict_
) {
1023 if (!ApplyPredictFilter(enc
, enc
->current_width_
, height
, quality
, bw
)) {
1024 err
= VP8_ENC_ERROR_INVALID_CONFIGURATION
;
1029 if (enc
->use_cross_color_
) {
1030 if (!ApplyCrossColorFilter(enc
, enc
->current_width_
, height
, quality
, bw
)) {
1031 err
= VP8_ENC_ERROR_INVALID_CONFIGURATION
;
1036 VP8LWriteBits(bw
, 1, !TRANSFORM_PRESENT
); // No more transforms.
1038 // ---------------------------------------------------------------------------
1039 // Estimate the color cache size.
1041 if (enc
->cache_bits_
> 0) {
1042 if (!VP8LCalculateEstimateForCacheSize(enc
->argb_
, enc
->current_width_
,
1043 height
, &enc
->cache_bits_
)) {
1044 err
= VP8_ENC_ERROR_INVALID_CONFIGURATION
;
1049 // ---------------------------------------------------------------------------
1050 // Encode and write the transformed image.
1052 if (!EncodeImageInternal(bw
, enc
->argb_
, enc
->current_width_
, height
,
1053 quality
, enc
->cache_bits_
, enc
->histo_bits_
)) {
1054 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
1058 if (picture
->stats
!= NULL
) {
1059 WebPAuxStats
* const stats
= picture
->stats
;
1060 stats
->lossless_features
= 0;
1061 if (enc
->use_predict_
) stats
->lossless_features
|= 1;
1062 if (enc
->use_cross_color_
) stats
->lossless_features
|= 2;
1063 if (enc
->use_subtract_green_
) stats
->lossless_features
|= 4;
1064 if (enc
->use_palette_
) stats
->lossless_features
|= 8;
1065 stats
->histogram_bits
= enc
->histo_bits_
;
1066 stats
->transform_bits
= enc
->transform_bits_
;
1067 stats
->cache_bits
= enc
->cache_bits_
;
1068 stats
->palette_size
= enc
->palette_size_
;
1069 stats
->lossless_size
= (int)(VP8LBitWriterNumBytes(bw
) - byte_position
);
1073 VP8LEncoderDelete(enc
);
1077 int VP8LEncodeImage(const WebPConfig
* const config
,
1078 const WebPPicture
* const picture
) {
1083 WebPEncodingError err
= VP8_ENC_OK
;
1086 if (picture
== NULL
) return 0;
1088 if (config
== NULL
|| picture
->argb
== NULL
) {
1089 err
= VP8_ENC_ERROR_NULL_PARAMETER
;
1090 WebPEncodingSetError(picture
, err
);
1094 width
= picture
->width
;
1095 height
= picture
->height
;
1096 if (!VP8LBitWriterInit(&bw
, (width
* height
) >> 1)) {
1097 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
1101 if (!WebPReportProgress(picture
, 1, &percent
)) {
1103 err
= VP8_ENC_ERROR_USER_ABORT
;
1106 // Reset stats (for pure lossless coding)
1107 if (picture
->stats
!= NULL
) {
1108 WebPAuxStats
* const stats
= picture
->stats
;
1109 memset(stats
, 0, sizeof(*stats
));
1110 stats
->PSNR
[0] = 99.f
;
1111 stats
->PSNR
[1] = 99.f
;
1112 stats
->PSNR
[2] = 99.f
;
1113 stats
->PSNR
[3] = 99.f
;
1114 stats
->PSNR
[4] = 99.f
;
1117 // Write image size.
1118 if (!WriteImageSize(picture
, &bw
)) {
1119 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
1123 has_alpha
= WebPPictureHasTransparency(picture
);
1124 // Write the non-trivial Alpha flag and lossless version.
1125 if (!WriteRealAlphaAndVersion(&bw
, has_alpha
)) {
1126 err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
1130 if (!WebPReportProgress(picture
, 5, &percent
)) goto UserAbort
;
1132 // Encode main image stream.
1133 err
= VP8LEncodeStream(config
, picture
, &bw
);
1134 if (err
!= VP8_ENC_OK
) goto Error
;
1136 // TODO(skal): have a fine-grained progress report in VP8LEncodeStream().
1137 if (!WebPReportProgress(picture
, 90, &percent
)) goto UserAbort
;
1139 // Finish the RIFF chunk.
1140 err
= WriteImage(picture
, &bw
, &coded_size
);
1141 if (err
!= VP8_ENC_OK
) goto Error
;
1143 if (!WebPReportProgress(picture
, 100, &percent
)) goto UserAbort
;
1146 if (picture
->stats
!= NULL
) {
1147 picture
->stats
->coded_size
+= (int)coded_size
;
1148 picture
->stats
->lossless_size
= (int)coded_size
;
1151 if (picture
->extra_info
!= NULL
) {
1152 const int mb_w
= (width
+ 15) >> 4;
1153 const int mb_h
= (height
+ 15) >> 4;
1154 memset(picture
->extra_info
, 0, mb_w
* mb_h
* sizeof(*picture
->extra_info
));
1158 if (bw
.error_
) err
= VP8_ENC_ERROR_OUT_OF_MEMORY
;
1159 VP8LBitWriterDestroy(&bw
);
1160 if (err
!= VP8_ENC_OK
) {
1161 WebPEncodingSetError(picture
, err
);
1167 //------------------------------------------------------------------------------