Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: third_party/libwebp/dec/vp8l.c

Issue 116213006: Update libwebp to 0.4.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: After Blink Roll Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/dec/vp8i.h ('k') | third_party/libwebp/dec/vp8li.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 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 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 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
9 // 9 //
10 // main entry for the decoder 10 // main entry for the decoder
11 // 11 //
12 // Authors: Vikas Arora (vikaas.arora@gmail.com) 12 // Authors: Vikas Arora (vikaas.arora@gmail.com)
13 // Jyrki Alakuijala (jyrki@google.com) 13 // Jyrki Alakuijala (jyrki@google.com)
14 14
15 #include <stdio.h> 15 #include <stdio.h>
16 #include <stdlib.h> 16 #include <stdlib.h>
17 #include "./alphai.h"
17 #include "./vp8li.h" 18 #include "./vp8li.h"
18 #include "../dsp/lossless.h" 19 #include "../dsp/lossless.h"
19 #include "../dsp/yuv.h" 20 #include "../dsp/yuv.h"
21 #include "../utils/alpha_processing.h"
20 #include "../utils/huffman.h" 22 #include "../utils/huffman.h"
21 #include "../utils/utils.h" 23 #include "../utils/utils.h"
22 24
23 #if defined(__cplusplus) || defined(c_plusplus)
24 extern "C" {
25 #endif
26
27 #define NUM_ARGB_CACHE_ROWS 16 25 #define NUM_ARGB_CACHE_ROWS 16
28 26
29 static const int kCodeLengthLiterals = 16; 27 static const int kCodeLengthLiterals = 16;
30 static const int kCodeLengthRepeatCode = 16; 28 static const int kCodeLengthRepeatCode = 16;
31 static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; 29 static const int kCodeLengthExtraBits[3] = { 2, 3, 7 };
32 static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; 30 static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
33 31
34 // ----------------------------------------------------------------------------- 32 // -----------------------------------------------------------------------------
35 // Five Huffman codes are used at each meta code: 33 // Five Huffman codes are used at each meta code:
36 // 1. green + length prefix codes + color cache codes, 34 // 1. green + length prefix codes + color cache codes,
(...skipping 15 matching lines...) Expand all
52 NUM_DISTANCE_CODES 50 NUM_DISTANCE_CODES
53 }; 51 };
54 52
55 53
56 #define NUM_CODE_LENGTH_CODES 19 54 #define NUM_CODE_LENGTH_CODES 19
57 static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = { 55 static const uint8_t kCodeLengthCodeOrder[NUM_CODE_LENGTH_CODES] = {
58 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 56 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
59 }; 57 };
60 58
61 #define CODE_TO_PLANE_CODES 120 59 #define CODE_TO_PLANE_CODES 120
62 static const uint8_t code_to_plane_lut[CODE_TO_PLANE_CODES] = { 60 static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = {
63 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, 61 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
64 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, 62 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
65 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, 63 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
66 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, 64 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
67 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, 65 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
68 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, 66 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
69 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, 67 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
70 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, 68 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
71 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, 69 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
72 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, 70 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 static WEBP_INLINE int GetCopyLength(int length_symbol, 132 static WEBP_INLINE int GetCopyLength(int length_symbol,
135 VP8LBitReader* const br) { 133 VP8LBitReader* const br) {
136 // Length and distance prefixes are encoded the same way. 134 // Length and distance prefixes are encoded the same way.
137 return GetCopyDistance(length_symbol, br); 135 return GetCopyDistance(length_symbol, br);
138 } 136 }
139 137
140 static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) { 138 static WEBP_INLINE int PlaneCodeToDistance(int xsize, int plane_code) {
141 if (plane_code > CODE_TO_PLANE_CODES) { 139 if (plane_code > CODE_TO_PLANE_CODES) {
142 return plane_code - CODE_TO_PLANE_CODES; 140 return plane_code - CODE_TO_PLANE_CODES;
143 } else { 141 } else {
144 const int dist_code = code_to_plane_lut[plane_code - 1]; 142 const int dist_code = kCodeToPlane[plane_code - 1];
145 const int yoffset = dist_code >> 4; 143 const int yoffset = dist_code >> 4;
146 const int xoffset = 8 - (dist_code & 0xf); 144 const int xoffset = 8 - (dist_code & 0xf);
147 const int dist = yoffset * xsize + xoffset; 145 const int dist = yoffset * xsize + xoffset;
148 return (dist >= 1) ? dist : 1; 146 return (dist >= 1) ? dist : 1; // dist<1 can happen if xsize is very small
149 } 147 }
150 } 148 }
151 149
152 //------------------------------------------------------------------------------ 150 //------------------------------------------------------------------------------
153 // Decodes the next Huffman code from bit-stream. 151 // Decodes the next Huffman code from bit-stream.
154 // FillBitWindow(br) needs to be called at minimum every second call 152 // FillBitWindow(br) needs to be called at minimum every second call
155 // to ReadSymbol, in order to pre-fetch enough bits. 153 // to ReadSymbol, in order to pre-fetch enough bits.
156 static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree, 154 static WEBP_INLINE int ReadSymbol(const HuffmanTree* tree,
157 VP8LBitReader* const br) { 155 VP8LBitReader* const br) {
158 const HuffmanTreeNode* node = tree->root_; 156 const HuffmanTreeNode* node = tree->root_;
159 int num_bits = 0;
160 uint32_t bits = VP8LPrefetchBits(br); 157 uint32_t bits = VP8LPrefetchBits(br);
158 int bitpos = br->bit_pos_;
159 // Check if we find the bit combination from the Huffman lookup table.
160 const int lut_ix = bits & (HUFF_LUT - 1);
161 const int lut_bits = tree->lut_bits_[lut_ix];
162 if (lut_bits <= HUFF_LUT_BITS) {
163 VP8LSetBitPos(br, bitpos + lut_bits);
164 return tree->lut_symbol_[lut_ix];
165 }
166 node += tree->lut_jump_[lut_ix];
167 bitpos += HUFF_LUT_BITS;
168 bits >>= HUFF_LUT_BITS;
169
170 // Decode the value from a binary tree.
161 assert(node != NULL); 171 assert(node != NULL);
162 while (!HuffmanTreeNodeIsLeaf(node)) { 172 do {
163 node = HuffmanTreeNextNode(node, bits & 1); 173 node = HuffmanTreeNextNode(node, bits & 1);
164 bits >>= 1; 174 bits >>= 1;
165 ++num_bits; 175 ++bitpos;
166 } 176 } while (HuffmanTreeNodeIsNotLeaf(node));
167 VP8LDiscardBits(br, num_bits); 177 VP8LSetBitPos(br, bitpos);
168 return node->symbol_; 178 return node->symbol_;
169 } 179 }
170 180
171 static int ReadHuffmanCodeLengths( 181 static int ReadHuffmanCodeLengths(
172 VP8LDecoder* const dec, const int* const code_length_code_lengths, 182 VP8LDecoder* const dec, const int* const code_length_code_lengths,
173 int num_symbols, int* const code_lengths) { 183 int num_symbols, int* const code_lengths) {
174 int ok = 0; 184 int ok = 0;
175 VP8LBitReader* const br = &dec->br_; 185 VP8LBitReader* const br = &dec->br_;
176 int symbol; 186 int symbol;
177 int max_symbol; 187 int max_symbol;
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 in_width, out_width, in_height, out_height, work); 408 in_width, out_width, in_height, out_height, work);
399 return 1; 409 return 1;
400 } 410 }
401 411
402 //------------------------------------------------------------------------------ 412 //------------------------------------------------------------------------------
403 // Export to ARGB 413 // Export to ARGB
404 414
405 // We have special "export" function since we need to convert from BGRA 415 // We have special "export" function since we need to convert from BGRA
406 static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, 416 static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace,
407 int rgba_stride, uint8_t* const rgba) { 417 int rgba_stride, uint8_t* const rgba) {
408 const uint32_t* const src = (const uint32_t*)rescaler->dst; 418 uint32_t* const src = (uint32_t*)rescaler->dst;
409 const int dst_width = rescaler->dst_width; 419 const int dst_width = rescaler->dst_width;
410 int num_lines_out = 0; 420 int num_lines_out = 0;
411 while (WebPRescalerHasPendingOutput(rescaler)) { 421 while (WebPRescalerHasPendingOutput(rescaler)) {
412 uint8_t* const dst = rgba + num_lines_out * rgba_stride; 422 uint8_t* const dst = rgba + num_lines_out * rgba_stride;
413 WebPRescalerExportRow(rescaler); 423 WebPRescalerExportRow(rescaler);
424 WebPMultARGBRow(src, dst_width, 1);
414 VP8LConvertFromBGRA(src, dst_width, colorspace, dst); 425 VP8LConvertFromBGRA(src, dst_width, colorspace, dst);
415 ++num_lines_out; 426 ++num_lines_out;
416 } 427 }
417 return num_lines_out; 428 return num_lines_out;
418 } 429 }
419 430
420 // Emit scaled rows. 431 // Emit scaled rows.
421 static int EmitRescaledRows(const VP8LDecoder* const dec, 432 static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec,
422 const uint32_t* const data, int in_stride, int mb_h, 433 uint8_t* in, int in_stride, int mb_h,
423 uint8_t* const out, int out_stride) { 434 uint8_t* const out, int out_stride) {
424 const WEBP_CSP_MODE colorspace = dec->output_->colorspace; 435 const WEBP_CSP_MODE colorspace = dec->output_->colorspace;
425 const uint8_t* const in = (const uint8_t*)data;
426 int num_lines_in = 0; 436 int num_lines_in = 0;
427 int num_lines_out = 0; 437 int num_lines_out = 0;
428 while (num_lines_in < mb_h) { 438 while (num_lines_in < mb_h) {
429 const uint8_t* const row_in = in + num_lines_in * in_stride; 439 uint8_t* const row_in = in + num_lines_in * in_stride;
430 uint8_t* const row_out = out + num_lines_out * out_stride; 440 uint8_t* const row_out = out + num_lines_out * out_stride;
431 num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in, 441 const int lines_left = mb_h - num_lines_in;
432 row_in, in_stride); 442 const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
443 assert(needed_lines > 0 && needed_lines <= lines_left);
444 WebPMultARGBRows(row_in, in_stride,
445 dec->rescaler->src_width, needed_lines, 0);
446 WebPRescalerImport(dec->rescaler, lines_left, row_in, in_stride);
447 num_lines_in += needed_lines;
433 num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out); 448 num_lines_out += Export(dec->rescaler, colorspace, out_stride, row_out);
434 } 449 }
435 return num_lines_out; 450 return num_lines_out;
436 } 451 }
437 452
438 // Emit rows without any scaling. 453 // Emit rows without any scaling.
439 static int EmitRows(WEBP_CSP_MODE colorspace, 454 static int EmitRows(WEBP_CSP_MODE colorspace,
440 const uint32_t* const data, int in_stride, 455 const uint8_t* row_in, int in_stride,
441 int mb_w, int mb_h, 456 int mb_w, int mb_h,
442 uint8_t* const out, int out_stride) { 457 uint8_t* const out, int out_stride) {
443 int lines = mb_h; 458 int lines = mb_h;
444 const uint8_t* row_in = (const uint8_t*)data;
445 uint8_t* row_out = out; 459 uint8_t* row_out = out;
446 while (lines-- > 0) { 460 while (lines-- > 0) {
447 VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out); 461 VP8LConvertFromBGRA((const uint32_t*)row_in, mb_w, colorspace, row_out);
448 row_in += in_stride; 462 row_in += in_stride;
449 row_out += out_stride; 463 row_out += out_stride;
450 } 464 }
451 return mb_h; // Num rows out == num rows in. 465 return mb_h; // Num rows out == num rows in.
452 } 466 }
453 467
454 //------------------------------------------------------------------------------ 468 //------------------------------------------------------------------------------
455 // Export to YUVA 469 // Export to YUVA
456 470
457 static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos, 471 static void ConvertToYUVA(const uint32_t* const src, int width, int y_pos,
458 const WebPDecBuffer* const output) { 472 const WebPDecBuffer* const output) {
459 const WebPYUVABuffer* const buf = &output->u.YUVA; 473 const WebPYUVABuffer* const buf = &output->u.YUVA;
460 // first, the luma plane 474 // first, the luma plane
461 { 475 {
462 int i; 476 int i;
463 uint8_t* const y = buf->y + y_pos * buf->y_stride; 477 uint8_t* const y = buf->y + y_pos * buf->y_stride;
464 for (i = 0; i < width; ++i) { 478 for (i = 0; i < width; ++i) {
465 const uint32_t p = src[i]; 479 const uint32_t p = src[i];
466 y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff); 480 y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff,
481 YUV_HALF);
467 } 482 }
468 } 483 }
469 484
470 // then U/V planes 485 // then U/V planes
471 { 486 {
472 uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride; 487 uint8_t* const u = buf->u + (y_pos >> 1) * buf->u_stride;
473 uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride; 488 uint8_t* const v = buf->v + (y_pos >> 1) * buf->v_stride;
474 const int uv_width = width >> 1; 489 const int uv_width = width >> 1;
475 int i; 490 int i;
476 for (i = 0; i < uv_width; ++i) { 491 for (i = 0; i < uv_width; ++i) {
477 const uint32_t v0 = src[2 * i + 0]; 492 const uint32_t v0 = src[2 * i + 0];
478 const uint32_t v1 = src[2 * i + 1]; 493 const uint32_t v1 = src[2 * i + 1];
479 // VP8RGBToU/V expects four accumulated pixels. Hence we need to 494 // VP8RGBToU/V expects four accumulated pixels. Hence we need to
480 // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less. 495 // scale r/g/b value by a factor 2. We just shift v0/v1 one bit less.
481 const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe); 496 const int r = ((v0 >> 15) & 0x1fe) + ((v1 >> 15) & 0x1fe);
482 const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe); 497 const int g = ((v0 >> 7) & 0x1fe) + ((v1 >> 7) & 0x1fe);
483 const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe); 498 const int b = ((v0 << 1) & 0x1fe) + ((v1 << 1) & 0x1fe);
484 if (!(y_pos & 1)) { // even lines: store values 499 if (!(y_pos & 1)) { // even lines: store values
485 u[i] = VP8RGBToU(r, g, b); 500 u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
486 v[i] = VP8RGBToV(r, g, b); 501 v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
487 } else { // odd lines: average with previous values 502 } else { // odd lines: average with previous values
488 const int tmp_u = VP8RGBToU(r, g, b); 503 const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
489 const int tmp_v = VP8RGBToV(r, g, b); 504 const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
490 // Approximated average-of-four. But it's an acceptable diff. 505 // Approximated average-of-four. But it's an acceptable diff.
491 u[i] = (u[i] + tmp_u + 1) >> 1; 506 u[i] = (u[i] + tmp_u + 1) >> 1;
492 v[i] = (v[i] + tmp_v + 1) >> 1; 507 v[i] = (v[i] + tmp_v + 1) >> 1;
493 } 508 }
494 } 509 }
495 if (width & 1) { // last pixel 510 if (width & 1) { // last pixel
496 const uint32_t v0 = src[2 * i + 0]; 511 const uint32_t v0 = src[2 * i + 0];
497 const int r = (v0 >> 14) & 0x3fc; 512 const int r = (v0 >> 14) & 0x3fc;
498 const int g = (v0 >> 6) & 0x3fc; 513 const int g = (v0 >> 6) & 0x3fc;
499 const int b = (v0 << 2) & 0x3fc; 514 const int b = (v0 << 2) & 0x3fc;
500 if (!(y_pos & 1)) { // even lines 515 if (!(y_pos & 1)) { // even lines
501 u[i] = VP8RGBToU(r, g, b); 516 u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2);
502 v[i] = VP8RGBToV(r, g, b); 517 v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2);
503 } else { // odd lines (note: we could just skip this) 518 } else { // odd lines (note: we could just skip this)
504 const int tmp_u = VP8RGBToU(r, g, b); 519 const int tmp_u = VP8RGBToU(r, g, b, YUV_HALF << 2);
505 const int tmp_v = VP8RGBToV(r, g, b); 520 const int tmp_v = VP8RGBToV(r, g, b, YUV_HALF << 2);
506 u[i] = (u[i] + tmp_u + 1) >> 1; 521 u[i] = (u[i] + tmp_u + 1) >> 1;
507 v[i] = (v[i] + tmp_v + 1) >> 1; 522 v[i] = (v[i] + tmp_v + 1) >> 1;
508 } 523 }
509 } 524 }
510 } 525 }
511 // Lastly, store alpha if needed. 526 // Lastly, store alpha if needed.
512 if (buf->a != NULL) { 527 if (buf->a != NULL) {
513 int i; 528 int i;
514 uint8_t* const a = buf->a + y_pos * buf->a_stride; 529 uint8_t* const a = buf->a + y_pos * buf->a_stride;
515 for (i = 0; i < width; ++i) a[i] = (src[i] >> 24); 530 for (i = 0; i < width; ++i) a[i] = (src[i] >> 24);
516 } 531 }
517 } 532 }
518 533
519 static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) { 534 static int ExportYUVA(const VP8LDecoder* const dec, int y_pos) {
520 WebPRescaler* const rescaler = dec->rescaler; 535 WebPRescaler* const rescaler = dec->rescaler;
521 const uint32_t* const src = (const uint32_t*)rescaler->dst; 536 uint32_t* const src = (uint32_t*)rescaler->dst;
522 const int dst_width = rescaler->dst_width; 537 const int dst_width = rescaler->dst_width;
523 int num_lines_out = 0; 538 int num_lines_out = 0;
524 while (WebPRescalerHasPendingOutput(rescaler)) { 539 while (WebPRescalerHasPendingOutput(rescaler)) {
525 WebPRescalerExportRow(rescaler); 540 WebPRescalerExportRow(rescaler);
541 WebPMultARGBRow(src, dst_width, 1);
526 ConvertToYUVA(src, dst_width, y_pos, dec->output_); 542 ConvertToYUVA(src, dst_width, y_pos, dec->output_);
527 ++y_pos; 543 ++y_pos;
528 ++num_lines_out; 544 ++num_lines_out;
529 } 545 }
530 return num_lines_out; 546 return num_lines_out;
531 } 547 }
532 548
533 static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec, 549 static int EmitRescaledRowsYUVA(const VP8LDecoder* const dec,
534 const uint32_t* const data, 550 uint8_t* in, int in_stride, int mb_h) {
535 int in_stride, int mb_h) {
536 const uint8_t* const in = (const uint8_t*)data;
537 int num_lines_in = 0; 551 int num_lines_in = 0;
538 int y_pos = dec->last_out_row_; 552 int y_pos = dec->last_out_row_;
539 while (num_lines_in < mb_h) { 553 while (num_lines_in < mb_h) {
540 const uint8_t* const row_in = in + num_lines_in * in_stride; 554 const int lines_left = mb_h - num_lines_in;
541 num_lines_in += WebPRescalerImport(dec->rescaler, mb_h - num_lines_in, 555 const int needed_lines = WebPRescaleNeededLines(dec->rescaler, lines_left);
542 row_in, in_stride); 556 WebPMultARGBRows(in, in_stride, dec->rescaler->src_width, needed_lines, 0);
557 WebPRescalerImport(dec->rescaler, lines_left, in, in_stride);
558 num_lines_in += needed_lines;
559 in += needed_lines * in_stride;
543 y_pos += ExportYUVA(dec, y_pos); 560 y_pos += ExportYUVA(dec, y_pos);
544 } 561 }
545 return y_pos; 562 return y_pos;
546 } 563 }
547 564
548 static int EmitRowsYUVA(const VP8LDecoder* const dec, 565 static int EmitRowsYUVA(const VP8LDecoder* const dec,
549 const uint32_t* const data, int in_stride, 566 const uint8_t* in, int in_stride,
550 int mb_w, int num_rows) { 567 int mb_w, int num_rows) {
551 int y_pos = dec->last_out_row_; 568 int y_pos = dec->last_out_row_;
552 const uint8_t* row_in = (const uint8_t*)data;
553 while (num_rows-- > 0) { 569 while (num_rows-- > 0) {
554 ConvertToYUVA((const uint32_t*)row_in, mb_w, y_pos, dec->output_); 570 ConvertToYUVA((const uint32_t*)in, mb_w, y_pos, dec->output_);
555 row_in += in_stride; 571 in += in_stride;
556 ++y_pos; 572 ++y_pos;
557 } 573 }
558 return y_pos; 574 return y_pos;
559 } 575 }
560 576
561 //------------------------------------------------------------------------------ 577 //------------------------------------------------------------------------------
562 // Cropping. 578 // Cropping.
563 579
564 // Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and 580 // Sets io->mb_y, io->mb_h & io->mb_w according to start row, end row and
565 // crop options. Also updates the input data pointer, so that it points to the 581 // crop options. Also updates the input data pointer, so that it points to the
566 // start of the cropped window. 582 // start of the cropped window. Note that pixels are in ARGB format even if
567 // Note that 'pixel_stride' is in units of 'uint32_t' (and not 'bytes). 583 // 'in_data' is uint8_t*.
568 // Returns true if the crop window is not empty. 584 // Returns true if the crop window is not empty.
569 static int SetCropWindow(VP8Io* const io, int y_start, int y_end, 585 static int SetCropWindow(VP8Io* const io, int y_start, int y_end,
570 const uint32_t** const in_data, int pixel_stride) { 586 uint8_t** const in_data, int pixel_stride) {
571 assert(y_start < y_end); 587 assert(y_start < y_end);
572 assert(io->crop_left < io->crop_right); 588 assert(io->crop_left < io->crop_right);
573 if (y_end > io->crop_bottom) { 589 if (y_end > io->crop_bottom) {
574 y_end = io->crop_bottom; // make sure we don't overflow on last row. 590 y_end = io->crop_bottom; // make sure we don't overflow on last row.
575 } 591 }
576 if (y_start < io->crop_top) { 592 if (y_start < io->crop_top) {
577 const int delta = io->crop_top - y_start; 593 const int delta = io->crop_top - y_start;
578 y_start = io->crop_top; 594 y_start = io->crop_top;
579 *in_data += pixel_stride * delta; 595 *in_data += delta * pixel_stride;
580 } 596 }
581 if (y_start >= y_end) return 0; // Crop window is empty. 597 if (y_start >= y_end) return 0; // Crop window is empty.
582 598
583 *in_data += io->crop_left; 599 *in_data += io->crop_left * sizeof(uint32_t);
584 600
585 io->mb_y = y_start - io->crop_top; 601 io->mb_y = y_start - io->crop_top;
586 io->mb_w = io->crop_right - io->crop_left; 602 io->mb_w = io->crop_right - io->crop_left;
587 io->mb_h = y_end - y_start; 603 io->mb_h = y_end - y_start;
588 return 1; // Non-empty crop window. 604 return 1; // Non-empty crop window.
589 } 605 }
590 606
591 //------------------------------------------------------------------------------ 607 //------------------------------------------------------------------------------
592 608
593 static WEBP_INLINE int GetMetaIndex( 609 static WEBP_INLINE int GetMetaIndex(
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 static void ProcessRows(VP8LDecoder* const dec, int row) { 663 static void ProcessRows(VP8LDecoder* const dec, int row) {
648 const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_; 664 const uint32_t* const rows = dec->pixels_ + dec->width_ * dec->last_row_;
649 const int num_rows = row - dec->last_row_; 665 const int num_rows = row - dec->last_row_;
650 666
651 if (num_rows <= 0) return; // Nothing to be done. 667 if (num_rows <= 0) return; // Nothing to be done.
652 ApplyInverseTransforms(dec, num_rows, rows); 668 ApplyInverseTransforms(dec, num_rows, rows);
653 669
654 // Emit output. 670 // Emit output.
655 { 671 {
656 VP8Io* const io = dec->io_; 672 VP8Io* const io = dec->io_;
657 const uint32_t* rows_data = dec->argb_cache_; 673 uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
658 if (!SetCropWindow(io, dec->last_row_, row, &rows_data, io->width)) { 674 const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
675 if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
659 // Nothing to output (this time). 676 // Nothing to output (this time).
660 } else { 677 } else {
661 const WebPDecBuffer* const output = dec->output_; 678 const WebPDecBuffer* const output = dec->output_;
662 const int in_stride = io->width * sizeof(*rows_data);
663 if (output->colorspace < MODE_YUV) { // convert to RGBA 679 if (output->colorspace < MODE_YUV) { // convert to RGBA
664 const WebPRGBABuffer* const buf = &output->u.RGBA; 680 const WebPRGBABuffer* const buf = &output->u.RGBA;
665 uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; 681 uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride;
666 const int num_rows_out = io->use_scaling ? 682 const int num_rows_out = io->use_scaling ?
667 EmitRescaledRows(dec, rows_data, in_stride, io->mb_h, 683 EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h,
668 rgba, buf->stride) : 684 rgba, buf->stride) :
669 EmitRows(output->colorspace, rows_data, in_stride, 685 EmitRows(output->colorspace, rows_data, in_stride,
670 io->mb_w, io->mb_h, rgba, buf->stride); 686 io->mb_w, io->mb_h, rgba, buf->stride);
671 // Update 'last_out_row_'. 687 // Update 'last_out_row_'.
672 dec->last_out_row_ += num_rows_out; 688 dec->last_out_row_ += num_rows_out;
673 } else { // convert to YUVA 689 } else { // convert to YUVA
674 dec->last_out_row_ = io->use_scaling ? 690 dec->last_out_row_ = io->use_scaling ?
675 EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) : 691 EmitRescaledRowsYUVA(dec, rows_data, in_stride, io->mb_h) :
676 EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h); 692 EmitRowsYUVA(dec, rows_data, in_stride, io->mb_w, io->mb_h);
677 } 693 }
678 assert(dec->last_out_row_ <= output->height); 694 assert(dec->last_out_row_ <= output->height);
679 } 695 }
680 } 696 }
681 697
682 // Update 'last_row_'. 698 // Update 'last_row_'.
683 dec->last_row_ = row; 699 dec->last_row_ = row;
684 assert(dec->last_row_ <= dec->height_); 700 assert(dec->last_row_ <= dec->height_);
685 } 701 }
686 702
687 #define DECODE_DATA_FUNC(FUNC_NAME, TYPE, STORE_PIXEL) \ 703 // Row-processing for the special case when alpha data contains only one
688 static int FUNC_NAME(VP8LDecoder* const dec, TYPE* const data, int width, \ 704 // transform (color indexing), and trivial non-green literals.
689 int height, ProcessRowsFunc process_func) { \ 705 static int Is8bOptimizable(const VP8LMetadata* const hdr) {
690 int ok = 1; \ 706 int i;
691 int col = 0, row = 0; \ 707 if (hdr->color_cache_size_ > 0) return 0;
692 VP8LBitReader* const br = &dec->br_; \ 708 // When the Huffman tree contains only one symbol, we can skip the
693 VP8LMetadata* const hdr = &dec->hdr_; \ 709 // call to ReadSymbol() for red/blue/alpha channels.
694 HTreeGroup* htree_group = hdr->htree_groups_; \ 710 for (i = 0; i < hdr->num_htree_groups_; ++i) {
695 TYPE* src = data; \ 711 const HuffmanTree* const htrees = hdr->htree_groups_[i].htrees_;
696 TYPE* last_cached = data; \ 712 if (htrees[RED].num_nodes_ > 1) return 0;
697 TYPE* const src_end = data + width * height; \ 713 if (htrees[BLUE].num_nodes_ > 1) return 0;
698 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES; \ 714 if (htrees[ALPHA].num_nodes_ > 1) return 0;
699 const int color_cache_limit = len_code_limit + hdr->color_cache_size_; \ 715 }
700 VP8LColorCache* const color_cache = \ 716 return 1;
701 (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL; \ 717 }
702 const int mask = hdr->huffman_mask_; \ 718
703 assert(htree_group != NULL); \ 719 static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) {
704 while (!br->eos_ && src < src_end) { \ 720 const int num_rows = row - dec->last_row_;
705 int code; \ 721 const uint8_t* const in =
706 /* Only update when changing tile. Note we could use this test: */ \ 722 (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_;
707 /* if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed */ \ 723 if (num_rows > 0) {
708 /* but that's actually slower and needs storing the previous col/row. */ \ 724 ApplyInverseTransformsAlpha(dec, num_rows, in);
709 if ((col & mask) == 0) { \ 725 }
710 htree_group = GetHtreeGroupForPos(hdr, col, row); \ 726 dec->last_row_ = dec->last_out_row_ = row;
711 } \ 727 }
712 VP8LFillBitWindow(br); \ 728
713 code = ReadSymbol(&htree_group->htrees_[GREEN], br); \ 729 static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data,
714 if (code < NUM_LITERAL_CODES) { /* Literal*/ \ 730 int width, int height, int last_row) {
715 int red, green, blue, alpha; \ 731 int ok = 1;
716 red = ReadSymbol(&htree_group->htrees_[RED], br); \ 732 int row = dec->last_pixel_ / width;
717 green = code; \ 733 int col = dec->last_pixel_ % width;
718 VP8LFillBitWindow(br); \ 734 VP8LBitReader* const br = &dec->br_;
719 blue = ReadSymbol(&htree_group->htrees_[BLUE], br); \ 735 VP8LMetadata* const hdr = &dec->hdr_;
720 alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br); \ 736 const HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
721 *src = STORE_PIXEL(alpha, red, green, blue); \ 737 int pos = dec->last_pixel_; // current position
722 AdvanceByOne: \ 738 const int end = width * height; // End of data
723 ++src; \ 739 const int last = width * last_row; // Last pixel to decode
724 ++col; \ 740 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
725 if (col >= width) { \ 741 const int mask = hdr->huffman_mask_;
726 col = 0; \ 742 assert(htree_group != NULL);
727 ++row; \ 743 assert(last_row <= height);
728 if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) { \ 744 assert(Is8bOptimizable(hdr));
729 process_func(dec, row); \ 745
730 } \ 746 while (!br->eos_ && pos < last) {
731 if (color_cache != NULL) { \ 747 int code;
732 while (last_cached < src) { \ 748 // Only update when changing tile.
733 VP8LColorCacheInsert(color_cache, *last_cached++); \ 749 if ((col & mask) == 0) {
734 } \ 750 htree_group = GetHtreeGroupForPos(hdr, col, row);
735 } \ 751 }
736 } \ 752 VP8LFillBitWindow(br);
737 } else if (code < len_code_limit) { /* Backward reference */ \ 753 code = ReadSymbol(&htree_group->htrees_[GREEN], br);
738 int dist_code, dist; \ 754 if (code < NUM_LITERAL_CODES) { // Literal
739 const int length_sym = code - NUM_LITERAL_CODES; \ 755 data[pos] = code;
740 const int length = GetCopyLength(length_sym, br); \ 756 ++pos;
741 const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br); \ 757 ++col;
742 VP8LFillBitWindow(br); \ 758 if (col >= width) {
743 dist_code = GetCopyDistance(dist_symbol, br); \ 759 col = 0;
744 dist = PlaneCodeToDistance(width, dist_code); \ 760 ++row;
745 if (src - data < dist || src_end - src < length) { \ 761 if (row % NUM_ARGB_CACHE_ROWS == 0) {
746 ok = 0; \ 762 ExtractPalettedAlphaRows(dec, row);
747 goto End; \ 763 }
748 } \ 764 }
749 { \ 765 } else if (code < len_code_limit) { // Backward reference
750 int i; \ 766 int dist_code, dist;
751 for (i = 0; i < length; ++i) src[i] = src[i - dist]; \ 767 const int length_sym = code - NUM_LITERAL_CODES;
752 src += length; \ 768 const int length = GetCopyLength(length_sym, br);
753 } \ 769 const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
754 col += length; \ 770 VP8LFillBitWindow(br);
755 while (col >= width) { \ 771 dist_code = GetCopyDistance(dist_symbol, br);
756 col -= width; \ 772 dist = PlaneCodeToDistance(width, dist_code);
757 ++row; \ 773 if (pos >= dist && end - pos >= length) {
758 if ((process_func != NULL) && (row % NUM_ARGB_CACHE_ROWS == 0)) { \ 774 int i;
759 process_func(dec, row); \ 775 for (i = 0; i < length; ++i) data[pos + i] = data[pos + i - dist];
760 } \ 776 } else {
761 } \ 777 ok = 0;
762 if (src < src_end) { \ 778 goto End;
763 htree_group = GetHtreeGroupForPos(hdr, col, row); \ 779 }
764 if (color_cache != NULL) { \ 780 pos += length;
765 while (last_cached < src) { \ 781 col += length;
766 VP8LColorCacheInsert(color_cache, *last_cached++); \ 782 while (col >= width) {
767 } \ 783 col -= width;
768 } \ 784 ++row;
769 } \ 785 if (row % NUM_ARGB_CACHE_ROWS == 0) {
770 } else if (code < color_cache_limit) { /* Color cache */ \ 786 ExtractPalettedAlphaRows(dec, row);
771 const int key = code - len_code_limit; \ 787 }
772 assert(color_cache != NULL); \ 788 }
773 while (last_cached < src) { \ 789 if (pos < last && (col & mask)) {
774 VP8LColorCacheInsert(color_cache, *last_cached++); \ 790 htree_group = GetHtreeGroupForPos(hdr, col, row);
775 } \ 791 }
776 *src = VP8LColorCacheLookup(color_cache, key); \ 792 } else { // Not reached
777 goto AdvanceByOne; \ 793 ok = 0;
778 } else { /* Not reached */ \ 794 goto End;
779 ok = 0; \ 795 }
780 goto End; \ 796 ok = !br->error_;
781 } \ 797 if (!ok) goto End;
782 ok = !br->error_; \ 798 }
783 if (!ok) goto End; \ 799 // Process the remaining rows corresponding to last row-block.
784 } \ 800 ExtractPalettedAlphaRows(dec, row);
785 /* Process the remaining rows corresponding to last row-block. */ \ 801
786 if (process_func != NULL) process_func(dec, row); \ 802 End:
787 End: \ 803 if (br->error_ || !ok || (br->eos_ && pos < end)) {
788 if (br->error_ || !ok || (br->eos_ && src < src_end)) { \ 804 ok = 0;
789 ok = 0; \ 805 dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
790 dec->status_ = \ 806 : VP8_STATUS_BITSTREAM_ERROR;
791 (!br->eos_) ? VP8_STATUS_BITSTREAM_ERROR : VP8_STATUS_SUSPENDED; \ 807 } else {
792 } else if (src == src_end) { \ 808 dec->last_pixel_ = (int)pos;
793 dec->state_ = READ_DATA; \ 809 if (pos == end) dec->state_ = READ_DATA;
794 } \ 810 }
795 return ok; \ 811 return ok;
796 } 812 }
797 813
798 static WEBP_INLINE uint32_t GetARGBPixel(int alpha, int red, int green, 814 static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
799 int blue) { 815 int width, int height, int last_row,
800 return (alpha << 24) | (red << 16) | (green << 8) | blue; 816 ProcessRowsFunc process_func) {
801 } 817 int ok = 1;
802 818 int row = dec->last_pixel_ / width;
803 static WEBP_INLINE uint8_t GetAlphaPixel(int alpha, int red, int green, 819 int col = dec->last_pixel_ % width;
804 int blue) { 820 VP8LBitReader* const br = &dec->br_;
805 (void)alpha; 821 VP8LMetadata* const hdr = &dec->hdr_;
806 (void)red; 822 HTreeGroup* htree_group = GetHtreeGroupForPos(hdr, col, row);
807 (void)blue; 823 uint32_t* src = data + dec->last_pixel_;
808 return green; // Alpha value is stored in green channel. 824 uint32_t* last_cached = src;
809 } 825 uint32_t* const src_end = data + width * height; // End of data
810 826 uint32_t* const src_last = data + width * last_row; // Last pixel to decode
811 DECODE_DATA_FUNC(DecodeImageData, uint32_t, GetARGBPixel) 827 const int len_code_limit = NUM_LITERAL_CODES + NUM_LENGTH_CODES;
812 DECODE_DATA_FUNC(DecodeAlphaData, uint8_t, GetAlphaPixel) 828 const int color_cache_limit = len_code_limit + hdr->color_cache_size_;
813 829 VP8LColorCache* const color_cache =
814 #undef DECODE_DATA_FUNC 830 (hdr->color_cache_size_ > 0) ? &hdr->color_cache_ : NULL;
831 const int mask = hdr->huffman_mask_;
832 assert(htree_group != NULL);
833 assert(src_last <= src_end);
834
835 while (!br->eos_ && src < src_last) {
836 int code;
837 // Only update when changing tile. Note we could use this test:
838 // if "((((prev_col ^ col) | prev_row ^ row)) > mask)" -> tile changed
839 // but that's actually slower and needs storing the previous col/row.
840 if ((col & mask) == 0) {
841 htree_group = GetHtreeGroupForPos(hdr, col, row);
842 }
843 VP8LFillBitWindow(br);
844 code = ReadSymbol(&htree_group->htrees_[GREEN], br);
845 if (code < NUM_LITERAL_CODES) { // Literal
846 int red, green, blue, alpha;
847 red = ReadSymbol(&htree_group->htrees_[RED], br);
848 green = code;
849 VP8LFillBitWindow(br);
850 blue = ReadSymbol(&htree_group->htrees_[BLUE], br);
851 alpha = ReadSymbol(&htree_group->htrees_[ALPHA], br);
852 *src = (alpha << 24) | (red << 16) | (green << 8) | blue;
853 AdvanceByOne:
854 ++src;
855 ++col;
856 if (col >= width) {
857 col = 0;
858 ++row;
859 if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
860 process_func(dec, row);
861 }
862 if (color_cache != NULL) {
863 while (last_cached < src) {
864 VP8LColorCacheInsert(color_cache, *last_cached++);
865 }
866 }
867 }
868 } else if (code < len_code_limit) { // Backward reference
869 int dist_code, dist;
870 const int length_sym = code - NUM_LITERAL_CODES;
871 const int length = GetCopyLength(length_sym, br);
872 const int dist_symbol = ReadSymbol(&htree_group->htrees_[DIST], br);
873 VP8LFillBitWindow(br);
874 dist_code = GetCopyDistance(dist_symbol, br);
875 dist = PlaneCodeToDistance(width, dist_code);
876 if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
877 ok = 0;
878 goto End;
879 } else {
880 int i;
881 for (i = 0; i < length; ++i) src[i] = src[i - dist];
882 src += length;
883 }
884 col += length;
885 while (col >= width) {
886 col -= width;
887 ++row;
888 if ((row % NUM_ARGB_CACHE_ROWS == 0) && (process_func != NULL)) {
889 process_func(dec, row);
890 }
891 }
892 if (src < src_last) {
893 if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row);
894 if (color_cache != NULL) {
895 while (last_cached < src) {
896 VP8LColorCacheInsert(color_cache, *last_cached++);
897 }
898 }
899 }
900 } else if (code < color_cache_limit) { // Color cache
901 const int key = code - len_code_limit;
902 assert(color_cache != NULL);
903 while (last_cached < src) {
904 VP8LColorCacheInsert(color_cache, *last_cached++);
905 }
906 *src = VP8LColorCacheLookup(color_cache, key);
907 goto AdvanceByOne;
908 } else { // Not reached
909 ok = 0;
910 goto End;
911 }
912 ok = !br->error_;
913 if (!ok) goto End;
914 }
915 // Process the remaining rows corresponding to last row-block.
916 if (process_func != NULL) process_func(dec, row);
917
918 End:
919 if (br->error_ || !ok || (br->eos_ && src < src_end)) {
920 ok = 0;
921 dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED
922 : VP8_STATUS_BITSTREAM_ERROR;
923 } else {
924 dec->last_pixel_ = (int)(src - data);
925 if (src == src_end) dec->state_ = READ_DATA;
926 }
927 return ok;
928 }
815 929
816 // ----------------------------------------------------------------------------- 930 // -----------------------------------------------------------------------------
817 // VP8LTransform 931 // VP8LTransform
818 932
819 static void ClearTransform(VP8LTransform* const transform) { 933 static void ClearTransform(VP8LTransform* const transform) {
820 free(transform->data_); 934 free(transform->data_);
821 transform->data_ = NULL; 935 transform->data_ = NULL;
822 } 936 }
823 937
824 // For security reason, we need to remap the color map to span 938 // For security reason, we need to remap the color map to span
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 1033
920 // ----------------------------------------------------------------------------- 1034 // -----------------------------------------------------------------------------
921 // VP8LDecoder 1035 // VP8LDecoder
922 1036
923 VP8LDecoder* VP8LNew(void) { 1037 VP8LDecoder* VP8LNew(void) {
924 VP8LDecoder* const dec = (VP8LDecoder*)calloc(1, sizeof(*dec)); 1038 VP8LDecoder* const dec = (VP8LDecoder*)calloc(1, sizeof(*dec));
925 if (dec == NULL) return NULL; 1039 if (dec == NULL) return NULL;
926 dec->status_ = VP8_STATUS_OK; 1040 dec->status_ = VP8_STATUS_OK;
927 dec->action_ = READ_DIM; 1041 dec->action_ = READ_DIM;
928 dec->state_ = READ_DIM; 1042 dec->state_ = READ_DIM;
1043
1044 VP8LDspInit(); // Init critical function pointers.
1045
929 return dec; 1046 return dec;
930 } 1047 }
931 1048
932 void VP8LClear(VP8LDecoder* const dec) { 1049 void VP8LClear(VP8LDecoder* const dec) {
933 int i; 1050 int i;
934 if (dec == NULL) return; 1051 if (dec == NULL) return;
935 ClearMetadata(&dec->hdr_); 1052 ClearMetadata(&dec->hdr_);
936 1053
937 free(dec->pixels_); 1054 free(dec->pixels_);
938 dec->pixels_ = NULL; 1055 dec->pixels_ = NULL;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize; 1141 const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
1025 data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data)); 1142 data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
1026 if (data == NULL) { 1143 if (data == NULL) {
1027 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1144 dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1028 ok = 0; 1145 ok = 0;
1029 goto End; 1146 goto End;
1030 } 1147 }
1031 } 1148 }
1032 1149
1033 // Use the Huffman trees to decode the LZ77 encoded data. 1150 // Use the Huffman trees to decode the LZ77 encoded data.
1034 ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, NULL); 1151 ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
1152 transform_ysize, NULL);
1035 ok = ok && !br->error_; 1153 ok = ok && !br->error_;
1036 1154
1037 End: 1155 End:
1038 1156
1039 if (!ok) { 1157 if (!ok) {
1040 free(data); 1158 free(data);
1041 ClearMetadata(hdr); 1159 ClearMetadata(hdr);
1042 // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the 1160 // If not enough data (br.eos_) resulted in BIT_STREAM_ERROR, update the
1043 // status appropriately. 1161 // status appropriately.
1044 if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) { 1162 if (dec->status_ == VP8_STATUS_BITSTREAM_ERROR && dec->br_.eos_) {
1045 dec->status_ = VP8_STATUS_SUSPENDED; 1163 dec->status_ = VP8_STATUS_SUSPENDED;
1046 } 1164 }
1047 } else { 1165 } else {
1048 if (decoded_data != NULL) { 1166 if (decoded_data != NULL) {
1049 *decoded_data = data; 1167 *decoded_data = data;
1050 } else { 1168 } else {
1051 // We allocate image data in this function only for transforms. At level 0 1169 // We allocate image data in this function only for transforms. At level 0
1052 // (that is: not the transforms), we shouldn't have allocated anything. 1170 // (that is: not the transforms), we shouldn't have allocated anything.
1053 assert(data == NULL); 1171 assert(data == NULL);
1054 assert(is_level0); 1172 assert(is_level0);
1055 } 1173 }
1174 dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
1056 if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind. 1175 if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
1057 } 1176 }
1058 return ok; 1177 return ok;
1059 } 1178 }
1060 1179
1061 //------------------------------------------------------------------------------ 1180 //------------------------------------------------------------------------------
1062 // Allocate internal buffers dec->pixels_ and dec->argb_cache_. 1181 // Allocate internal buffers dec->pixels_ and dec->argb_cache_.
1063 static int AllocateInternalBuffers(VP8LDecoder* const dec, int final_width, 1182 static int AllocateInternalBuffers32b(VP8LDecoder* const dec, int final_width) {
1064 size_t bytes_per_pixel) {
1065 const int argb_cache_needed = (bytes_per_pixel == sizeof(uint32_t));
1066 const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_; 1183 const uint64_t num_pixels = (uint64_t)dec->width_ * dec->height_;
1067 // Scratch buffer corresponding to top-prediction row for transforming the 1184 // Scratch buffer corresponding to top-prediction row for transforming the
1068 // first row in the row-blocks. Not needed for paletted alpha. 1185 // first row in the row-blocks. Not needed for paletted alpha.
1069 const uint64_t cache_top_pixels = 1186 const uint64_t cache_top_pixels = (uint16_t)final_width;
1070 argb_cache_needed ? (uint16_t)final_width : 0ULL;
1071 // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha. 1187 // Scratch buffer for temporary BGRA storage. Not needed for paletted alpha.
1072 const uint64_t cache_pixels = 1188 const uint64_t cache_pixels = (uint64_t)final_width * NUM_ARGB_CACHE_ROWS;
1073 argb_cache_needed ? (uint64_t)final_width * NUM_ARGB_CACHE_ROWS : 0ULL;
1074 const uint64_t total_num_pixels = 1189 const uint64_t total_num_pixels =
1075 num_pixels + cache_top_pixels + cache_pixels; 1190 num_pixels + cache_top_pixels + cache_pixels;
1076 1191
1077 assert(dec->width_ <= final_width); 1192 assert(dec->width_ <= final_width);
1078 dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, bytes_per_pixel); 1193 dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint32_t));
1079 if (dec->pixels_ == NULL) { 1194 if (dec->pixels_ == NULL) {
1080 dec->argb_cache_ = NULL; // for sanity check 1195 dec->argb_cache_ = NULL; // for sanity check
1081 dec->status_ = VP8_STATUS_OUT_OF_MEMORY; 1196 dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1082 return 0; 1197 return 0;
1083 } 1198 }
1084 dec->argb_cache_ = 1199 dec->argb_cache_ = dec->pixels_ + num_pixels + cache_top_pixels;
1085 argb_cache_needed ? dec->pixels_ + num_pixels + cache_top_pixels : NULL;
1086 return 1; 1200 return 1;
1087 } 1201 }
1088 1202
1203 static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
1204 const uint64_t total_num_pixels = (uint64_t)dec->width_ * dec->height_;
1205 dec->argb_cache_ = NULL; // for sanity check
1206 dec->pixels_ = (uint32_t*)WebPSafeMalloc(total_num_pixels, sizeof(uint8_t));
1207 if (dec->pixels_ == NULL) {
1208 dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
1209 return 0;
1210 }
1211 return 1;
1212 }
1213
1089 //------------------------------------------------------------------------------ 1214 //------------------------------------------------------------------------------
1090 1215
1091 // Special row-processing that only stores the alpha data. 1216 // Special row-processing that only stores the alpha data.
1092 static void ExtractAlphaRows(VP8LDecoder* const dec, int row) { 1217 static void ExtractAlphaRows(VP8LDecoder* const dec, int row) {
1093 const int num_rows = row - dec->last_row_; 1218 const int num_rows = row - dec->last_row_;
1094 const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_; 1219 const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_;
1095 1220
1096 if (num_rows <= 0) return; // Nothing to be done. 1221 if (num_rows <= 0) return; // Nothing to be done.
1097 ApplyInverseTransforms(dec, num_rows, in); 1222 ApplyInverseTransforms(dec, num_rows, in);
1098 1223
1099 // Extract alpha (which is stored in the green plane). 1224 // Extract alpha (which is stored in the green plane).
1100 { 1225 {
1101 const int width = dec->io_->width; // the final width (!= dec->width_) 1226 const int width = dec->io_->width; // the final width (!= dec->width_)
1102 const int cache_pixs = width * num_rows; 1227 const int cache_pixs = width * num_rows;
1103 uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_; 1228 uint8_t* const dst = (uint8_t*)dec->io_->opaque + width * dec->last_row_;
1104 const uint32_t* const src = dec->argb_cache_; 1229 const uint32_t* const src = dec->argb_cache_;
1105 int i; 1230 int i;
1106 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff; 1231 for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
1107 } 1232 }
1108 dec->last_row_ = dec->last_out_row_ = row; 1233 dec->last_row_ = dec->last_out_row_ = row;
1109 } 1234 }
1110 1235
1111 // Row-processing for the special case when alpha data contains only one 1236 int VP8LDecodeAlphaHeader(ALPHDecoder* const alph_dec,
1112 // transform: color indexing. 1237 const uint8_t* const data, size_t data_size,
1113 static void ExtractPalettedAlphaRows(VP8LDecoder* const dec, int row) { 1238 uint8_t* const output) {
1114 const int num_rows = row - dec->last_row_; 1239 int ok = 0;
1115 const uint8_t* const in = 1240 VP8LDecoder* dec;
1116 (uint8_t*)dec->pixels_ + dec->width_ * dec->last_row_; 1241 VP8Io* io;
1117 if (num_rows <= 0) return; // Nothing to be done. 1242 assert(alph_dec != NULL);
1118 ApplyInverseTransformsAlpha(dec, num_rows, in); 1243 alph_dec->vp8l_dec_ = VP8LNew();
1119 dec->last_row_ = dec->last_out_row_ = row; 1244 if (alph_dec->vp8l_dec_ == NULL) return 0;
1120 } 1245 dec = alph_dec->vp8l_dec_;
1121 1246
1122 int VP8LDecodeAlphaImageStream(int width, int height, const uint8_t* const data, 1247 dec->width_ = alph_dec->width_;
1123 size_t data_size, uint8_t* const output) { 1248 dec->height_ = alph_dec->height_;
1124 VP8Io io; 1249 dec->io_ = &alph_dec->io_;
1125 int ok = 0; 1250 io = dec->io_;
1126 VP8LDecoder* const dec = VP8LNew();
1127 size_t bytes_per_pixel = sizeof(uint32_t); // Default: BGRA mode.
1128 if (dec == NULL) return 0;
1129 1251
1130 dec->width_ = width; 1252 VP8InitIo(io);
1131 dec->height_ = height; 1253 WebPInitCustomIo(NULL, io); // Just a sanity Init. io won't be used.
1132 dec->io_ = &io; 1254 io->opaque = output;
1133 1255 io->width = alph_dec->width_;
1134 VP8InitIo(&io); 1256 io->height = alph_dec->height_;
1135 WebPInitCustomIo(NULL, &io); // Just a sanity Init. io won't be used.
1136 io.opaque = output;
1137 io.width = width;
1138 io.height = height;
1139 1257
1140 dec->status_ = VP8_STATUS_OK; 1258 dec->status_ = VP8_STATUS_OK;
1141 VP8LInitBitReader(&dec->br_, data, data_size); 1259 VP8LInitBitReader(&dec->br_, data, data_size);
1142 1260
1143 dec->action_ = READ_HDR; 1261 dec->action_ = READ_HDR;
1144 if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Err; 1262 if (!DecodeImageStream(alph_dec->width_, alph_dec->height_, 1, dec, NULL)) {
1263 goto Err;
1264 }
1145 1265
1146 // Special case: if alpha data uses only the color indexing transform and 1266 // Special case: if alpha data uses only the color indexing transform and
1147 // doesn't use color cache (a frequent case), we will use DecodeAlphaData() 1267 // doesn't use color cache (a frequent case), we will use DecodeAlphaData()
1148 // method that only needs allocation of 1 byte per pixel (alpha channel). 1268 // method that only needs allocation of 1 byte per pixel (alpha channel).
1149 if (dec->next_transform_ == 1 && 1269 if (dec->next_transform_ == 1 &&
1150 dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM && 1270 dec->transforms_[0].type_ == COLOR_INDEXING_TRANSFORM &&
1151 dec->hdr_.color_cache_size_ == 0) { 1271 Is8bOptimizable(&dec->hdr_)) {
1152 bytes_per_pixel = sizeof(uint8_t); 1272 alph_dec->use_8b_decode = 1;
1273 ok = AllocateInternalBuffers8b(dec);
1274 } else {
1275 // Allocate internal buffers (note that dec->width_ may have changed here).
1276 alph_dec->use_8b_decode = 0;
1277 ok = AllocateInternalBuffers32b(dec, alph_dec->width_);
1153 } 1278 }
1154 1279
1155 // Allocate internal buffers (note that dec->width_ may have changed here). 1280 if (!ok) goto Err;
1156 if (!AllocateInternalBuffers(dec, width, bytes_per_pixel)) goto Err; 1281
1282 dec->action_ = READ_DATA;
1283 return 1;
1284
1285 Err:
1286 VP8LDelete(alph_dec->vp8l_dec_);
1287 alph_dec->vp8l_dec_ = NULL;
1288 return 0;
1289 }
1290
1291 int VP8LDecodeAlphaImageStream(ALPHDecoder* const alph_dec, int last_row) {
1292 VP8LDecoder* const dec = alph_dec->vp8l_dec_;
1293 assert(dec != NULL);
1294 assert(dec->action_ == READ_DATA);
1295 assert(last_row <= dec->height_);
1157 1296
1158 // Decode (with special row processing). 1297 // Decode (with special row processing).
1159 dec->action_ = READ_DATA; 1298 return alph_dec->use_8b_decode ?
1160 ok = (bytes_per_pixel == sizeof(uint8_t)) ?
1161 DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_, 1299 DecodeAlphaData(dec, (uint8_t*)dec->pixels_, dec->width_, dec->height_,
1162 ExtractPalettedAlphaRows) : 1300 last_row) :
1163 DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, 1301 DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
1164 ExtractAlphaRows); 1302 last_row, ExtractAlphaRows);
1165
1166 Err:
1167 VP8LDelete(dec);
1168 return ok;
1169 } 1303 }
1170 1304
1171 //------------------------------------------------------------------------------ 1305 //------------------------------------------------------------------------------
1172 1306
1173 int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) { 1307 int VP8LDecodeHeader(VP8LDecoder* const dec, VP8Io* const io) {
1174 int width, height, has_alpha; 1308 int width, height, has_alpha;
1175 1309
1176 if (dec == NULL) return 0; 1310 if (dec == NULL) return 0;
1177 if (io == NULL) { 1311 if (io == NULL) {
1178 dec->status_ = VP8_STATUS_INVALID_PARAM; 1312 dec->status_ = VP8_STATUS_INVALID_PARAM;
(...skipping 15 matching lines...) Expand all
1194 if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error; 1328 if (!DecodeImageStream(width, height, 1, dec, NULL)) goto Error;
1195 return 1; 1329 return 1;
1196 1330
1197 Error: 1331 Error:
1198 VP8LClear(dec); 1332 VP8LClear(dec);
1199 assert(dec->status_ != VP8_STATUS_OK); 1333 assert(dec->status_ != VP8_STATUS_OK);
1200 return 0; 1334 return 0;
1201 } 1335 }
1202 1336
1203 int VP8LDecodeImage(VP8LDecoder* const dec) { 1337 int VP8LDecodeImage(VP8LDecoder* const dec) {
1204 const size_t bytes_per_pixel = sizeof(uint32_t);
1205 VP8Io* io = NULL; 1338 VP8Io* io = NULL;
1206 WebPDecParams* params = NULL; 1339 WebPDecParams* params = NULL;
1207 1340
1208 // Sanity checks. 1341 // Sanity checks.
1209 if (dec == NULL) return 0; 1342 if (dec == NULL) return 0;
1210 1343
1211 io = dec->io_; 1344 io = dec->io_;
1212 assert(io != NULL); 1345 assert(io != NULL);
1213 params = (WebPDecParams*)io->opaque; 1346 params = (WebPDecParams*)io->opaque;
1214 assert(params != NULL); 1347 assert(params != NULL);
1215 dec->output_ = params->output; 1348 dec->output_ = params->output;
1216 assert(dec->output_ != NULL); 1349 assert(dec->output_ != NULL);
1217 1350
1218 // Initialization. 1351 // Initialization.
1219 if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) { 1352 if (!WebPIoInitFromOptions(params->options, io, MODE_BGRA)) {
1220 dec->status_ = VP8_STATUS_INVALID_PARAM; 1353 dec->status_ = VP8_STATUS_INVALID_PARAM;
1221 goto Err; 1354 goto Err;
1222 } 1355 }
1223 1356
1224 if (!AllocateInternalBuffers(dec, io->width, bytes_per_pixel)) goto Err; 1357 if (!AllocateInternalBuffers32b(dec, io->width)) goto Err;
1225 1358
1226 if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; 1359 if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err;
1227 1360
1228 // Decode. 1361 // Decode.
1229 dec->action_ = READ_DATA; 1362 dec->action_ = READ_DATA;
1230 if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_, 1363 if (!DecodeImageData(dec, dec->pixels_, dec->width_, dec->height_,
1231 ProcessRows)) { 1364 dec->height_, ProcessRows)) {
1232 goto Err; 1365 goto Err;
1233 } 1366 }
1234 1367
1235 // Cleanup. 1368 // Cleanup.
1236 params->last_y = dec->last_out_row_; 1369 params->last_y = dec->last_out_row_;
1237 VP8LClear(dec); 1370 VP8LClear(dec);
1238 return 1; 1371 return 1;
1239 1372
1240 Err: 1373 Err:
1241 VP8LClear(dec); 1374 VP8LClear(dec);
1242 assert(dec->status_ != VP8_STATUS_OK); 1375 assert(dec->status_ != VP8_STATUS_OK);
1243 return 0; 1376 return 0;
1244 } 1377 }
1245 1378
1246 //------------------------------------------------------------------------------ 1379 //------------------------------------------------------------------------------
1247 1380
1248 #if defined(__cplusplus) || defined(c_plusplus)
1249 } // extern "C"
1250 #endif
OLDNEW
« no previous file with comments | « third_party/libwebp/dec/vp8i.h ('k') | third_party/libwebp/dec/vp8li.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698