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

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

Issue 1546003002: libwebp: update to 0.5.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase around clang-cl fix Created 4 years, 12 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
OLDNEW
1 // Copyright 2010 Google Inc. All Rights Reserved. 1 // Copyright 2010 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 decoding functions for WEBP images. 10 // Main decoding functions for WEBP images.
11 // 11 //
12 // Author: Skal (pascal.massimino@gmail.com) 12 // Author: Skal (pascal.massimino@gmail.com)
13 13
14 #include <stdlib.h> 14 #include <stdlib.h>
15 15
16 #include "./vp8i.h" 16 #include "./vp8i.h"
17 #include "./vp8li.h" 17 #include "./vp8li.h"
18 #include "./webpi.h" 18 #include "./webpi.h"
19 #include "../utils/utils.h"
19 #include "../webp/mux_types.h" // ALPHA_FLAG 20 #include "../webp/mux_types.h" // ALPHA_FLAG
20 21
21 //------------------------------------------------------------------------------ 22 //------------------------------------------------------------------------------
22 // RIFF layout is: 23 // RIFF layout is:
23 // Offset tag 24 // Offset tag
24 // 0...3 "RIFF" 4-byte tag 25 // 0...3 "RIFF" 4-byte tag
25 // 4...7 size of image data (including metadata) starting at offset 8 26 // 4...7 size of image data (including metadata) starting at offset 8
26 // 8...11 "WEBP" our form-type signature 27 // 8...11 "WEBP" our form-type signature
27 // The RIFF container (12 bytes) is followed by appropriate chunks: 28 // The RIFF container (12 bytes) is followed by appropriate chunks:
28 // 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format 29 // 12..15 "VP8 ": 4-bytes tags, signaling the use of VP8 video format
29 // 16..19 size of the raw VP8 image data, starting at offset 20 30 // 16..19 size of the raw VP8 image data, starting at offset 20
30 // 20.... the VP8 bytes 31 // 20.... the VP8 bytes
31 // Or, 32 // Or,
32 // 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format 33 // 12..15 "VP8L": 4-bytes tags, signaling the use of VP8L lossless format
33 // 16..19 size of the raw VP8L image data, starting at offset 20 34 // 16..19 size of the raw VP8L image data, starting at offset 20
34 // 20.... the VP8L bytes 35 // 20.... the VP8L bytes
35 // Or, 36 // Or,
36 // 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk. 37 // 12..15 "VP8X": 4-bytes tags, describing the extended-VP8 chunk.
37 // 16..19 size of the VP8X chunk starting at offset 20. 38 // 16..19 size of the VP8X chunk starting at offset 20.
38 // 20..23 VP8X flags bit-map corresponding to the chunk-types present. 39 // 20..23 VP8X flags bit-map corresponding to the chunk-types present.
39 // 24..26 Width of the Canvas Image. 40 // 24..26 Width of the Canvas Image.
40 // 27..29 Height of the Canvas Image. 41 // 27..29 Height of the Canvas Image.
41 // There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8, 42 // There can be extra chunks after the "VP8X" chunk (ICCP, FRGM, ANMF, VP8,
42 // VP8L, XMP, EXIF ...) 43 // VP8L, XMP, EXIF ...)
43 // All sizes are in little-endian order. 44 // All sizes are in little-endian order.
44 // Note: chunk data size must be padded to multiple of 2 when written. 45 // Note: chunk data size must be padded to multiple of 2 when written.
45 46
46 static WEBP_INLINE uint32_t get_le24(const uint8_t* const data) {
47 return data[0] | (data[1] << 8) | (data[2] << 16);
48 }
49
50 static WEBP_INLINE uint32_t get_le32(const uint8_t* const data) {
51 return (uint32_t)get_le24(data) | (data[3] << 24);
52 }
53
54 // Validates the RIFF container (if detected) and skips over it. 47 // Validates the RIFF container (if detected) and skips over it.
55 // If a RIFF container is detected, returns: 48 // If a RIFF container is detected, returns:
56 // VP8_STATUS_BITSTREAM_ERROR for invalid header, 49 // VP8_STATUS_BITSTREAM_ERROR for invalid header,
57 // VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true, 50 // VP8_STATUS_NOT_ENOUGH_DATA for truncated data if have_all_data is true,
58 // and VP8_STATUS_OK otherwise. 51 // and VP8_STATUS_OK otherwise.
59 // In case there are not enough bytes (partial RIFF container), return 0 for 52 // In case there are not enough bytes (partial RIFF container), return 0 for
60 // *riff_size. Else return the RIFF size extracted from the header. 53 // *riff_size. Else return the RIFF size extracted from the header.
61 static VP8StatusCode ParseRIFF(const uint8_t** const data, 54 static VP8StatusCode ParseRIFF(const uint8_t** const data,
62 size_t* const data_size, int have_all_data, 55 size_t* const data_size, int have_all_data,
63 size_t* const riff_size) { 56 size_t* const riff_size) {
64 assert(data != NULL); 57 assert(data != NULL);
65 assert(data_size != NULL); 58 assert(data_size != NULL);
66 assert(riff_size != NULL); 59 assert(riff_size != NULL);
67 60
68 *riff_size = 0; // Default: no RIFF present. 61 *riff_size = 0; // Default: no RIFF present.
69 if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { 62 if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) {
70 if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { 63 if (memcmp(*data + 8, "WEBP", TAG_SIZE)) {
71 return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. 64 return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature.
72 } else { 65 } else {
73 const uint32_t size = get_le32(*data + TAG_SIZE); 66 const uint32_t size = GetLE32(*data + TAG_SIZE);
74 // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). 67 // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn").
75 if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { 68 if (size < TAG_SIZE + CHUNK_HEADER_SIZE) {
76 return VP8_STATUS_BITSTREAM_ERROR; 69 return VP8_STATUS_BITSTREAM_ERROR;
77 } 70 }
78 if (size > MAX_CHUNK_PAYLOAD) { 71 if (size > MAX_CHUNK_PAYLOAD) {
79 return VP8_STATUS_BITSTREAM_ERROR; 72 return VP8_STATUS_BITSTREAM_ERROR;
80 } 73 }
81 if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { 74 if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) {
82 return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. 75 return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream.
83 } 76 }
(...skipping 25 matching lines...) Expand all
109 102
110 *found_vp8x = 0; 103 *found_vp8x = 0;
111 104
112 if (*data_size < CHUNK_HEADER_SIZE) { 105 if (*data_size < CHUNK_HEADER_SIZE) {
113 return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. 106 return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
114 } 107 }
115 108
116 if (!memcmp(*data, "VP8X", TAG_SIZE)) { 109 if (!memcmp(*data, "VP8X", TAG_SIZE)) {
117 int width, height; 110 int width, height;
118 uint32_t flags; 111 uint32_t flags;
119 const uint32_t chunk_size = get_le32(*data + TAG_SIZE); 112 const uint32_t chunk_size = GetLE32(*data + TAG_SIZE);
120 if (chunk_size != VP8X_CHUNK_SIZE) { 113 if (chunk_size != VP8X_CHUNK_SIZE) {
121 return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. 114 return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size.
122 } 115 }
123 116
124 // Verify if enough data is available to validate the VP8X chunk. 117 // Verify if enough data is available to validate the VP8X chunk.
125 if (*data_size < vp8x_size) { 118 if (*data_size < vp8x_size) {
126 return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. 119 return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
127 } 120 }
128 flags = get_le32(*data + 8); 121 flags = GetLE32(*data + 8);
129 width = 1 + get_le24(*data + 12); 122 width = 1 + GetLE24(*data + 12);
130 height = 1 + get_le24(*data + 15); 123 height = 1 + GetLE24(*data + 15);
131 if (width * (uint64_t)height >= MAX_IMAGE_AREA) { 124 if (width * (uint64_t)height >= MAX_IMAGE_AREA) {
132 return VP8_STATUS_BITSTREAM_ERROR; // image is too large 125 return VP8_STATUS_BITSTREAM_ERROR; // image is too large
133 } 126 }
134 127
135 if (flags_ptr != NULL) *flags_ptr = flags; 128 if (flags_ptr != NULL) *flags_ptr = flags;
136 if (width_ptr != NULL) *width_ptr = width; 129 if (width_ptr != NULL) *width_ptr = width;
137 if (height_ptr != NULL) *height_ptr = height; 130 if (height_ptr != NULL) *height_ptr = height;
138 // Skip over VP8X header bytes. 131 // Skip over VP8X header bytes.
139 *data += vp8x_size; 132 *data += vp8x_size;
140 *data_size -= vp8x_size; 133 *data_size -= vp8x_size;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 uint32_t chunk_size; 167 uint32_t chunk_size;
175 uint32_t disk_chunk_size; // chunk_size with padding 168 uint32_t disk_chunk_size; // chunk_size with padding
176 169
177 *data = buf; 170 *data = buf;
178 *data_size = buf_size; 171 *data_size = buf_size;
179 172
180 if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. 173 if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data.
181 return VP8_STATUS_NOT_ENOUGH_DATA; 174 return VP8_STATUS_NOT_ENOUGH_DATA;
182 } 175 }
183 176
184 chunk_size = get_le32(buf + TAG_SIZE); 177 chunk_size = GetLE32(buf + TAG_SIZE);
185 if (chunk_size > MAX_CHUNK_PAYLOAD) { 178 if (chunk_size > MAX_CHUNK_PAYLOAD) {
186 return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. 179 return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
187 } 180 }
188 // For odd-sized chunk-payload, there's one byte padding at the end. 181 // For odd-sized chunk-payload, there's one byte padding at the end.
189 disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; 182 disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1;
190 total_size += disk_chunk_size; 183 total_size += disk_chunk_size;
191 184
192 // Check that total bytes skipped so far does not exceed riff_size. 185 // Check that total bytes skipped so far does not exceed riff_size.
193 if (riff_size > 0 && (total_size > riff_size)) { 186 if (riff_size > 0 && (total_size > riff_size)) {
194 return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. 187 return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 assert(data_size != NULL); 233 assert(data_size != NULL);
241 assert(chunk_size != NULL); 234 assert(chunk_size != NULL);
242 assert(is_lossless != NULL); 235 assert(is_lossless != NULL);
243 236
244 if (*data_size < CHUNK_HEADER_SIZE) { 237 if (*data_size < CHUNK_HEADER_SIZE) {
245 return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. 238 return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data.
246 } 239 }
247 240
248 if (is_vp8 || is_vp8l) { 241 if (is_vp8 || is_vp8l) {
249 // Bitstream contains VP8/VP8L header. 242 // Bitstream contains VP8/VP8L header.
250 const uint32_t size = get_le32(data + TAG_SIZE); 243 const uint32_t size = GetLE32(data + TAG_SIZE);
251 if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { 244 if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) {
252 return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. 245 return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information.
253 } 246 }
254 if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { 247 if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) {
255 return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. 248 return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream.
256 } 249 }
257 // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. 250 // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header.
258 *chunk_size = size; 251 *chunk_size = size;
259 *data_ptr += CHUNK_HEADER_SIZE; 252 *data_ptr += CHUNK_HEADER_SIZE;
260 *data_size -= CHUNK_HEADER_SIZE; 253 *data_size -= CHUNK_HEADER_SIZE;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 } 495 }
503 } 496 }
504 } 497 }
505 VP8LDelete(dec); 498 VP8LDelete(dec);
506 } 499 }
507 500
508 if (status != VP8_STATUS_OK) { 501 if (status != VP8_STATUS_OK) {
509 WebPFreeDecBuffer(params->output); 502 WebPFreeDecBuffer(params->output);
510 } 503 }
511 504
512 #if WEBP_DECODER_ABI_VERSION > 0x0203
513 if (params->options != NULL && params->options->flip) { 505 if (params->options != NULL && params->options->flip) {
514 status = WebPFlipBuffer(params->output); 506 status = WebPFlipBuffer(params->output);
515 } 507 }
516 #endif
517 return status; 508 return status;
518 } 509 }
519 510
520 // Helpers 511 // Helpers
521 static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, 512 static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace,
522 const uint8_t* const data, 513 const uint8_t* const data,
523 size_t data_size, 514 size_t data_size,
524 uint8_t* const rgba, 515 uint8_t* const rgba,
525 int stride, size_t size) { 516 int stride, size_t size) {
526 WebPDecParams params; 517 WebPDecParams params;
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 io->crop_left = x; 780 io->crop_left = x;
790 io->crop_top = y; 781 io->crop_top = y;
791 io->crop_right = x + w; 782 io->crop_right = x + w;
792 io->crop_bottom = y + h; 783 io->crop_bottom = y + h;
793 io->mb_w = w; 784 io->mb_w = w;
794 io->mb_h = h; 785 io->mb_h = h;
795 786
796 // Scaling 787 // Scaling
797 io->use_scaling = (options != NULL) && (options->use_scaling > 0); 788 io->use_scaling = (options != NULL) && (options->use_scaling > 0);
798 if (io->use_scaling) { 789 if (io->use_scaling) {
799 if (options->scaled_width <= 0 || options->scaled_height <= 0) { 790 int scaled_width = options->scaled_width;
791 int scaled_height = options->scaled_height;
792 if (!WebPRescalerGetScaledDimensions(w, h, &scaled_width, &scaled_height)) {
800 return 0; 793 return 0;
801 } 794 }
802 io->scaled_width = options->scaled_width; 795 io->scaled_width = scaled_width;
803 io->scaled_height = options->scaled_height; 796 io->scaled_height = scaled_height;
804 } 797 }
805 798
806 // Filter 799 // Filter
807 io->bypass_filtering = options && options->bypass_filtering; 800 io->bypass_filtering = options && options->bypass_filtering;
808 801
809 // Fancy upsampler 802 // Fancy upsampler
810 #ifdef FANCY_UPSAMPLING 803 #ifdef FANCY_UPSAMPLING
811 io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling); 804 io->fancy_upsampling = (options == NULL) || (!options->no_fancy_upsampling);
812 #endif 805 #endif
813 806
814 if (io->use_scaling) { 807 if (io->use_scaling) {
815 // disable filter (only for large downscaling ratio). 808 // disable filter (only for large downscaling ratio).
816 io->bypass_filtering = (io->scaled_width < W * 3 / 4) && 809 io->bypass_filtering = (io->scaled_width < W * 3 / 4) &&
817 (io->scaled_height < H * 3 / 4); 810 (io->scaled_height < H * 3 / 4);
818 io->fancy_upsampling = 0; 811 io->fancy_upsampling = 0;
819 } 812 }
820 return 1; 813 return 1;
821 } 814 }
822 815
823 //------------------------------------------------------------------------------ 816 //------------------------------------------------------------------------------
824 817
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698