OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCodecPriv.h" | 8 #include "SkCodecPriv.h" |
9 #include "SkWebpCodec.h" | 9 #include "SkWebpCodec.h" |
10 #include "SkTemplates.h" | 10 #include "SkTemplates.h" |
11 | 11 |
12 // A WebP decoder on top of (subset of) libwebp | 12 // A WebP decoder on top of (subset of) libwebp |
13 // For more information on WebP image format, and libwebp library, see: | 13 // For more information on WebP image format, and libwebp library, see: |
14 // https://code.google.com/speed/webp/ | 14 // https://code.google.com/speed/webp/ |
15 // http://www.webmproject.org/code/#libwebp-webp-image-library | 15 // http://www.webmproject.org/code/#libwebp-webp-image-library |
16 // https://chromium.googlesource.com/webm/libwebp | 16 // https://chromium.googlesource.com/webm/libwebp |
17 | 17 |
18 // If moving libwebp out of skia source tree, path for webp headers must be | 18 // If moving libwebp out of skia source tree, path for webp headers must be |
19 // updated accordingly. Here, we enforce using local copy in webp sub-directory. | 19 // updated accordingly. Here, we enforce using local copy in webp sub-directory. |
20 #include "webp/decode.h" | 20 #include "webp/decode.h" |
21 #include "webp/encode.h" | 21 #include "webp/encode.h" |
22 | 22 |
23 bool SkWebpCodec::IsWebp(SkStream* stream) { | 23 bool SkWebpCodec::IsWebp(const char* bytes, size_t bytesRead) { |
24 // WEBP starts with the following: | 24 // WEBP starts with the following: |
25 // RIFFXXXXWEBPVP | 25 // RIFFXXXXWEBPVP |
26 // Where XXXX is unspecified. | 26 // Where XXXX is unspecified. |
27 const char LENGTH = 14; | 27 return bytesRead >= 14 && !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "W
EBPVP", 6); |
28 char bytes[LENGTH]; | |
29 if (stream->read(&bytes, LENGTH) != LENGTH) { | |
30 return false; | |
31 } | |
32 return !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "WEBPVP", 6); | |
33 } | 28 } |
34 | 29 |
35 static const size_t WEBP_VP8_HEADER_SIZE = 30; | |
36 | |
37 // Parse headers of RIFF container, and check for valid Webp (VP8) content. | 30 // Parse headers of RIFF container, and check for valid Webp (VP8) content. |
38 // NOTE: This calls peek instead of read, since onGetPixels will need these | 31 // NOTE: This calls peek instead of read, since onGetPixels will need these |
39 // bytes again. | 32 // bytes again. |
40 static bool webp_parse_header(SkStream* stream, SkImageInfo* info) { | 33 static bool webp_parse_header(SkStream* stream, SkImageInfo* info) { |
41 unsigned char buffer[WEBP_VP8_HEADER_SIZE]; | 34 unsigned char buffer[WEBP_VP8_HEADER_SIZE]; |
42 if (!stream->peek(buffer, WEBP_VP8_HEADER_SIZE)) { | 35 SkASSERT(WEBP_VP8_HEADER_SIZE <= SkCodec::BufferedBytesNeeded()); |
| 36 |
| 37 const size_t bytesPeeked = stream->peek(buffer, WEBP_VP8_HEADER_SIZE); |
| 38 if (bytesPeeked != WEBP_VP8_HEADER_SIZE) { |
| 39 // Use read + rewind as a backup |
| 40 if (stream->read(buffer, WEBP_VP8_HEADER_SIZE) != WEBP_VP8_HEADER_SIZE |
| 41 || !stream->rewind()) |
43 return false; | 42 return false; |
44 } | 43 } |
45 | 44 |
46 WebPBitstreamFeatures features; | 45 WebPBitstreamFeatures features; |
47 VP8StatusCode status = WebPGetFeatures(buffer, WEBP_VP8_HEADER_SIZE, &featur
es); | 46 VP8StatusCode status = WebPGetFeatures(buffer, WEBP_VP8_HEADER_SIZE, &featur
es); |
48 if (VP8_STATUS_OK != status) { | 47 if (VP8_STATUS_OK != status) { |
49 return false; // Invalid WebP file. | 48 return false; // Invalid WebP file. |
50 } | 49 } |
51 | 50 |
52 // sanity check for image size that's about to be decoded. | 51 // sanity check for image size that's about to be decoded. |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 // Break out of the switch statement. Continue the loop. | 245 // Break out of the switch statement. Continue the loop. |
247 break; | 246 break; |
248 default: | 247 default: |
249 return kInvalidInput; | 248 return kInvalidInput; |
250 } | 249 } |
251 } | 250 } |
252 } | 251 } |
253 | 252 |
254 SkWebpCodec::SkWebpCodec(const SkImageInfo& info, SkStream* stream) | 253 SkWebpCodec::SkWebpCodec(const SkImageInfo& info, SkStream* stream) |
255 : INHERITED(info, stream) {} | 254 : INHERITED(info, stream) {} |
OLD | NEW |