aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/SkBmpCodec.cpp6
-rw-r--r--src/codec/SkBmpCodec.h6
-rw-r--r--src/codec/SkCodec.cpp46
-rw-r--r--src/codec/SkCodec_libgif.cpp5
-rw-r--r--src/codec/SkCodec_libgif.h6
-rw-r--r--src/codec/SkCodec_libico.cpp9
-rw-r--r--src/codec/SkCodec_libico.h6
-rw-r--r--src/codec/SkCodec_libpng.cpp13
-rw-r--r--src/codec/SkCodec_libpng.h2
-rw-r--r--src/codec/SkCodec_wbmp.cpp7
-rw-r--r--src/codec/SkCodec_wbmp.h2
-rw-r--r--src/codec/SkJpegCodec.cpp6
-rw-r--r--src/codec/SkJpegCodec.h7
-rw-r--r--src/codec/SkWebpCodec.cpp20
-rw-r--r--src/codec/SkWebpCodec.h4
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;