OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |