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