diff options
Diffstat (limited to 'src/codec/SkWebpCodec.cpp')
-rw-r--r-- | src/codec/SkWebpCodec.cpp | 97 |
1 files changed, 43 insertions, 54 deletions
diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp index e40c3f2377..cefde2d20d 100644 --- a/src/codec/SkWebpCodec.cpp +++ b/src/codec/SkWebpCodec.cpp @@ -31,7 +31,10 @@ bool SkWebpCodec::IsWebp(const void* buf, size_t bytesRead) { // Parse headers of RIFF container, and check for valid Webp (VP8) content. // NOTE: This calls peek instead of read, since onGetPixels will need these // bytes again. -static bool webp_parse_header(SkStream* stream, int* width, int* height, SkEncodedInfo* info) { +// Returns an SkWebpCodec on success; +SkCodec* SkWebpCodec::NewFromStream(SkStream* stream) { + SkAutoTDelete<SkStream> streamDeleter(stream); + unsigned char buffer[WEBP_VP8_HEADER_SIZE]; SkASSERT(WEBP_VP8_HEADER_SIZE <= SkCodec::MinBufferedBytesNeeded()); @@ -40,79 +43,65 @@ static bool webp_parse_header(SkStream* stream, int* width, int* height, SkEncod // Use read + rewind as a backup if (stream->read(buffer, WEBP_VP8_HEADER_SIZE) != WEBP_VP8_HEADER_SIZE || !stream->rewind()) - return false; + return nullptr; } WebPBitstreamFeatures features; VP8StatusCode status = WebPGetFeatures(buffer, WEBP_VP8_HEADER_SIZE, &features); if (VP8_STATUS_OK != status) { - return false; // Invalid WebP file. + return nullptr; // Invalid WebP file. } // sanity check for image size that's about to be decoded. { const int64_t size = sk_64_mul(features.width, features.height); if (!sk_64_isS32(size)) { - return false; + return nullptr; } // now check that if we are 4-bytes per pixel, we also don't overflow if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) { - return false; + return nullptr; } } - if (info) { - SkEncodedInfo::Color color; - SkEncodedInfo::Alpha alpha; - switch (features.format) { - case 0: - // This indicates a "mixed" format. We would see this for - // animated webps or for webps encoded in multiple fragments. - // I believe that this is a rare case. - // We could also guess kYUV here, but I think it makes more - // sense to guess kBGRA which is likely closer to the final - // output. Otherwise, we might end up converting - // BGRA->YUVA->BGRA. - color = SkEncodedInfo::kBGRA_Color; + SkEncodedInfo::Color color; + SkEncodedInfo::Alpha alpha; + switch (features.format) { + case 0: + // This indicates a "mixed" format. We would see this for + // animated webps or for webps encoded in multiple fragments. + // I believe that this is a rare case. + // We could also guess kYUV here, but I think it makes more + // sense to guess kBGRA which is likely closer to the final + // output. Otherwise, we might end up converting + // BGRA->YUVA->BGRA. + color = SkEncodedInfo::kBGRA_Color; + alpha = SkEncodedInfo::kUnpremul_Alpha; + break; + case 1: + // This is the lossy format (YUV). + if (SkToBool(features.has_alpha)) { + color = SkEncodedInfo::kYUVA_Color; alpha = SkEncodedInfo::kUnpremul_Alpha; - break; - case 1: - // This is the lossy format (YUV). - if (SkToBool(features.has_alpha)) { - color = SkEncodedInfo::kYUVA_Color; - alpha = SkEncodedInfo::kUnpremul_Alpha; - } else { - color = SkEncodedInfo::kYUV_Color; - alpha = SkEncodedInfo::kOpaque_Alpha; - } - break; - case 2: - // This is the lossless format (BGRA). - // FIXME: Should we check the has_alpha flag here? It looks - // like the image is encoded with an alpha channel - // regardless of whether or not the alpha flag is set. - color = SkEncodedInfo::kBGRA_Color; - alpha = SkEncodedInfo::kUnpremul_Alpha; - break; - default: - return false; - } - - *width = features.width; - *height = features.height; - *info = SkEncodedInfo::Make(color, alpha, 8); + } else { + color = SkEncodedInfo::kYUV_Color; + alpha = SkEncodedInfo::kOpaque_Alpha; + } + break; + case 2: + // This is the lossless format (BGRA). + // FIXME: Should we check the has_alpha flag here? It looks + // like the image is encoded with an alpha channel + // regardless of whether or not the alpha flag is set. + color = SkEncodedInfo::kBGRA_Color; + alpha = SkEncodedInfo::kUnpremul_Alpha; + break; + default: + return nullptr; } - return true; -} -SkCodec* SkWebpCodec::NewFromStream(SkStream* stream) { - SkAutoTDelete<SkStream> streamDeleter(stream); - int width, height; - SkEncodedInfo info; - if (webp_parse_header(stream, &width, &height, &info)) { - return new SkWebpCodec(width, height, info, streamDeleter.release()); - } - return nullptr; + SkEncodedInfo info = SkEncodedInfo::Make(color, alpha, 8); + return new SkWebpCodec(features.width, features.height, info, streamDeleter.release()); } // This version is slightly different from SkCodecPriv's version of conversion_possible. It |