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