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

Unified Diff: src/images/SkDecodingImageGenerator.cpp

Issue 101973005: SkDecodingImageGenerator now uses SkStreamRewindable (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: rebased again Created 7 years 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/images/SkDecodingImageGenerator.h ('k') | src/images/SkImageDecoder.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/images/SkDecodingImageGenerator.cpp
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index 05651c78c29e2f67af1b568846f2bfd24fb9727e..2b804441417938042168d4ddce2b65232faceb30 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -9,39 +9,184 @@
#include "SkData.h"
#include "SkDiscardablePixelRef.h"
#include "SkImageDecoder.h"
+#include "SkImagePriv.h"
+#include "SkStream.h"
+
+
+namespace {
+/**
+ * Special allocator used by getPixels(). Uses preallocated memory
+ * provided.
+ */
+class TargetAllocator : public SkBitmap::Allocator {
+public:
+ TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
+ : fTarget(target)
+ , fRowBytes(rowBytes)
+ , fInfo(info) { }
+
+ virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
+ if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
+ || (bm->width() != fInfo.fWidth)
+ || (bm->height() != fInfo.fHeight)) {
+ return false;
+ }
+ bm->setConfig(bm->config(), bm->width(), bm->height(),
+ fRowBytes, bm->alphaType());
+ bm->setPixels(fTarget, ct);
+ return true;
+ }
+
+private:
+ void* fTarget;
+ size_t fRowBytes;
+ SkImageInfo fInfo;
+ typedef SkBitmap::Allocator INHERITED;
+};
+} // namespace
+////////////////////////////////////////////////////////////////////////////////
SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
- : fData(data) {
+ : fData(data)
+ , fHasInfo(false)
+ , fDoCopyTo(false) {
SkASSERT(fData != NULL);
+ fStream = SkNEW_ARGS(SkMemoryStream, (fData));
+ SkASSERT(fStream != NULL);
+ SkASSERT(fStream->unique());
fData->ref();
}
+SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream)
+ : fData(NULL)
+ , fStream(stream)
+ , fHasInfo(false)
+ , fDoCopyTo(false) {
+ SkASSERT(fStream != NULL);
+ SkASSERT(fStream->unique());
+}
+
SkDecodingImageGenerator::~SkDecodingImageGenerator() {
- fData->unref();
+ SkSafeUnref(fData);
+ fStream->unref();
}
+// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
+#ifdef SK_DEBUG
+ #define SkCheckResult(expr, value) SkASSERT((value) == (expr))
+#else
+ #define SkCheckResult(expr, value) (void)(expr)
+#endif
+
SkData* SkDecodingImageGenerator::refEncodedData() {
// This functionality is used in `gm --serialize`
- fData->ref();
- return fData;
+ if (fData != NULL) {
+ return SkSafeRef(fData);
+ }
+ // TODO(halcanary): SkStreamRewindable needs a refData() function
+ // which returns a cheap copy of the underlying data.
+ if (!fStream->rewind()) {
+ return NULL;
+ }
+ size_t length = fStream->getLength();
+ if (0 == length) {
+ return NULL;
+ }
+ void* buffer = sk_malloc_flags(length, 0);
+ SkCheckResult(fStream->read(buffer, length), length);
+ fData = SkData::NewFromMalloc(buffer, length);
+ return SkSafeRef(fData);
}
bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
- SkASSERT(info != NULL);
- return SkImageDecoder::DecodeMemoryToTarget(fData->data(),
- fData->size(),
- info, NULL);
+ // info can be NULL. If so, will update fInfo, fDoCopyTo, and fHasInfo.
+ if (fHasInfo) {
+ if (info != NULL) {
+ *info = fInfo;
+ }
+ return true;
+ }
+ SkAssertResult(fStream->rewind());
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+ if (NULL == decoder.get()) {
+ return false;
+ }
+ SkBitmap bitmap;
+ if (!decoder->decode(fStream, &bitmap,
+ SkImageDecoder::kDecodeBounds_Mode)) {
+ return false;
+ }
+ if (bitmap.config() == SkBitmap::kNo_Config) {
+ return false;
+ }
+ if (!SkBitmapToImageInfo(bitmap, &fInfo)) {
+ // We can't use bitmap.config() as is.
+ // Must be kARGB_4444_Config.
+ if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
+ // kARGB_4444_Config can copy to kARGB_8888.
+ SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)");
+ return false;
+ }
+ fDoCopyTo = true;
+ fInfo.fWidth = bitmap.width();
+ fInfo.fHeight = bitmap.height();
+ fInfo.fColorType = kPMColor_SkColorType;
+ fInfo.fAlphaType = bitmap.alphaType();
+ }
+ if (info != NULL) {
+ *info = fInfo;
+ }
+ fHasInfo = true;
+ return true;
}
bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) {
- SkASSERT(pixels != NULL);
- SkImageDecoder::Target target = {pixels, rowBytes};
- SkImageInfo tmpInfo = info;
- return SkImageDecoder::DecodeMemoryToTarget(fData->data(),
- fData->size(),
- &tmpInfo, &target);
+ if (NULL == pixels) {
+ return false;
+ }
+ if (!this->getInfo(NULL)) {
+ return false;
+ }
+ if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
+ return false; // Unsupported SkColorType.
+ }
+ SkAssertResult(fStream->rewind());
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+ if (NULL == decoder.get()) {
+ return false;
+ }
+ if (fInfo != info) {
+ // The caller has specified a different info. For now, this
+ // is an error. In the future, we will check to see if we can
+ // convert.
+ return false;
+ }
+ int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
+ if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
+ return false;
+ }
+ SkBitmap bitmap;
+ if (!bitmap.setConfig(info, rowBytes)) {
+ return false;
+ }
+
+ TargetAllocator allocator(pixels, rowBytes, info);
+ if (!fDoCopyTo) {
+ decoder->setAllocator(&allocator);
+ }
+ bool success = decoder->decode(fStream, &bitmap,
+ SkImageDecoder::kDecodePixels_Mode);
+ decoder->setAllocator(NULL);
+ if (!success) {
+ return false;
+ }
+ if (fDoCopyTo) {
+ SkBitmap bm8888;
+ bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
+ }
+ return true;
}
bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
SkDiscardableMemory::Factory* factory) {
@@ -50,3 +195,17 @@ bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
return SkDiscardablePixelRef::Install(gen, dst, factory);
}
+
+bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
+ SkBitmap* dst,
+ SkDiscardableMemory::Factory* factory) {
+ SkASSERT(stream != NULL);
+ SkASSERT(dst != NULL);
+ if ((stream == NULL) || !stream->unique()) {
+ SkSafeUnref(stream);
+ return false;
+ }
+ SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
+ return SkDiscardablePixelRef::Install(gen, dst, factory);
+}
+
« no previous file with comments | « src/images/SkDecodingImageGenerator.h ('k') | src/images/SkImageDecoder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698