diff options
Diffstat (limited to 'src/codec')
-rw-r--r-- | src/codec/SkBmpCodec.cpp | 6 | ||||
-rw-r--r-- | src/codec/SkBmpCodec.h | 6 | ||||
-rw-r--r-- | src/codec/SkCodec.cpp | 46 | ||||
-rw-r--r-- | src/codec/SkCodec_libgif.cpp | 5 | ||||
-rw-r--r-- | src/codec/SkCodec_libgif.h | 6 | ||||
-rw-r--r-- | src/codec/SkCodec_libico.cpp | 9 | ||||
-rw-r--r-- | src/codec/SkCodec_libico.h | 6 | ||||
-rw-r--r-- | src/codec/SkCodec_libpng.cpp | 13 | ||||
-rw-r--r-- | src/codec/SkCodec_libpng.h | 2 | ||||
-rw-r--r-- | src/codec/SkCodec_wbmp.cpp | 7 | ||||
-rw-r--r-- | src/codec/SkCodec_wbmp.h | 2 | ||||
-rw-r--r-- | src/codec/SkJpegCodec.cpp | 6 | ||||
-rw-r--r-- | src/codec/SkJpegCodec.h | 7 | ||||
-rw-r--r-- | src/codec/SkWebpCodec.cpp | 20 | ||||
-rw-r--r-- | src/codec/SkWebpCodec.h | 4 |
15 files changed, 69 insertions, 76 deletions
diff --git a/src/codec/SkBmpCodec.cpp b/src/codec/SkBmpCodec.cpp index 580ff25ddd..3302e4f752 100644 --- a/src/codec/SkBmpCodec.cpp +++ b/src/codec/SkBmpCodec.cpp @@ -56,12 +56,10 @@ enum BmpInputFormat { /* * Checks the start of the stream to see if the image is a bitmap */ -bool SkBmpCodec::IsBmp(SkStream* stream) { +bool SkBmpCodec::IsBmp(const void* buffer, size_t bytesRead) { // TODO: Support "IC", "PT", "CI", "CP", "BA" const char bmpSig[] = { 'B', 'M' }; - char buffer[sizeof(bmpSig)]; - return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && - !memcmp(buffer, bmpSig, sizeof(bmpSig)); + return bytesRead >= sizeof(bmpSig) && !memcmp(buffer, bmpSig, sizeof(bmpSig)); } /* diff --git a/src/codec/SkBmpCodec.h b/src/codec/SkBmpCodec.h index 30523b0838..5d77ca3fc8 100644 --- a/src/codec/SkBmpCodec.h +++ b/src/codec/SkBmpCodec.h @@ -20,11 +20,7 @@ */ class SkBmpCodec : public SkCodec { public: - - /* - * Checks the start of the stream to see if the image is a bmp - */ - static bool IsBmp(SkStream*); + static bool IsBmp(const void*, size_t); /* * Assumes IsBmp was called and returned true diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index 11eb1f9847..87a7ded7dd 100644 --- a/src/codec/SkCodec.cpp +++ b/src/codec/SkCodec.cpp @@ -20,7 +20,7 @@ #include "SkWebpCodec.h" struct DecoderProc { - bool (*IsFormat)(SkStream*); + bool (*IsFormat)(const void*, size_t); SkCodec* (*NewFromStream)(SkStream*); }; @@ -35,6 +35,10 @@ static const DecoderProc gDecoderProcs[] = { { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewFromStream } }; +size_t SkCodec::MinBufferedBytesNeeded() { + return WEBP_VP8_HEADER_SIZE; +} + SkCodec* SkCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkReader) { if (!stream) { @@ -42,23 +46,41 @@ SkCodec* SkCodec::NewFromStream(SkStream* stream, } SkAutoTDelete<SkStream> streamDeleter(stream); - + + // 14 is enough to read all of the supported types. + const size_t bytesToRead = 14; + SkASSERT(bytesToRead <= MinBufferedBytesNeeded()); + + char buffer[bytesToRead]; + size_t bytesRead = stream->peek(buffer, bytesToRead); + + // It is also possible to have a complete image less than bytesToRead bytes + // (e.g. a 1 x 1 wbmp), meaning peek() would return less than bytesToRead. + // Assume that if bytesRead < bytesToRead, but > 0, the stream is shorter + // than bytesToRead, so pass that directly to the decoder. + // It also is possible the stream uses too small a buffer for peeking, but + // we trust the caller to use a large enough buffer. + + if (0 == bytesRead) { + SkCodecPrintf("Could not peek!\n"); + // It is possible the stream does not support peeking, but does support + // rewinding. + // Attempt to read() and pass the actual amount read to the decoder. + bytesRead = stream->read(buffer, bytesToRead); + if (!stream->rewind()) { + SkCodecPrintf("Could not rewind!\n"); + return nullptr; + } + } + SkAutoTDelete<SkCodec> codec(nullptr); // PNG is special, since we want to be able to supply an SkPngChunkReader. // But this code follows the same pattern as the loop. - const bool isPng = SkPngCodec::IsPng(stream); - if (!stream->rewind()) { - return NULL; - } - if (isPng) { + if (SkPngCodec::IsPng(buffer, bytesRead)) { codec.reset(SkPngCodec::NewFromStream(streamDeleter.detach(), chunkReader)); } else { for (DecoderProc proc : gDecoderProcs) { - const bool correctFormat = proc.IsFormat(stream); - if (!stream->rewind()) { - return nullptr; - } - if (correctFormat) { + if (proc.IsFormat(buffer, bytesRead)) { codec.reset(proc.NewFromStream(streamDeleter.detach())); break; } diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp index e6a40164f3..40ed94d0bb 100644 --- a/src/codec/SkCodec_libgif.cpp +++ b/src/codec/SkCodec_libgif.cpp @@ -16,9 +16,8 @@ /* * Checks the start of the stream to see if the image is a gif */ -bool SkGifCodec::IsGif(SkStream* stream) { - char buf[GIF_STAMP_LEN]; - if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { +bool SkGifCodec::IsGif(const void* buf, size_t bytesRead) { + if (bytesRead >= GIF_STAMP_LEN) { if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 || memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 || memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) diff --git a/src/codec/SkCodec_libgif.h b/src/codec/SkCodec_libgif.h index 200f176e32..ba48989cbb 100644 --- a/src/codec/SkCodec_libgif.h +++ b/src/codec/SkCodec_libgif.h @@ -19,11 +19,7 @@ */ class SkGifCodec : public SkCodec { public: - - /* - * Checks the start of the stream to see if the image is a gif - */ - static bool IsGif(SkStream*); + static bool IsGif(const void*, size_t); /* * Assumes IsGif was called and returned true diff --git a/src/codec/SkCodec_libico.cpp b/src/codec/SkCodec_libico.cpp index e1314d7121..660576a26a 100644 --- a/src/codec/SkCodec_libico.cpp +++ b/src/codec/SkCodec_libico.cpp @@ -55,11 +55,10 @@ static SkImageInfo fix_embedded_alpha(const SkImageInfo& dstInfo, SkAlphaType em /* * Checks the start of the stream to see if the image is an Ico or Cur */ -bool SkIcoCodec::IsIco(SkStream* stream) { +bool SkIcoCodec::IsIco(const void* buffer, size_t bytesRead) { const char icoSig[] = { '\x00', '\x00', '\x01', '\x00' }; const char curSig[] = { '\x00', '\x00', '\x02', '\x00' }; - char buffer[sizeof(icoSig)]; - return stream->read(buffer, sizeof(icoSig)) == sizeof(icoSig) && + return bytesRead >= sizeof(icoSig) && (!memcmp(buffer, icoSig, sizeof(icoSig)) || !memcmp(buffer, curSig, sizeof(curSig))); } @@ -176,10 +175,8 @@ SkCodec* SkIcoCodec::NewFromStream(SkStream* stream) { bytesRead += size; // Check if the embedded codec is bmp or png and create the codec - const bool isPng = SkPngCodec::IsPng(embeddedStream); - SkAssertResult(embeddedStream->rewind()); SkCodec* codec = nullptr; - if (isPng) { + if (SkPngCodec::IsPng((const char*) data->bytes(), data->size())) { codec = SkPngCodec::NewFromStream(embeddedStream.detach()); } else { codec = SkBmpCodec::NewFromIco(embeddedStream.detach()); diff --git a/src/codec/SkCodec_libico.h b/src/codec/SkCodec_libico.h index a1d99b884d..9a3f248af5 100644 --- a/src/codec/SkCodec_libico.h +++ b/src/codec/SkCodec_libico.h @@ -15,11 +15,7 @@ */ class SkIcoCodec : public SkCodec { public: - - /* - * Checks the start of the stream to see if the image is a Ico or Cur - */ - static bool IsIco(SkStream*); + static bool IsIco(const void*, size_t); /* * Assumes IsIco was called and returned true diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp index a611705c3b..744bca41fa 100644 --- a/src/codec/SkCodec_libpng.cpp +++ b/src/codec/SkCodec_libpng.cpp @@ -206,17 +206,8 @@ bool SkPngCodec::decodePalette(bool premultiply, int* ctableCount) { // Creation /////////////////////////////////////////////////////////////////////////////// -#define PNG_BYTES_TO_CHECK 4 - -bool SkPngCodec::IsPng(SkStream* stream) { - char buf[PNG_BYTES_TO_CHECK]; - if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) { - return false; - } - if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { - return false; - } - return true; +bool SkPngCodec::IsPng(const char* buf, size_t bytesRead) { + return !png_sig_cmp((png_bytep) buf, (png_size_t)0, bytesRead); } // Reads the header and initializes the output fields, if not NULL. diff --git a/src/codec/SkCodec_libpng.h b/src/codec/SkCodec_libpng.h index c2a5f4a707..78f1c5de53 100644 --- a/src/codec/SkCodec_libpng.h +++ b/src/codec/SkCodec_libpng.h @@ -19,7 +19,7 @@ class SkStream; class SkPngCodec : public SkCodec { public: - static bool IsPng(SkStream*); + static bool IsPng(const char*, size_t); // Assume IsPng was called and returned true. static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL); diff --git a/src/codec/SkCodec_wbmp.cpp b/src/codec/SkCodec_wbmp.cpp index 8f8763fb90..d734ad3a62 100644 --- a/src/codec/SkCodec_wbmp.cpp +++ b/src/codec/SkCodec_wbmp.cpp @@ -9,6 +9,7 @@ #include "SkCodecPriv.h" #include "SkColorPriv.h" #include "SkColorTable.h" +#include "SkData.h" #include "SkStream.h" #include "SkCodec_wbmp.h" @@ -151,8 +152,10 @@ SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, return kSuccess; } -bool SkWbmpCodec::IsWbmp(SkStream* stream) { - return read_header(stream, nullptr); +bool SkWbmpCodec::IsWbmp(const void* buffer, size_t bytesRead) { + SkAutoTUnref<SkData> data(SkData::NewWithoutCopy(buffer, bytesRead)); + SkMemoryStream stream(data); + return read_header(&stream, nullptr); } SkCodec* SkWbmpCodec::NewFromStream(SkStream* stream) { diff --git a/src/codec/SkCodec_wbmp.h b/src/codec/SkCodec_wbmp.h index f54dd0f166..fb062c94d5 100644 --- a/src/codec/SkCodec_wbmp.h +++ b/src/codec/SkCodec_wbmp.h @@ -13,7 +13,7 @@ class SkWbmpCodec final : public SkCodec { public: - static bool IsWbmp(SkStream*); + static bool IsWbmp(const void*, size_t); /* * Assumes IsWbmp was called and returned true diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp index 6e2fc84ec8..6ea13b7639 100644 --- a/src/codec/SkJpegCodec.cpp +++ b/src/codec/SkJpegCodec.cpp @@ -23,11 +23,9 @@ extern "C" { #include "jpeglib.h" } -bool SkJpegCodec::IsJpeg(SkStream* stream) { +bool SkJpegCodec::IsJpeg(const void* buffer, size_t bytesRead) { static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF }; - char buffer[sizeof(jpegSig)]; - return stream->read(buffer, sizeof(jpegSig)) == sizeof(jpegSig) && - !memcmp(buffer, jpegSig, sizeof(jpegSig)); + return bytesRead >= 3 && !memcmp(buffer, jpegSig, sizeof(jpegSig)); } bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, diff --git a/src/codec/SkJpegCodec.h b/src/codec/SkJpegCodec.h index 687cf4b4b8..ed94b613f9 100644 --- a/src/codec/SkJpegCodec.h +++ b/src/codec/SkJpegCodec.h @@ -25,12 +25,7 @@ extern "C" { */ class SkJpegCodec : public SkCodec { public: - - /* - * Checks the start of the stream to see if the image is a jpeg - * Does not take ownership of the stream - */ - static bool IsJpeg(SkStream*); + static bool IsJpeg(const void*, size_t); /* * Assumes IsJpeg was called and returned true diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp index 3c61b93762..2137877f1e 100644 --- a/src/codec/SkWebpCodec.cpp +++ b/src/codec/SkWebpCodec.cpp @@ -20,26 +20,26 @@ #include "webp/decode.h" #include "webp/encode.h" -bool SkWebpCodec::IsWebp(SkStream* stream) { +bool SkWebpCodec::IsWebp(const void* buf, size_t bytesRead) { // WEBP starts with the following: // RIFFXXXXWEBPVP // Where XXXX is unspecified. - const char LENGTH = 14; - char bytes[LENGTH]; - if (stream->read(&bytes, LENGTH) != LENGTH) { - return false; - } - return !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "WEBPVP", 6); + const char* bytes = static_cast<const char*>(buf); + return bytesRead >= 14 && !memcmp(bytes, "RIFF", 4) && !memcmp(&bytes[8], "WEBPVP", 6); } -static const size_t WEBP_VP8_HEADER_SIZE = 30; - // 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, SkImageInfo* info) { unsigned char buffer[WEBP_VP8_HEADER_SIZE]; - if (!stream->peek(buffer, WEBP_VP8_HEADER_SIZE)) { + SkASSERT(WEBP_VP8_HEADER_SIZE <= SkCodec::MinBufferedBytesNeeded()); + + const size_t bytesPeeked = stream->peek(buffer, WEBP_VP8_HEADER_SIZE); + if (bytesPeeked != WEBP_VP8_HEADER_SIZE) { + // Use read + rewind as a backup + if (stream->read(buffer, WEBP_VP8_HEADER_SIZE) != WEBP_VP8_HEADER_SIZE + || !stream->rewind()) return false; } diff --git a/src/codec/SkWebpCodec.h b/src/codec/SkWebpCodec.h index 97b3920ce9..5c0f0286f7 100644 --- a/src/codec/SkWebpCodec.h +++ b/src/codec/SkWebpCodec.h @@ -15,11 +15,13 @@ class SkStream; +static const size_t WEBP_VP8_HEADER_SIZE = 30; + class SkWebpCodec final : public SkCodec { public: // Assumes IsWebp was called and returned true. static SkCodec* NewFromStream(SkStream*); - static bool IsWebp(SkStream*); + static bool IsWebp(const void*, size_t); protected: Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*, int*) override; |