Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Unified Diff: src/codec/SkCodec_libpng.cpp

Issue 1048423003: Make SkPngCodec support rewinding properly. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | tests/CodexTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkCodec_libpng.cpp
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index 9330ac5aee3974fd8044b6fd22333997be444462..18574f70be705ae15a2ae959006d6399b86b2cea 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -201,19 +201,25 @@ bool SkPngCodec::IsPng(SkStream* stream) {
return true;
}
-SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
+// Reads the header, and initializes the passed in fields, if not NULL (except
+// stream, which is passed to the read function).
+// Returns true on success, in which case the caller is responsible for calling
+// png_destroy_read_struct. If it returns false, the passed in fields (except
+// stream) are unchanged.
+static bool read_header(SkStream* stream, png_structp* png_ptrp,
+ png_infop* info_ptrp, SkImageInfo* imageInfo) {
// The image is known to be a PNG. Decode enough to know the SkImageInfo.
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
sk_error_fn, sk_warning_fn);
if (!png_ptr) {
- return NULL;
+ return false;
}
AutoCleanPng autoClean(png_ptr);
png_infop info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
- return NULL;
+ return false;
}
autoClean.setInfoPtr(info_ptr);
@@ -221,7 +227,7 @@ SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
// FIXME: Could we use the return value of setjmp to specify the type of
// error?
if (setjmp(png_jmpbuf(png_ptr))) {
- return NULL;
+ return false;
}
png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn);
@@ -244,7 +250,7 @@ SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
int64_t size = sk_64_mul(origWidth, origHeight);
// now check that if we are 4-bytes per pixel, we also don't overflow
if (size < 0 || size > (0x7FFFFFFF >> 2)) {
- return NULL;
+ return false;
}
}
@@ -325,11 +331,28 @@ SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
// FIXME: Also need to check for sRGB (skbug.com/3471).
- SkImageInfo info = SkImageInfo::Make(origWidth, origHeight, skColorType,
- skAlphaType);
- SkCodec* codec = SkNEW_ARGS(SkPngCodec, (info, stream, png_ptr, info_ptr));
+ if (imageInfo) {
+ *imageInfo = SkImageInfo::Make(origWidth, origHeight, skColorType,
+ skAlphaType);
+ }
autoClean.detach();
- return codec;
+ if (png_ptrp) {
+ *png_ptrp = png_ptr;
+ }
+ if (info_ptrp) {
+ *info_ptrp = info_ptr;
+ }
+ return true;
+}
+
+SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
+ png_structp png_ptr;
+ png_infop info_ptr;
+ SkImageInfo imageInfo;
+ if (read_header(stream, &png_ptr, &info_ptr, &imageInfo)) {
+ return SkNEW_ARGS(SkPngCodec, (imageInfo, stream, png_ptr, info_ptr));
+ }
+ return NULL;
}
#define INVALID_NUMBER_PASSES -1
@@ -344,7 +367,17 @@ SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream,
{}
SkPngCodec::~SkPngCodec() {
- png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
+ this->destroyReadStruct();
+}
+
+void SkPngCodec::destroyReadStruct() {
+ if (fPng_ptr) {
+ // We will never have a NULL fInfo_ptr with a non-NULL fPng_ptr
+ SkASSERT(fInfo_ptr);
+ png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
+ fPng_ptr = NULL;
+ fInfo_ptr = NULL;
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -424,8 +457,20 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
if (rewindState == kCouldNotRewind_RewindState) {
return kCouldNotRewind;
} else if (rewindState == kRewound_RewindState) {
- // TODO(scroggo): handle rewinds
- return kCouldNotRewind;
+ // This sets fPng_ptr and fInfo_ptr to NULL. If read_header succeeds,
+ // they will be repopulated, and if it fails, they will remain NULL.
+ // Any future accesses to fPng_ptr and fInfo_ptr will come through this
+ // function which will rewind and again attempt to reinitialize them.
+ this->destroyReadStruct();
+ png_structp png_ptr;
+ png_infop info_ptr;
+ if (read_header(this->stream(), &png_ptr, &info_ptr, NULL)) {
+ fPng_ptr = png_ptr;
+ fInfo_ptr = info_ptr;
+ } else {
+ return kCouldNotRewind;
+ }
+
}
if (requestedInfo.dimensions() != this->getInfo().dimensions()) {
return kInvalidScale;
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | tests/CodexTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698