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 <stdlib.h> 17 18 #include "./backward_references_enc.h" 19 #include "./histogram_enc.h" 20 #include "./vp8i_enc.h" 21 #include "./vp8li_enc.h" 22 #include "../dsp/lossless.h" 23 #include "../dsp/lossless_common.h" 24 #include "../utils/bit_writer_utils.h" 25 #include "../utils/huffman_encode_utils.h" 26 #include "../utils/utils.h" 27 #include "../webp/format_constants.h" 28 29 #include "./delta_palettization_enc.h" 30 31 #define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. 32 // Maximum number of histogram images (sub-blocks). 33 #define MAX_HUFF_IMAGE_SIZE 2600 34 35 // Palette reordering for smaller sum of deltas (and for smaller storage). 36 37 static int PaletteCompareColorsForQsort(const void* p1, const void* p2) { 38 const uint32_t a = WebPMemToUint32((uint8_t*)p1); 39 const uint32_t b = WebPMemToUint32((uint8_t*)p2); 40 assert(a != b); 41 return (a < b) ? -1 : 1; 42 } 43 44 static WEBP_INLINE uint32_t PaletteComponentDistance(uint32_t v) { 45 return (v <= 128) ? v : (256 - v); 46 } 47 48 // Computes a value that is related to the entropy created by the 49 // palette entry diff. 50 // 51 // Note that the last & 0xff is a no-operation in the next statement, but 52 // removed by most compilers and is here only for regularity of the code. 53 static WEBP_INLINE uint32_t PaletteColorDistance(uint32_t col1, uint32_t col2) { 54 const uint32_t diff = VP8LSubPixels(col1, col2); 55 const int kMoreWeightForRGBThanForAlpha = 9; 56 uint32_t score; 57 score = PaletteComponentDistance((diff >> 0) & 0xff); 58 score += PaletteComponentDistance((diff >> 8) & 0xff); 59 score += PaletteComponentDistance((diff >> 16) & 0xff); 60 score *= kMoreWeightForRGBThanForAlpha; 61 score += PaletteComponentDistance((diff >> 24) & 0xff); 62 return score; 63 } 64 65 static WEBP_INLINE void SwapColor(uint32_t* const col1, uint32_t* const col2) { 66 const uint32_t tmp = *col1; 67 *col1 = *col2; 68 *col2 = tmp; 69 } 70 71 static void GreedyMinimizeDeltas(uint32_t palette[], int num_colors) { 72 // Find greedily always the closest color of the predicted color to minimize 73 // deltas in the palette. This reduces storage needs since the 74 // palette is stored with delta encoding. 75 uint32_t predict = 0x00000000; 76 int i, k; 77 for (i = 0; i < num_colors; ++i) { 78 int best_ix = i; 79 uint32_t best_score = ~0U; 80 for (k = i; k < num_colors; ++k) { 81 const uint32_t cur_score = PaletteColorDistance(palette[k], predict); 82 if (best_score > cur_score) { 83 best_score = cur_score; 84 best_ix = k; 85 } 86 } 87 SwapColor(&palette[best_ix], &palette[i]); 88 predict = palette[i]; 89 } 90 } 91 92 // The palette has been sorted by alpha. This function checks if the other 93 // components of the palette have a monotonic development with regards to 94 // position in the palette. If all have monotonic development, there is 95 // no benefit to re-organize them greedily. A monotonic development 96 // would be spotted in green-only situations (like lossy alpha) or gray-scale 97 // images. 98 static int PaletteHasNonMonotonousDeltas(uint32_t palette[], int num_colors) { 99 uint32_t predict = 0x000000; 100 int i; 101 uint8_t sign_found = 0x00; 102 for (i = 0; i < num_colors; ++i) { 103 const uint32_t diff = VP8LSubPixels(palette[i], predict); 104 const uint8_t rd = (diff >> 16) & 0xff; 105 const uint8_t gd = (diff >> 8) & 0xff; 106 const uint8_t bd = (diff >> 0) & 0xff; 107 if (rd != 0x00) { 108 sign_found |= (rd < 0x80) ? 1 : 2; 109 } 110 if (gd != 0x00) { 111 sign_found |= (gd < 0x80) ? 8 : 16; 112 } 113 if (bd != 0x00) { 114 sign_found |= (bd < 0x80) ? 64 : 128; 115 } 116 predict = palette[i]; 117 } 118 return (sign_found & (sign_found << 1)) != 0; // two consequent signs. 119 } 120 121 // ----------------------------------------------------------------------------- 122 // Palette 123 124 // If number of colors in the image is less than or equal to MAX_PALETTE_SIZE, 125 // creates a palette and returns true, else returns false. 126 static int AnalyzeAndCreatePalette(const WebPPicture* const pic, 127 int low_effort, 128 uint32_t palette[MAX_PALETTE_SIZE], 129 int* const palette_size) { 130 const int num_colors = WebPGetColorPalette(pic, palette); 131 if (num_colors > MAX_PALETTE_SIZE) return 0; 132 *palette_size = num_colors; 133 qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); 134 if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) { 135 GreedyMinimizeDeltas(palette, num_colors); 136 } 137 return 1; 138 } 139 140 // These five modes are evaluated and their respective entropy is computed. 141 typedef enum { 142 kDirect = 0, 143 kSpatial = 1, 144 kSubGreen = 2, 145 kSpatialSubGreen = 3, 146 kPalette = 4, 147 kNumEntropyIx = 5 148 } EntropyIx; 149 150 typedef enum { 151 kHistoAlpha = 0, 152 kHistoAlphaPred, 153 kHistoGreen, 154 kHistoGreenPred, 155 kHistoRed, 156 kHistoRedPred, 157 kHistoBlue, 158 kHistoBluePred, 159 kHistoRedSubGreen, 160 kHistoRedPredSubGreen, 161 kHistoBlueSubGreen, 162 kHistoBluePredSubGreen, 163 kHistoPalette, 164 kHistoTotal // Must be last. 165 } HistoIx; 166 167 static void AddSingleSubGreen(int p, uint32_t* const r, uint32_t* const b) { 168 const int green = p >> 8; // The upper bits are masked away later. 169 ++r[((p >> 16) - green) & 0xff]; 170 ++b[((p >> 0) - green) & 0xff]; 171 } 172 173 static void AddSingle(uint32_t p, 174 uint32_t* const a, uint32_t* const r, 175 uint32_t* const g, uint32_t* const b) { 176 ++a[(p >> 24) & 0xff]; 177 ++r[(p >> 16) & 0xff]; 178 ++g[(p >> 8) & 0xff]; 179 ++b[(p >> 0) & 0xff]; 180 } 181 182 static WEBP_INLINE uint32_t HashPix(uint32_t pix) { 183 // Note that masking with 0xffffffffu is for preventing an 184 // 'unsigned int overflow' warning. Doesn't impact the compiled code. 185 return ((((uint64_t)pix + (pix >> 19)) * 0x39c5fba7ull) & 0xffffffffu) >> 24; 186 } 187 188 static int AnalyzeEntropy(const uint32_t* argb, 189 int width, int height, int argb_stride, 190 int use_palette, 191 EntropyIx* const min_entropy_ix, 192 int* const red_and_blue_always_zero) { 193 // Allocate histogram set with cache_bits = 0. 194 uint32_t* const histo = 195 (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); 196 if (histo != NULL) { 197 int i, x, y; 198 const uint32_t* prev_row = argb; 199 const uint32_t* curr_row = argb + argb_stride; 200 for (y = 1; y < height; ++y) { 201 uint32_t prev_pix = curr_row[0]; 202 for (x = 1; x < width; ++x) { 203 const uint32_t pix = curr_row[x]; 204 const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix); 205 if ((pix_diff == 0) || (pix == prev_row[x])) continue; 206 prev_pix = pix; 207 AddSingle(pix, 208 &histo[kHistoAlpha * 256], 209 &histo[kHistoRed * 256], 210 &histo[kHistoGreen * 256], 211 &histo[kHistoBlue * 256]); 212 AddSingle(pix_diff, 213 &histo[kHistoAlphaPred * 256], 214 &histo[kHistoRedPred * 256], 215 &histo[kHistoGreenPred * 256], 216 &histo[kHistoBluePred * 256]); 217 AddSingleSubGreen(pix, 218 &histo[kHistoRedSubGreen * 256], 219 &histo[kHistoBlueSubGreen * 256]); 220 AddSingleSubGreen(pix_diff, 221 &histo[kHistoRedPredSubGreen * 256], 222 &histo[kHistoBluePredSubGreen * 256]); 223 { 224 // Approximate the palette by the entropy of the multiplicative hash. 225 const uint32_t hash = HashPix(pix); 226 ++histo[kHistoPalette * 256 + hash]; 227 } 228 } 229 prev_row = curr_row; 230 curr_row += argb_stride; 231 } 232 { 233 double entropy_comp[kHistoTotal]; 234 double entropy[kNumEntropyIx]; 235 int k; 236 int last_mode_to_analyze = use_palette ? kPalette : kSpatialSubGreen; 237 int j; 238 // Let's add one zero to the predicted histograms. The zeros are removed 239 // too efficiently by the pix_diff == 0 comparison, at least one of the 240 // zeros is likely to exist. 241 ++histo[kHistoRedPredSubGreen * 256]; 242 ++histo[kHistoBluePredSubGreen * 256]; 243 ++histo[kHistoRedPred * 256]; 244 ++histo[kHistoGreenPred * 256]; 245 ++histo[kHistoBluePred * 256]; 246 ++histo[kHistoAlphaPred * 256]; 247 248 for (j = 0; j < kHistoTotal; ++j) { 249 entropy_comp[j] = VP8LBitsEntropy(&histo[j * 256], 256, NULL); 250 } 251 entropy[kDirect] = entropy_comp[kHistoAlpha] + 252 entropy_comp[kHistoRed] + 253 entropy_comp[kHistoGreen] + 254 entropy_comp[kHistoBlue]; 255 entropy[kSpatial] = entropy_comp[kHistoAlphaPred] + 256 entropy_comp[kHistoRedPred] + 257 entropy_comp[kHistoGreenPred] + 258 entropy_comp[kHistoBluePred]; 259 entropy[kSubGreen] = entropy_comp[kHistoAlpha] + 260 entropy_comp[kHistoRedSubGreen] + 261 entropy_comp[kHistoGreen] + 262 entropy_comp[kHistoBlueSubGreen]; 263 entropy[kSpatialSubGreen] = entropy_comp[kHistoAlphaPred] + 264 entropy_comp[kHistoRedPredSubGreen] + 265 entropy_comp[kHistoGreenPred] + 266 entropy_comp[kHistoBluePredSubGreen]; 267 // Palette mode seems more efficient in a breakeven case. Bias with 1.0. 268 entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0; 269 270 *min_entropy_ix = kDirect; 271 for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { 272 if (entropy[*min_entropy_ix] > entropy[k]) { 273 *min_entropy_ix = (EntropyIx)k; 274 } 275 } 276 *red_and_blue_always_zero = 1; 277 // Let's check if the histogram of the chosen entropy mode has 278 // non-zero red and blue values. If all are zero, we can later skip 279 // the cross color optimization. 280 { 281 static const uint8_t kHistoPairs[5][2] = { 282 { kHistoRed, kHistoBlue }, 283 { kHistoRedPred, kHistoBluePred }, 284 { kHistoRedSubGreen, kHistoBlueSubGreen }, 285 { kHistoRedPredSubGreen, kHistoBluePredSubGreen }, 286 { kHistoRed, kHistoBlue } 287 }; 288 const uint32_t* const red_histo = 289 &histo[256 * kHistoPairs[*min_entropy_ix][0]]; 290 const uint32_t* const blue_histo = 291 &histo[256 * kHistoPairs[*min_entropy_ix][1]]; 292 for (i = 1; i < 256; ++i) { 293 if ((red_histo[i] | blue_histo[i]) != 0) { 294 *red_and_blue_always_zero = 0; 295 break; 296 } 297 } 298 } 299 } 300 WebPSafeFree(histo); 301 return 1; 302 } else { 303 return 0; 304 } 305 } 306 307 static int GetHistoBits(int method, int use_palette, int width, int height) { 308 // Make tile size a function of encoding method (Range: 0 to 6). 309 int histo_bits = (use_palette ? 9 : 7) - method; 310 while (1) { 311 const int huff_image_size = VP8LSubSampleSize(width, histo_bits) * 312 VP8LSubSampleSize(height, histo_bits); 313 if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break; 314 ++histo_bits; 315 } 316 return (histo_bits < MIN_HUFFMAN_BITS) ? MIN_HUFFMAN_BITS : 317 (histo_bits > MAX_HUFFMAN_BITS) ? MAX_HUFFMAN_BITS : histo_bits; 318 } 319 320 static int GetTransformBits(int method, int histo_bits) { 321 const int max_transform_bits = (method < 4) ? 6 : (method > 4) ? 4 : 5; 322 const int res = 323 (histo_bits > max_transform_bits) ? max_transform_bits : histo_bits; 324 assert(res <= MAX_TRANSFORM_BITS); 325 return res; 326 } 327 328 static int AnalyzeAndInit(VP8LEncoder* const enc) { 329 const WebPPicture* const pic = enc->pic_; 330 const int width = pic->width; 331 const int height = pic->height; 332 const int pix_cnt = width * height; 333 const WebPConfig* const config = enc->config_; 334 const int method = config->method; 335 const int low_effort = (config->method == 0); 336 // we round the block size up, so we're guaranteed to have 337 // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: 338 int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; 339 assert(pic != NULL && pic->argb != NULL); 340 341 enc->use_cross_color_ = 0; 342 enc->use_predict_ = 0; 343 enc->use_subtract_green_ = 0; 344 enc->use_palette_ = 345 AnalyzeAndCreatePalette(pic, low_effort, 346 enc->palette_, &enc->palette_size_); 347 348 // TODO(jyrki): replace the decision to be based on an actual estimate 349 // of entropy, or even spatial variance of entropy. 350 enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, 351 pic->width, pic->height); 352 enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); 353 354 if (low_effort) { 355 // AnalyzeEntropy is somewhat slow. 356 enc->use_predict_ = !enc->use_palette_; 357 enc->use_subtract_green_ = !enc->use_palette_; 358 enc->use_cross_color_ = 0; 359 } else { 360 int red_and_blue_always_zero; 361 EntropyIx min_entropy_ix; 362 if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, 363 enc->use_palette_, &min_entropy_ix, 364 &red_and_blue_always_zero)) { 365 return 0; 366 } 367 enc->use_palette_ = (min_entropy_ix == kPalette); 368 enc->use_subtract_green_ = 369 (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); 370 enc->use_predict_ = 371 (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); 372 enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; 373 } 374 375 if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; 376 377 // palette-friendly input typically uses less literals 378 // -> reduce block size a bit 379 if (enc->use_palette_) refs_block_size /= 2; 380 VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size); 381 VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size); 382 383 return 1; 384 } 385 386 // Returns false in case of memory error. 387 static int GetHuffBitLengthsAndCodes( 388 const VP8LHistogramSet* const histogram_image, 389 HuffmanTreeCode* const huffman_codes) { 390 int i, k; 391 int ok = 0; 392 uint64_t total_length_size = 0; 393 uint8_t* mem_buf = NULL; 394 const int histogram_image_size = histogram_image->size; 395 int max_num_symbols = 0; 396 uint8_t* buf_rle = NULL; 397 HuffmanTree* huff_tree = NULL; 398 399 // Iterate over all histograms and get the aggregate number of codes used. 400 for (i = 0; i < histogram_image_size; ++i) { 401 const VP8LHistogram* const histo = histogram_image->histograms[i]; 402 HuffmanTreeCode* const codes = &huffman_codes[5 * i]; 403 for (k = 0; k < 5; ++k) { 404 const int num_symbols = 405 (k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) : 406 (k == 4) ? NUM_DISTANCE_CODES : 256; 407 codes[k].num_symbols = num_symbols; 408 total_length_size += num_symbols; 409 } 410 } 411 412 // Allocate and Set Huffman codes. 413 { 414 uint16_t* codes; 415 uint8_t* lengths; 416 mem_buf = (uint8_t*)WebPSafeCalloc(total_length_size, 417 sizeof(*lengths) + sizeof(*codes)); 418 if (mem_buf == NULL) goto End; 419 420 codes = (uint16_t*)mem_buf; 421 lengths = (uint8_t*)&codes[total_length_size]; 422 for (i = 0; i < 5 * histogram_image_size; ++i) { 423 const int bit_length = huffman_codes[i].num_symbols; 424 huffman_codes[i].codes = codes; 425 huffman_codes[i].code_lengths = lengths; 426 codes += bit_length; 427 lengths += bit_length; 428 if (max_num_symbols < bit_length) { 429 max_num_symbols = bit_length; 430 } 431 } 432 } 433 434 buf_rle = (uint8_t*)WebPSafeMalloc(1ULL, max_num_symbols); 435 huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * max_num_symbols, 436 sizeof(*huff_tree)); 437 if (buf_rle == NULL || huff_tree == NULL) goto End; 438 439 // Create Huffman trees. 440 for (i = 0; i < histogram_image_size; ++i) { 441 HuffmanTreeCode* const codes = &huffman_codes[5 * i]; 442 VP8LHistogram* const histo = histogram_image->histograms[i]; 443 VP8LCreateHuffmanTree(histo->literal_, 15, buf_rle, huff_tree, codes + 0); 444 VP8LCreateHuffmanTree(histo->red_, 15, buf_rle, huff_tree, codes + 1); 445 VP8LCreateHuffmanTree(histo->blue_, 15, buf_rle, huff_tree, codes + 2); 446 VP8LCreateHuffmanTree(histo->alpha_, 15, buf_rle, huff_tree, codes + 3); 447 VP8LCreateHuffmanTree(histo->distance_, 15, buf_rle, huff_tree, codes + 4); 448 } 449 ok = 1; 450 End: 451 WebPSafeFree(huff_tree); 452 WebPSafeFree(buf_rle); 453 if (!ok) { 454 WebPSafeFree(mem_buf); 455 memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes)); 456 } 457 return ok; 458 } 459 460 static void StoreHuffmanTreeOfHuffmanTreeToBitMask( 461 VP8LBitWriter* const bw, const uint8_t* code_length_bitdepth) { 462 // RFC 1951 will calm you down if you are worried about this funny sequence. 463 // This sequence is tuned from that, but more weighted for lower symbol count, 464 // and more spiking histograms. 465 static const uint8_t kStorageOrder[CODE_LENGTH_CODES] = { 466 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 467 }; 468 int i; 469 // Throw away trailing zeros: 470 int codes_to_store = CODE_LENGTH_CODES; 471 for (; codes_to_store > 4; --codes_to_store) { 472 if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) { 473 break; 474 } 475 } 476 VP8LPutBits(bw, codes_to_store - 4, 4); 477 for (i = 0; i < codes_to_store; ++i) { 478 VP8LPutBits(bw, code_length_bitdepth[kStorageOrder[i]], 3); 479 } 480 } 481 482 static void ClearHuffmanTreeIfOnlyOneSymbol( 483 HuffmanTreeCode* const huffman_code) { 484 int k; 485 int count = 0; 486 for (k = 0; k < huffman_code->num_symbols; ++k) { 487 if (huffman_code->code_lengths[k] != 0) { 488 ++count; 489 if (count > 1) return; 490 } 491 } 492 for (k = 0; k < huffman_code->num_symbols; ++k) { 493 huffman_code->code_lengths[k] = 0; 494 huffman_code->codes[k] = 0; 495 } 496 } 497 498 static void StoreHuffmanTreeToBitMask( 499 VP8LBitWriter* const bw, 500 const HuffmanTreeToken* const tokens, const int num_tokens, 501 const HuffmanTreeCode* const huffman_code) { 502 int i; 503 for (i = 0; i < num_tokens; ++i) { 504 const int ix = tokens[i].code; 505 const int extra_bits = tokens[i].extra_bits; 506 VP8LPutBits(bw, huffman_code->codes[ix], huffman_code->code_lengths[ix]); 507 switch (ix) { 508 case 16: 509 VP8LPutBits(bw, extra_bits, 2); 510 break; 511 case 17: 512 VP8LPutBits(bw, extra_bits, 3); 513 break; 514 case 18: 515 VP8LPutBits(bw, extra_bits, 7); 516 break; 517 } 518 } 519 } 520 521 // 'huff_tree' and 'tokens' are pre-alloacted buffers. 522 static void StoreFullHuffmanCode(VP8LBitWriter* const bw, 523 HuffmanTree* const huff_tree, 524 HuffmanTreeToken* const tokens, 525 const HuffmanTreeCode* const tree) { 526 uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; 527 uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; 528 const int max_tokens = tree->num_symbols; 529 int num_tokens; 530 HuffmanTreeCode huffman_code; 531 huffman_code.num_symbols = CODE_LENGTH_CODES; 532 huffman_code.code_lengths = code_length_bitdepth; 533 huffman_code.codes = code_length_bitdepth_symbols; 534 535 VP8LPutBits(bw, 0, 1); 536 num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens); 537 { 538 uint32_t histogram[CODE_LENGTH_CODES] = { 0 }; 539 uint8_t buf_rle[CODE_LENGTH_CODES] = { 0 }; 540 int i; 541 for (i = 0; i < num_tokens; ++i) { 542 ++histogram[tokens[i].code]; 543 } 544 545 VP8LCreateHuffmanTree(histogram, 7, buf_rle, huff_tree, &huffman_code); 546 } 547 548 StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); 549 ClearHuffmanTreeIfOnlyOneSymbol(&huffman_code); 550 { 551 int trailing_zero_bits = 0; 552 int trimmed_length = num_tokens; 553 int write_trimmed_length; 554 int length; 555 int i = num_tokens; 556 while (i-- > 0) { 557 const int ix = tokens[i].code; 558 if (ix == 0 || ix == 17 || ix == 18) { 559 --trimmed_length; // discount trailing zeros 560 trailing_zero_bits += code_length_bitdepth[ix]; 561 if (ix == 17) { 562 trailing_zero_bits += 3; 563 } else if (ix == 18) { 564 trailing_zero_bits += 7; 565 } 566 } else { 567 break; 568 } 569 } 570 write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); 571 length = write_trimmed_length ? trimmed_length : num_tokens; 572 VP8LPutBits(bw, write_trimmed_length, 1); 573 if (write_trimmed_length) { 574 const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); 575 const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; 576 VP8LPutBits(bw, nbitpairs - 1, 3); 577 assert(trimmed_length >= 2); 578 VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); 579 } 580 StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); 581 } 582 } 583 584 // 'huff_tree' and 'tokens' are pre-alloacted buffers. 585 static void StoreHuffmanCode(VP8LBitWriter* const bw, 586 HuffmanTree* const huff_tree, 587 HuffmanTreeToken* const tokens, 588 const HuffmanTreeCode* const huffman_code) { 589 int i; 590 int count = 0; 591 int symbols[2] = { 0, 0 }; 592 const int kMaxBits = 8; 593 const int kMaxSymbol = 1 << kMaxBits; 594 595 // Check whether it's a small tree. 596 for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) { 597 if (huffman_code->code_lengths[i] != 0) { 598 if (count < 2) symbols[count] = i; 599 ++count; 600 } 601 } 602 603 if (count == 0) { // emit minimal tree for empty cases 604 // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 605 VP8LPutBits(bw, 0x01, 4); 606 } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { 607 VP8LPutBits(bw, 1, 1); // Small tree marker to encode 1 or 2 symbols. 608 VP8LPutBits(bw, count - 1, 1); 609 if (symbols[0] <= 1) { 610 VP8LPutBits(bw, 0, 1); // Code bit for small (1 bit) symbol value. 611 VP8LPutBits(bw, symbols[0], 1); 612 } else { 613 VP8LPutBits(bw, 1, 1); 614 VP8LPutBits(bw, symbols[0], 8); 615 } 616 if (count == 2) { 617 VP8LPutBits(bw, symbols[1], 8); 618 } 619 } else { 620 StoreFullHuffmanCode(bw, huff_tree, tokens, huffman_code); 621 } 622 } 623 624 static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw, 625 const HuffmanTreeCode* const code, 626 int code_index) { 627 const int depth = code->code_lengths[code_index]; 628 const int symbol = code->codes[code_index]; 629 VP8LPutBits(bw, symbol, depth); 630 } 631 632 static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( 633 VP8LBitWriter* const bw, 634 const HuffmanTreeCode* const code, 635 int code_index, 636 int bits, 637 int n_bits) { 638 const int depth = code->code_lengths[code_index]; 639 const int symbol = code->codes[code_index]; 640 VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits); 641 } 642 643 static WebPEncodingError StoreImageToBitMask( 644 VP8LBitWriter* const bw, int width, int histo_bits, 645 VP8LBackwardRefs* const refs, 646 const uint16_t* histogram_symbols, 647 const HuffmanTreeCode* const huffman_codes) { 648 const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; 649 const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits); 650 // x and y trace the position in the image. 651 int x = 0; 652 int y = 0; 653 int tile_x = x & tile_mask; 654 int tile_y = y & tile_mask; 655 int histogram_ix = histogram_symbols[0]; 656 const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix; 657 VP8LRefsCursor c = VP8LRefsCursorInit(refs); 658 while (VP8LRefsCursorOk(&c)) { 659 const PixOrCopy* const v = c.cur_pos; 660 if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) { 661 tile_x = x & tile_mask; 662 tile_y = y & tile_mask; 663 histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize + 664 (x >> histo_bits)]; 665 codes = huffman_codes + 5 * histogram_ix; 666 } 667 if (PixOrCopyIsLiteral(v)) { 668 static const int order[] = { 1, 2, 0, 3 }; 669 int k; 670 for (k = 0; k < 4; ++k) { 671 const int code = PixOrCopyLiteral(v, order[k]); 672 WriteHuffmanCode(bw, codes + k, code); 673 } 674 } else if (PixOrCopyIsCacheIdx(v)) { 675 const int code = PixOrCopyCacheIdx(v); 676 const int literal_ix = 256 + NUM_LENGTH_CODES + code; 677 WriteHuffmanCode(bw, codes, literal_ix); 678 } else { 679 int bits, n_bits; 680 int code; 681 682 const int distance = PixOrCopyDistance(v); 683 VP8LPrefixEncode(v->len, &code, &n_bits, &bits); 684 WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits); 685 686 // Don't write the distance with the extra bits code since 687 // the distance can be up to 18 bits of extra bits, and the prefix 688 // 15 bits, totaling to 33, and our PutBits only supports up to 32 bits. 689 // TODO(jyrki): optimize this further. 690 VP8LPrefixEncode(distance, &code, &n_bits, &bits); 691 WriteHuffmanCode(bw, codes + 4, code); 692 VP8LPutBits(bw, bits, n_bits); 693 } 694 x += PixOrCopyLength(v); 695 while (x >= width) { 696 x -= width; 697 ++y; 698 } 699 VP8LRefsCursorNext(&c); 700 } 701 return bw->error_ ? VP8_ENC_ERROR_OUT_OF_MEMORY : VP8_ENC_OK; 702 } 703 704 // Special case of EncodeImageInternal() for cache-bits=0, histo_bits=31 705 static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, 706 const uint32_t* const argb, 707 VP8LHashChain* const hash_chain, 708 VP8LBackwardRefs refs_array[2], 709 int width, int height, 710 int quality, int low_effort) { 711 int i; 712 int max_tokens = 0; 713 WebPEncodingError err = VP8_ENC_OK; 714 VP8LBackwardRefs* refs; 715 HuffmanTreeToken* tokens = NULL; 716 HuffmanTreeCode huffman_codes[5] = { { 0, NULL, NULL } }; 717 const uint16_t histogram_symbols[1] = { 0 }; // only one tree, one symbol 718 int cache_bits = 0; 719 VP8LHistogramSet* histogram_image = NULL; 720 HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( 721 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); 722 if (huff_tree == NULL) { 723 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 724 goto Error; 725 } 726 727 // Calculate backward references from ARGB image. 728 if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, 729 low_effort)) { 730 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 731 goto Error; 732 } 733 refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, 734 hash_chain, refs_array); 735 if (refs == NULL) { 736 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 737 goto Error; 738 } 739 histogram_image = VP8LAllocateHistogramSet(1, cache_bits); 740 if (histogram_image == NULL) { 741 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 742 goto Error; 743 } 744 745 // Build histogram image and symbols from backward references. 746 VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]); 747 748 // Create Huffman bit lengths and codes for each histogram image. 749 assert(histogram_image->size == 1); 750 if (!GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { 751 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 752 goto Error; 753 } 754 755 // No color cache, no Huffman image. 756 VP8LPutBits(bw, 0, 1); 757 758 // Find maximum number of symbols for the huffman tree-set. 759 for (i = 0; i < 5; ++i) { 760 HuffmanTreeCode* const codes = &huffman_codes[i]; 761 if (max_tokens < codes->num_symbols) { 762 max_tokens = codes->num_symbols; 763 } 764 } 765 766 tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); 767 if (tokens == NULL) { 768 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 769 goto Error; 770 } 771 772 // Store Huffman codes. 773 for (i = 0; i < 5; ++i) { 774 HuffmanTreeCode* const codes = &huffman_codes[i]; 775 StoreHuffmanCode(bw, huff_tree, tokens, codes); 776 ClearHuffmanTreeIfOnlyOneSymbol(codes); 777 } 778 779 // Store actual literals. 780 err = StoreImageToBitMask(bw, width, 0, refs, histogram_symbols, 781 huffman_codes); 782 783 Error: 784 WebPSafeFree(tokens); 785 WebPSafeFree(huff_tree); 786 VP8LFreeHistogramSet(histogram_image); 787 WebPSafeFree(huffman_codes[0].codes); 788 return err; 789 } 790 791 static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, 792 const uint32_t* const argb, 793 VP8LHashChain* const hash_chain, 794 VP8LBackwardRefs refs_array[2], 795 int width, int height, int quality, 796 int low_effort, 797 int use_cache, int* cache_bits, 798 int histogram_bits, 799 size_t init_byte_position, 800 int* const hdr_size, 801 int* const data_size) { 802 WebPEncodingError err = VP8_ENC_OK; 803 const uint32_t histogram_image_xysize = 804 VP8LSubSampleSize(width, histogram_bits) * 805 VP8LSubSampleSize(height, histogram_bits); 806 VP8LHistogramSet* histogram_image = NULL; 807 VP8LHistogramSet* tmp_histos = NULL; 808 int histogram_image_size = 0; 809 size_t bit_array_size = 0; 810 HuffmanTree* huff_tree = NULL; 811 HuffmanTreeToken* tokens = NULL; 812 HuffmanTreeCode* huffman_codes = NULL; 813 VP8LBackwardRefs refs; 814 VP8LBackwardRefs* best_refs; 815 uint16_t* const histogram_symbols = 816 (uint16_t*)WebPSafeMalloc(histogram_image_xysize, 817 sizeof(*histogram_symbols)); 818 assert(histogram_bits >= MIN_HUFFMAN_BITS); 819 assert(histogram_bits <= MAX_HUFFMAN_BITS); 820 assert(hdr_size != NULL); 821 assert(data_size != NULL); 822 823 VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); 824 if (histogram_symbols == NULL) { 825 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 826 goto Error; 827 } 828 829 if (use_cache) { 830 // If the value is different from zero, it has been set during the 831 // palette analysis. 832 if (*cache_bits == 0) *cache_bits = MAX_COLOR_CACHE_BITS; 833 } else { 834 *cache_bits = 0; 835 } 836 // 'best_refs' is the reference to the best backward refs and points to one 837 // of refs_array[0] or refs_array[1]. 838 // Calculate backward references from ARGB image. 839 if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, 840 low_effort)) { 841 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 842 goto Error; 843 } 844 best_refs = VP8LGetBackwardReferences(width, height, argb, quality, 845 low_effort, cache_bits, hash_chain, 846 refs_array); 847 if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { 848 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 849 goto Error; 850 } 851 histogram_image = 852 VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); 853 tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits); 854 if (histogram_image == NULL || tmp_histos == NULL) { 855 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 856 goto Error; 857 } 858 859 // Build histogram image and symbols from backward references. 860 if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort, 861 histogram_bits, *cache_bits, histogram_image, 862 tmp_histos, histogram_symbols)) { 863 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 864 goto Error; 865 } 866 // Create Huffman bit lengths and codes for each histogram image. 867 histogram_image_size = histogram_image->size; 868 bit_array_size = 5 * histogram_image_size; 869 huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, 870 sizeof(*huffman_codes)); 871 // Note: some histogram_image entries may point to tmp_histos[], so the latter 872 // need to outlive the following call to GetHuffBitLengthsAndCodes(). 873 if (huffman_codes == NULL || 874 !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { 875 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 876 goto Error; 877 } 878 // Free combined histograms. 879 VP8LFreeHistogramSet(histogram_image); 880 histogram_image = NULL; 881 882 // Free scratch histograms. 883 VP8LFreeHistogramSet(tmp_histos); 884 tmp_histos = NULL; 885 886 // Color Cache parameters. 887 if (*cache_bits > 0) { 888 VP8LPutBits(bw, 1, 1); 889 VP8LPutBits(bw, *cache_bits, 4); 890 } else { 891 VP8LPutBits(bw, 0, 1); 892 } 893 894 // Huffman image + meta huffman. 895 { 896 const int write_histogram_image = (histogram_image_size > 1); 897 VP8LPutBits(bw, write_histogram_image, 1); 898 if (write_histogram_image) { 899 uint32_t* const histogram_argb = 900 (uint32_t*)WebPSafeMalloc(histogram_image_xysize, 901 sizeof(*histogram_argb)); 902 int max_index = 0; 903 uint32_t i; 904 if (histogram_argb == NULL) { 905 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 906 goto Error; 907 } 908 for (i = 0; i < histogram_image_xysize; ++i) { 909 const int symbol_index = histogram_symbols[i] & 0xffff; 910 histogram_argb[i] = (symbol_index << 8); 911 if (symbol_index >= max_index) { 912 max_index = symbol_index + 1; 913 } 914 } 915 histogram_image_size = max_index; 916 917 VP8LPutBits(bw, histogram_bits - 2, 3); 918 err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, 919 VP8LSubSampleSize(width, histogram_bits), 920 VP8LSubSampleSize(height, histogram_bits), 921 quality, low_effort); 922 WebPSafeFree(histogram_argb); 923 if (err != VP8_ENC_OK) goto Error; 924 } 925 } 926 927 // Store Huffman codes. 928 { 929 int i; 930 int max_tokens = 0; 931 huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES, 932 sizeof(*huff_tree)); 933 if (huff_tree == NULL) { 934 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 935 goto Error; 936 } 937 // Find maximum number of symbols for the huffman tree-set. 938 for (i = 0; i < 5 * histogram_image_size; ++i) { 939 HuffmanTreeCode* const codes = &huffman_codes[i]; 940 if (max_tokens < codes->num_symbols) { 941 max_tokens = codes->num_symbols; 942 } 943 } 944 tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, 945 sizeof(*tokens)); 946 if (tokens == NULL) { 947 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 948 goto Error; 949 } 950 for (i = 0; i < 5 * histogram_image_size; ++i) { 951 HuffmanTreeCode* const codes = &huffman_codes[i]; 952 StoreHuffmanCode(bw, huff_tree, tokens, codes); 953 ClearHuffmanTreeIfOnlyOneSymbol(codes); 954 } 955 } 956 957 *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); 958 // Store actual literals. 959 err = StoreImageToBitMask(bw, width, histogram_bits, &refs, 960 histogram_symbols, huffman_codes); 961 *data_size = 962 (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); 963 964 Error: 965 WebPSafeFree(tokens); 966 WebPSafeFree(huff_tree); 967 VP8LFreeHistogramSet(histogram_image); 968 VP8LFreeHistogramSet(tmp_histos); 969 VP8LBackwardRefsClear(&refs); 970 if (huffman_codes != NULL) { 971 WebPSafeFree(huffman_codes->codes); 972 WebPSafeFree(huffman_codes); 973 } 974 WebPSafeFree(histogram_symbols); 975 return err; 976 } 977 978 // ----------------------------------------------------------------------------- 979 // Transforms 980 981 static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height, 982 VP8LBitWriter* const bw) { 983 VP8LPutBits(bw, TRANSFORM_PRESENT, 1); 984 VP8LPutBits(bw, SUBTRACT_GREEN, 2); 985 VP8LSubtractGreenFromBlueAndRed(enc->argb_, width * height); 986 } 987 988 static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, 989 int width, int height, 990 int quality, int low_effort, 991 int used_subtract_green, 992 VP8LBitWriter* const bw) { 993 const int pred_bits = enc->transform_bits_; 994 const int transform_width = VP8LSubSampleSize(width, pred_bits); 995 const int transform_height = VP8LSubSampleSize(height, pred_bits); 996 // we disable near-lossless quantization if palette is used. 997 const int near_lossless_strength = enc->use_palette_ ? 100 998 : enc->config_->near_lossless; 999 1000 VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_, 1001 enc->argb_scratch_, enc->transform_data_, 1002 near_lossless_strength, enc->config_->exact, 1003 used_subtract_green); 1004 VP8LPutBits(bw, TRANSFORM_PRESENT, 1); 1005 VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); 1006 assert(pred_bits >= 2); 1007 VP8LPutBits(bw, pred_bits - 2, 3); 1008 return EncodeImageNoHuffman(bw, enc->transform_data_, 1009 (VP8LHashChain*)&enc->hash_chain_, 1010 (VP8LBackwardRefs*)enc->refs_, // cast const away 1011 transform_width, transform_height, 1012 quality, low_effort); 1013 } 1014 1015 static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, 1016 int width, int height, 1017 int quality, int low_effort, 1018 VP8LBitWriter* const bw) { 1019 const int ccolor_transform_bits = enc->transform_bits_; 1020 const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); 1021 const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); 1022 1023 VP8LColorSpaceTransform(width, height, ccolor_transform_bits, quality, 1024 enc->argb_, enc->transform_data_); 1025 VP8LPutBits(bw, TRANSFORM_PRESENT, 1); 1026 VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); 1027 assert(ccolor_transform_bits >= 2); 1028 VP8LPutBits(bw, ccolor_transform_bits - 2, 3); 1029 return EncodeImageNoHuffman(bw, enc->transform_data_, 1030 (VP8LHashChain*)&enc->hash_chain_, 1031 (VP8LBackwardRefs*)enc->refs_, // cast const away 1032 transform_width, transform_height, 1033 quality, low_effort); 1034 } 1035 1036 // ----------------------------------------------------------------------------- 1037 1038 static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic, 1039 size_t riff_size, size_t vp8l_size) { 1040 uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = { 1041 'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P', 1042 'V', 'P', '8', 'L', 0, 0, 0, 0, VP8L_MAGIC_BYTE, 1043 }; 1044 PutLE32(riff + TAG_SIZE, (uint32_t)riff_size); 1045 PutLE32(riff + RIFF_HEADER_SIZE + TAG_SIZE, (uint32_t)vp8l_size); 1046 if (!pic->writer(riff, sizeof(riff), pic)) { 1047 return VP8_ENC_ERROR_BAD_WRITE; 1048 } 1049 return VP8_ENC_OK; 1050 } 1051 1052 static int WriteImageSize(const WebPPicture* const pic, 1053 VP8LBitWriter* const bw) { 1054 const int width = pic->width - 1; 1055 const int height = pic->height - 1; 1056 assert(width < WEBP_MAX_DIMENSION && height < WEBP_MAX_DIMENSION); 1057 1058 VP8LPutBits(bw, width, VP8L_IMAGE_SIZE_BITS); 1059 VP8LPutBits(bw, height, VP8L_IMAGE_SIZE_BITS); 1060 return !bw->error_; 1061 } 1062 1063 static int WriteRealAlphaAndVersion(VP8LBitWriter* const bw, int has_alpha) { 1064 VP8LPutBits(bw, has_alpha, 1); 1065 VP8LPutBits(bw, VP8L_VERSION, VP8L_VERSION_BITS); 1066 return !bw->error_; 1067 } 1068 1069 static WebPEncodingError WriteImage(const WebPPicture* const pic, 1070 VP8LBitWriter* const bw, 1071 size_t* const coded_size) { 1072 WebPEncodingError err = VP8_ENC_OK; 1073 const uint8_t* const webpll_data = VP8LBitWriterFinish(bw); 1074 const size_t webpll_size = VP8LBitWriterNumBytes(bw); 1075 const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size; 1076 const size_t pad = vp8l_size & 1; 1077 const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad; 1078 1079 err = WriteRiffHeader(pic, riff_size, vp8l_size); 1080 if (err != VP8_ENC_OK) goto Error; 1081 1082 if (!pic->writer(webpll_data, webpll_size, pic)) { 1083 err = VP8_ENC_ERROR_BAD_WRITE; 1084 goto Error; 1085 } 1086 1087 if (pad) { 1088 const uint8_t pad_byte[1] = { 0 }; 1089 if (!pic->writer(pad_byte, 1, pic)) { 1090 err = VP8_ENC_ERROR_BAD_WRITE; 1091 goto Error; 1092 } 1093 } 1094 *coded_size = CHUNK_HEADER_SIZE + riff_size; 1095 return VP8_ENC_OK; 1096 1097 Error: 1098 return err; 1099 } 1100 1101 // ----------------------------------------------------------------------------- 1102 1103 static void ClearTransformBuffer(VP8LEncoder* const enc) { 1104 WebPSafeFree(enc->transform_mem_); 1105 enc->transform_mem_ = NULL; 1106 enc->transform_mem_size_ = 0; 1107 } 1108 1109 // Allocates the memory for argb (W x H) buffer, 2 rows of context for 1110 // prediction and transform data. 1111 // Flags influencing the memory allocated: 1112 // enc->transform_bits_ 1113 // enc->use_predict_, enc->use_cross_color_ 1114 static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, 1115 int width, int height) { 1116 WebPEncodingError err = VP8_ENC_OK; 1117 const uint64_t image_size = width * height; 1118 // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra 1119 // pixel in each, plus 2 regular scanlines of bytes. 1120 // TODO(skal): Clean up by using arithmetic in bytes instead of words. 1121 const uint64_t argb_scratch_size = 1122 enc->use_predict_ 1123 ? (width + 1) * 2 + 1124 (width * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t) 1125 : 0; 1126 const uint64_t transform_data_size = 1127 (enc->use_predict_ || enc->use_cross_color_) 1128 ? VP8LSubSampleSize(width, enc->transform_bits_) * 1129 VP8LSubSampleSize(height, enc->transform_bits_) 1130 : 0; 1131 const uint64_t max_alignment_in_words = 1132 (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); 1133 const uint64_t mem_size = 1134 image_size + max_alignment_in_words + 1135 argb_scratch_size + max_alignment_in_words + 1136 transform_data_size; 1137 uint32_t* mem = enc->transform_mem_; 1138 if (mem == NULL || mem_size > enc->transform_mem_size_) { 1139 ClearTransformBuffer(enc); 1140 mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem)); 1141 if (mem == NULL) { 1142 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1143 goto Error; 1144 } 1145 enc->transform_mem_ = mem; 1146 enc->transform_mem_size_ = (size_t)mem_size; 1147 } 1148 enc->argb_ = mem; 1149 mem = (uint32_t*)WEBP_ALIGN(mem + image_size); 1150 enc->argb_scratch_ = mem; 1151 mem = (uint32_t*)WEBP_ALIGN(mem + argb_scratch_size); 1152 enc->transform_data_ = mem; 1153 1154 enc->current_width_ = width; 1155 Error: 1156 return err; 1157 } 1158 1159 static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) { 1160 WebPEncodingError err = VP8_ENC_OK; 1161 const WebPPicture* const picture = enc->pic_; 1162 const int width = picture->width; 1163 const int height = picture->height; 1164 int y; 1165 err = AllocateTransformBuffer(enc, width, height); 1166 if (err != VP8_ENC_OK) return err; 1167 for (y = 0; y < height; ++y) { 1168 memcpy(enc->argb_ + y * width, 1169 picture->argb + y * picture->argb_stride, 1170 width * sizeof(*enc->argb_)); 1171 } 1172 assert(enc->current_width_ == width); 1173 return VP8_ENC_OK; 1174 } 1175 1176 // ----------------------------------------------------------------------------- 1177 1178 static WEBP_INLINE int SearchColorNoIdx(const uint32_t sorted[], uint32_t color, 1179 int hi) { 1180 int low = 0; 1181 if (sorted[low] == color) return low; // loop invariant: sorted[low] != color 1182 while (1) { 1183 const int mid = (low + hi) >> 1; 1184 if (sorted[mid] == color) { 1185 return mid; 1186 } else if (sorted[mid] < color) { 1187 low = mid; 1188 } else { 1189 hi = mid; 1190 } 1191 } 1192 } 1193 1194 #define APPLY_PALETTE_GREEDY_MAX 4 1195 1196 static WEBP_INLINE uint32_t SearchColorGreedy(const uint32_t palette[], 1197 int palette_size, 1198 uint32_t color) { 1199 (void)palette_size; 1200 assert(palette_size < APPLY_PALETTE_GREEDY_MAX); 1201 assert(3 == APPLY_PALETTE_GREEDY_MAX - 1); 1202 if (color == palette[0]) return 0; 1203 if (color == palette[1]) return 1; 1204 if (color == palette[2]) return 2; 1205 return 3; 1206 } 1207 1208 static WEBP_INLINE uint32_t ApplyPaletteHash0(uint32_t color) { 1209 // Focus on the green color. 1210 return (color >> 8) & 0xff; 1211 } 1212 1213 #define PALETTE_INV_SIZE_BITS 11 1214 #define PALETTE_INV_SIZE (1 << PALETTE_INV_SIZE_BITS) 1215 1216 static WEBP_INLINE uint32_t ApplyPaletteHash1(uint32_t color) { 1217 // Forget about alpha. 1218 return ((color & 0x00ffffffu) * 4222244071u) >> (32 - PALETTE_INV_SIZE_BITS); 1219 } 1220 1221 static WEBP_INLINE uint32_t ApplyPaletteHash2(uint32_t color) { 1222 // Forget about alpha. 1223 return (color & 0x00ffffffu) * ((1u << 31) - 1) >> 1224 (32 - PALETTE_INV_SIZE_BITS); 1225 } 1226 1227 // Sort palette in increasing order and prepare an inverse mapping array. 1228 static void PrepareMapToPalette(const uint32_t palette[], int num_colors, 1229 uint32_t sorted[], uint32_t idx_map[]) { 1230 int i; 1231 memcpy(sorted, palette, num_colors * sizeof(*sorted)); 1232 qsort(sorted, num_colors, sizeof(*sorted), PaletteCompareColorsForQsort); 1233 for (i = 0; i < num_colors; ++i) { 1234 idx_map[SearchColorNoIdx(sorted, palette[i], num_colors)] = i; 1235 } 1236 } 1237 1238 // Use 1 pixel cache for ARGB pixels. 1239 #define APPLY_PALETTE_FOR(COLOR_INDEX) do { \ 1240 uint32_t prev_pix = palette[0]; \ 1241 uint32_t prev_idx = 0; \ 1242 for (y = 0; y < height; ++y) { \ 1243 for (x = 0; x < width; ++x) { \ 1244 const uint32_t pix = src[x]; \ 1245 if (pix != prev_pix) { \ 1246 prev_idx = COLOR_INDEX; \ 1247 prev_pix = pix; \ 1248 } \ 1249 tmp_row[x] = prev_idx; \ 1250 } \ 1251 VP8LBundleColorMap(tmp_row, width, xbits, dst); \ 1252 src += src_stride; \ 1253 dst += dst_stride; \ 1254 } \ 1255 } while (0) 1256 1257 // Remap argb values in src[] to packed palettes entries in dst[] 1258 // using 'row' as a temporary buffer of size 'width'. 1259 // We assume that all src[] values have a corresponding entry in the palette. 1260 // Note: src[] can be the same as dst[] 1261 static WebPEncodingError ApplyPalette(const uint32_t* src, uint32_t src_stride, 1262 uint32_t* dst, uint32_t dst_stride, 1263 const uint32_t* palette, int palette_size, 1264 int width, int height, int xbits) { 1265 // TODO(skal): this tmp buffer is not needed if VP8LBundleColorMap() can be 1266 // made to work in-place. 1267 uint8_t* const tmp_row = (uint8_t*)WebPSafeMalloc(width, sizeof(*tmp_row)); 1268 int x, y; 1269 1270 if (tmp_row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; 1271 1272 if (palette_size < APPLY_PALETTE_GREEDY_MAX) { 1273 APPLY_PALETTE_FOR(SearchColorGreedy(palette, palette_size, pix)); 1274 } else { 1275 int i, j; 1276 uint16_t buffer[PALETTE_INV_SIZE]; 1277 uint32_t (*const hash_functions[])(uint32_t) = { 1278 ApplyPaletteHash0, ApplyPaletteHash1, ApplyPaletteHash2 1279 }; 1280 1281 // Try to find a perfect hash function able to go from a color to an index 1282 // within 1 << PALETTE_INV_SIZE_BITS in order to build a hash map to go 1283 // from color to index in palette. 1284 for (i = 0; i < 3; ++i) { 1285 int use_LUT = 1; 1286 // Set each element in buffer to max uint16_t. 1287 memset(buffer, 0xff, sizeof(buffer)); 1288 for (j = 0; j < palette_size; ++j) { 1289 const uint32_t ind = hash_functions[i](palette[j]); 1290 if (buffer[ind] != 0xffffu) { 1291 use_LUT = 0; 1292 break; 1293 } else { 1294 buffer[ind] = j; 1295 } 1296 } 1297 if (use_LUT) break; 1298 } 1299 1300 if (i == 0) { 1301 APPLY_PALETTE_FOR(buffer[ApplyPaletteHash0(pix)]); 1302 } else if (i == 1) { 1303 APPLY_PALETTE_FOR(buffer[ApplyPaletteHash1(pix)]); 1304 } else if (i == 2) { 1305 APPLY_PALETTE_FOR(buffer[ApplyPaletteHash2(pix)]); 1306 } else { 1307 uint32_t idx_map[MAX_PALETTE_SIZE]; 1308 uint32_t palette_sorted[MAX_PALETTE_SIZE]; 1309 PrepareMapToPalette(palette, palette_size, palette_sorted, idx_map); 1310 APPLY_PALETTE_FOR( 1311 idx_map[SearchColorNoIdx(palette_sorted, pix, palette_size)]); 1312 } 1313 } 1314 WebPSafeFree(tmp_row); 1315 return VP8_ENC_OK; 1316 } 1317 #undef APPLY_PALETTE_FOR 1318 #undef PALETTE_INV_SIZE_BITS 1319 #undef PALETTE_INV_SIZE 1320 #undef APPLY_PALETTE_GREEDY_MAX 1321 1322 // Note: Expects "enc->palette_" to be set properly. 1323 static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, 1324 int in_place) { 1325 WebPEncodingError err = VP8_ENC_OK; 1326 const WebPPicture* const pic = enc->pic_; 1327 const int width = pic->width; 1328 const int height = pic->height; 1329 const uint32_t* const palette = enc->palette_; 1330 const uint32_t* src = in_place ? enc->argb_ : pic->argb; 1331 const int src_stride = in_place ? enc->current_width_ : pic->argb_stride; 1332 const int palette_size = enc->palette_size_; 1333 int xbits; 1334 1335 // Replace each input pixel by corresponding palette index. 1336 // This is done line by line. 1337 if (palette_size <= 4) { 1338 xbits = (palette_size <= 2) ? 3 : 2; 1339 } else { 1340 xbits = (palette_size <= 16) ? 1 : 0; 1341 } 1342 1343 err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height); 1344 if (err != VP8_ENC_OK) return err; 1345 1346 err = ApplyPalette(src, src_stride, 1347 enc->argb_, enc->current_width_, 1348 palette, palette_size, width, height, xbits); 1349 return err; 1350 } 1351 1352 // Save palette_[] to bitstream. 1353 static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort, 1354 VP8LEncoder* const enc) { 1355 int i; 1356 uint32_t tmp_palette[MAX_PALETTE_SIZE]; 1357 const int palette_size = enc->palette_size_; 1358 const uint32_t* const palette = enc->palette_; 1359 VP8LPutBits(bw, TRANSFORM_PRESENT, 1); 1360 VP8LPutBits(bw, COLOR_INDEXING_TRANSFORM, 2); 1361 assert(palette_size >= 1 && palette_size <= MAX_PALETTE_SIZE); 1362 VP8LPutBits(bw, palette_size - 1, 8); 1363 for (i = palette_size - 1; i >= 1; --i) { 1364 tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); 1365 } 1366 tmp_palette[0] = palette[0]; 1367 return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, 1368 palette_size, 1, 20 /* quality */, low_effort); 1369 } 1370 1371 #ifdef WEBP_EXPERIMENTAL_FEATURES 1372 1373 static WebPEncodingError EncodeDeltaPalettePredictorImage( 1374 VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality, 1375 int low_effort) { 1376 const WebPPicture* const pic = enc->pic_; 1377 const int width = pic->width; 1378 const int height = pic->height; 1379 1380 const int pred_bits = 5; 1381 const int transform_width = VP8LSubSampleSize(width, pred_bits); 1382 const int transform_height = VP8LSubSampleSize(height, pred_bits); 1383 const int pred = 7; // default is Predictor7 (Top/Left Average) 1384 const int tiles_per_row = VP8LSubSampleSize(width, pred_bits); 1385 const int tiles_per_col = VP8LSubSampleSize(height, pred_bits); 1386 uint32_t* predictors; 1387 int tile_x, tile_y; 1388 WebPEncodingError err = VP8_ENC_OK; 1389 1390 predictors = (uint32_t*)WebPSafeMalloc(tiles_per_col * tiles_per_row, 1391 sizeof(*predictors)); 1392 if (predictors == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY; 1393 1394 for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { 1395 for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { 1396 predictors[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); 1397 } 1398 } 1399 1400 VP8LPutBits(bw, TRANSFORM_PRESENT, 1); 1401 VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); 1402 VP8LPutBits(bw, pred_bits - 2, 3); 1403 err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, 1404 (VP8LBackwardRefs*)enc->refs_, // cast const away 1405 transform_width, transform_height, 1406 quality, low_effort); 1407 WebPSafeFree(predictors); 1408 return err; 1409 } 1410 1411 #endif // WEBP_EXPERIMENTAL_FEATURES 1412 1413 // ----------------------------------------------------------------------------- 1414 // VP8LEncoder 1415 1416 static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, 1417 const WebPPicture* const picture) { 1418 VP8LEncoder* const enc = (VP8LEncoder*)WebPSafeCalloc(1ULL, sizeof(*enc)); 1419 if (enc == NULL) { 1420 WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 1421 return NULL; 1422 } 1423 enc->config_ = config; 1424 enc->pic_ = picture; 1425 1426 VP8LEncDspInit(); 1427 1428 return enc; 1429 } 1430 1431 static void VP8LEncoderDelete(VP8LEncoder* enc) { 1432 if (enc != NULL) { 1433 VP8LHashChainClear(&enc->hash_chain_); 1434 VP8LBackwardRefsClear(&enc->refs_[0]); 1435 VP8LBackwardRefsClear(&enc->refs_[1]); 1436 ClearTransformBuffer(enc); 1437 WebPSafeFree(enc); 1438 } 1439 } 1440 1441 // ----------------------------------------------------------------------------- 1442 // Main call 1443 1444 WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, 1445 const WebPPicture* const picture, 1446 VP8LBitWriter* const bw, int use_cache) { 1447 WebPEncodingError err = VP8_ENC_OK; 1448 const int quality = (int)config->quality; 1449 const int low_effort = (config->method == 0); 1450 const int width = picture->width; 1451 const int height = picture->height; 1452 VP8LEncoder* const enc = VP8LEncoderNew(config, picture); 1453 const size_t byte_position = VP8LBitWriterNumBytes(bw); 1454 int use_near_lossless = 0; 1455 int hdr_size = 0; 1456 int data_size = 0; 1457 int use_delta_palette = 0; 1458 1459 if (enc == NULL) { 1460 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1461 goto Error; 1462 } 1463 1464 // --------------------------------------------------------------------------- 1465 // Analyze image (entropy, num_palettes etc) 1466 1467 if (!AnalyzeAndInit(enc)) { 1468 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1469 goto Error; 1470 } 1471 1472 // Apply near-lossless preprocessing. 1473 use_near_lossless = 1474 (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_; 1475 if (use_near_lossless) { 1476 if (!VP8ApplyNearLossless(width, height, picture->argb, 1477 config->near_lossless)) { 1478 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1479 goto Error; 1480 } 1481 } 1482 1483 #ifdef WEBP_EXPERIMENTAL_FEATURES 1484 if (config->use_delta_palette) { 1485 enc->use_predict_ = 1; 1486 enc->use_cross_color_ = 0; 1487 enc->use_subtract_green_ = 0; 1488 enc->use_palette_ = 1; 1489 err = MakeInputImageCopy(enc); 1490 if (err != VP8_ENC_OK) goto Error; 1491 err = WebPSearchOptimalDeltaPalette(enc); 1492 if (err != VP8_ENC_OK) goto Error; 1493 if (enc->use_palette_) { 1494 err = AllocateTransformBuffer(enc, width, height); 1495 if (err != VP8_ENC_OK) goto Error; 1496 err = EncodeDeltaPalettePredictorImage(bw, enc, quality, low_effort); 1497 if (err != VP8_ENC_OK) goto Error; 1498 use_delta_palette = 1; 1499 } 1500 } 1501 #endif // WEBP_EXPERIMENTAL_FEATURES 1502 1503 // Encode palette 1504 if (enc->use_palette_) { 1505 err = EncodePalette(bw, low_effort, enc); 1506 if (err != VP8_ENC_OK) goto Error; 1507 err = MapImageFromPalette(enc, use_delta_palette); 1508 if (err != VP8_ENC_OK) goto Error; 1509 // If using a color cache, do not have it bigger than the number of colors. 1510 if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { 1511 enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; 1512 } 1513 } 1514 if (!use_delta_palette) { 1515 // In case image is not packed. 1516 if (enc->argb_ == NULL) { 1517 err = MakeInputImageCopy(enc); 1518 if (err != VP8_ENC_OK) goto Error; 1519 } 1520 1521 // ------------------------------------------------------------------------- 1522 // Apply transforms and write transform data. 1523 1524 if (enc->use_subtract_green_) { 1525 ApplySubtractGreen(enc, enc->current_width_, height, bw); 1526 } 1527 1528 if (enc->use_predict_) { 1529 err = ApplyPredictFilter(enc, enc->current_width_, height, quality, 1530 low_effort, enc->use_subtract_green_, bw); 1531 if (err != VP8_ENC_OK) goto Error; 1532 } 1533 1534 if (enc->use_cross_color_) { 1535 err = ApplyCrossColorFilter(enc, enc->current_width_, 1536 height, quality, low_effort, bw); 1537 if (err != VP8_ENC_OK) goto Error; 1538 } 1539 } 1540 1541 VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. 1542 1543 // --------------------------------------------------------------------------- 1544 // Encode and write the transformed image. 1545 err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, 1546 enc->current_width_, height, quality, low_effort, 1547 use_cache, &enc->cache_bits_, enc->histo_bits_, 1548 byte_position, &hdr_size, &data_size); 1549 if (err != VP8_ENC_OK) goto Error; 1550 1551 if (picture->stats != NULL) { 1552 WebPAuxStats* const stats = picture->stats; 1553 stats->lossless_features = 0; 1554 if (enc->use_predict_) stats->lossless_features |= 1; 1555 if (enc->use_cross_color_) stats->lossless_features |= 2; 1556 if (enc->use_subtract_green_) stats->lossless_features |= 4; 1557 if (enc->use_palette_) stats->lossless_features |= 8; 1558 stats->histogram_bits = enc->histo_bits_; 1559 stats->transform_bits = enc->transform_bits_; 1560 stats->cache_bits = enc->cache_bits_; 1561 stats->palette_size = enc->palette_size_; 1562 stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); 1563 stats->lossless_hdr_size = hdr_size; 1564 stats->lossless_data_size = data_size; 1565 } 1566 1567 Error: 1568 VP8LEncoderDelete(enc); 1569 return err; 1570 } 1571 1572 int VP8LEncodeImage(const WebPConfig* const config, 1573 const WebPPicture* const picture) { 1574 int width, height; 1575 int has_alpha; 1576 size_t coded_size; 1577 int percent = 0; 1578 int initial_size; 1579 WebPEncodingError err = VP8_ENC_OK; 1580 VP8LBitWriter bw; 1581 1582 if (picture == NULL) return 0; 1583 1584 if (config == NULL || picture->argb == NULL) { 1585 err = VP8_ENC_ERROR_NULL_PARAMETER; 1586 WebPEncodingSetError(picture, err); 1587 return 0; 1588 } 1589 1590 width = picture->width; 1591 height = picture->height; 1592 // Initialize BitWriter with size corresponding to 16 bpp to photo images and 1593 // 8 bpp for graphical images. 1594 initial_size = (config->image_hint == WEBP_HINT_GRAPH) ? 1595 width * height : width * height * 2; 1596 if (!VP8LBitWriterInit(&bw, initial_size)) { 1597 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1598 goto Error; 1599 } 1600 1601 if (!WebPReportProgress(picture, 1, &percent)) { 1602 UserAbort: 1603 err = VP8_ENC_ERROR_USER_ABORT; 1604 goto Error; 1605 } 1606 // Reset stats (for pure lossless coding) 1607 if (picture->stats != NULL) { 1608 WebPAuxStats* const stats = picture->stats; 1609 memset(stats, 0, sizeof(*stats)); 1610 stats->PSNR[0] = 99.f; 1611 stats->PSNR[1] = 99.f; 1612 stats->PSNR[2] = 99.f; 1613 stats->PSNR[3] = 99.f; 1614 stats->PSNR[4] = 99.f; 1615 } 1616 1617 // Write image size. 1618 if (!WriteImageSize(picture, &bw)) { 1619 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1620 goto Error; 1621 } 1622 1623 has_alpha = WebPPictureHasTransparency(picture); 1624 // Write the non-trivial Alpha flag and lossless version. 1625 if (!WriteRealAlphaAndVersion(&bw, has_alpha)) { 1626 err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1627 goto Error; 1628 } 1629 1630 if (!WebPReportProgress(picture, 5, &percent)) goto UserAbort; 1631 1632 // Encode main image stream. 1633 err = VP8LEncodeStream(config, picture, &bw, 1 /*use_cache*/); 1634 if (err != VP8_ENC_OK) goto Error; 1635 1636 // TODO(skal): have a fine-grained progress report in VP8LEncodeStream(). 1637 if (!WebPReportProgress(picture, 90, &percent)) goto UserAbort; 1638 1639 // Finish the RIFF chunk. 1640 err = WriteImage(picture, &bw, &coded_size); 1641 if (err != VP8_ENC_OK) goto Error; 1642 1643 if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; 1644 1645 // Save size. 1646 if (picture->stats != NULL) { 1647 picture->stats->coded_size += (int)coded_size; 1648 picture->stats->lossless_size = (int)coded_size; 1649 } 1650 1651 if (picture->extra_info != NULL) { 1652 const int mb_w = (width + 15) >> 4; 1653 const int mb_h = (height + 15) >> 4; 1654 memset(picture->extra_info, 0, mb_w * mb_h * sizeof(*picture->extra_info)); 1655 } 1656 1657 Error: 1658 if (bw.error_) err = VP8_ENC_ERROR_OUT_OF_MEMORY; 1659 VP8LBitWriterWipeOut(&bw); 1660 if (err != VP8_ENC_OK) { 1661 WebPEncodingSetError(picture, err); 1662 return 0; 1663 } 1664 return 1; 1665 } 1666 1667 //------------------------------------------------------------------------------ 1668