aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar halcanary@google.com <halcanary@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-02 13:15:13 +0000
committerGravatar halcanary@google.com <halcanary@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-02 13:15:13 +0000
commit3d50ea1b87132833d7eab38964f40315ba553205 (patch)
tree3776e19965640462d197f926532c872ecb658cdc /src
parentf8affa2e5cf9d4e0c8b020ba322f03355050794e (diff)
Add Options to SkDecodingImageGenerator, simplify API.
Motivation: We want to remove redundant classes from Skia. To that end we want to remove SkImageRef and its subclasses and replace their uses with SkDiscardablePixelRef + SkDecodingImageGenerator. Since Android uses SkImageRef, we need to make sure that SkDecodingImageGenerator allows all of the settings that Android exposes in BitmapFactory.Options. To that end, we have created an Options struct for the SkDecodingImageGenerator which lets the client of the generator set sample size, dithering, and bitmap config. We have made the SkDecodingImageGenerator constructor private and replaced the SkDecodingImageGenerator::Install functions with a SkDecodingImageGenerator::Create functions (one for SkData and one for SkStream) which now take a SkDecodingImageGenerator::Options struct. Also added a ImageDecoderOptions test which loops through a list of sets of options and tries them on a set of 5 small encoded images. Also updated several users of SkDecodingImageGenerator::Install to follow new call signature - gm/factory.cpp, LazyDecodeBitmap.cpp, and PictureTest.cpp, CachedDecodingPixelRefTest.cpp. We also added a new ImprovedBitmapFactory Test which simulates the exact function that Android will need to modify to use this, installPixelRef() in BitmapFactory. R=reed@google.com, scroggo@google.com Committed: https://code.google.com/p/skia/source/detail?r=12744 Review URL: https://codereview.chromium.org/93703004 git-svn-id: http://skia.googlecode.com/svn/trunk@12855 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/image/SkImagePriv.cpp37
-rw-r--r--src/image/SkImagePriv.h2
-rw-r--r--src/images/SkDecodingImageGenerator.cpp307
-rw-r--r--src/images/SkDecodingImageGenerator.h181
-rw-r--r--src/lazy/SkCachingPixelRef.cpp1
-rw-r--r--src/lazy/SkDiscardablePixelRef.cpp15
-rw-r--r--src/lazy/SkDiscardablePixelRef.h9
7 files changed, 347 insertions, 205 deletions
diff --git a/src/image/SkImagePriv.cpp b/src/image/SkImagePriv.cpp
index 976a5b3333..43cc44b2fa 100644
--- a/src/image/SkImagePriv.cpp
+++ b/src/image/SkImagePriv.cpp
@@ -9,8 +9,8 @@
#include "SkCanvas.h"
#include "SkPicture.h"
-SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
- switch (info.fColorType) {
+SkBitmap::Config SkColorTypeToBitmapConfig(SkColorType colorType) {
+ switch (colorType) {
case kAlpha_8_SkColorType:
return SkBitmap::kA8_Config;
@@ -33,6 +33,39 @@ SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
return SkBitmap::kNo_Config;
}
+SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
+ return SkColorTypeToBitmapConfig(info.fColorType);
+}
+
+bool SkBitmapConfigToColorType(SkBitmap::Config config, SkColorType* ctOut) {
+ SkColorType ct;
+ switch (config) {
+ case SkBitmap::kA8_Config:
+ ct = kAlpha_8_SkColorType;
+ break;
+ case SkBitmap::kIndex8_Config:
+ ct = kIndex_8_SkColorType;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ ct = kRGB_565_SkColorType;
+ break;
+ case SkBitmap::kARGB_4444_Config:
+ ct = kARGB_4444_SkColorType;
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ ct = kPMColor_SkColorType;
+ break;
+ case SkBitmap::kNo_Config:
+ default:
+ return false;
+ }
+ if (ctOut) {
+ *ctOut = ct;
+ }
+ return true;
+}
+
+
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
SkImageInfo info;
if (!bm.asImageInfo(&info)) {
diff --git a/src/image/SkImagePriv.h b/src/image/SkImagePriv.h
index bf28f598c5..7c19c734c2 100644
--- a/src/image/SkImagePriv.h
+++ b/src/image/SkImagePriv.h
@@ -14,6 +14,8 @@
class SkPicture;
extern SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo&);
+extern SkBitmap::Config SkColorTypeToBitmapConfig(SkColorType);
+extern bool SkBitmapConfigToColorType(SkBitmap::Config, SkColorType* ctOut);
// Call this if you explicitly want to use/share this pixelRef in the image
extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index a833c636ff..153d1e220b 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -5,13 +5,14 @@
* found in the LICENSE file.
*/
-#include "SkDecodingImageGenerator.h"
#include "SkData.h"
+#include "SkDecodingImageGenerator.h"
#include "SkImageDecoder.h"
+#include "SkImageInfo.h"
#include "SkImageGenerator.h"
#include "SkImagePriv.h"
#include "SkStream.h"
-
+#include "SkUtils.h"
namespace {
/**
@@ -20,50 +21,89 @@ namespace {
*/
class TargetAllocator : public SkBitmap::Allocator {
public:
- TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
+ TargetAllocator(void* target,
+ size_t rowBytes,
+ int width,
+ int height,
+ SkBitmap::Config config)
: fTarget(target)
, fRowBytes(rowBytes)
- , fInfo(info) { }
+ , fWidth(width)
+ , fHeight(height)
+ , fConfig(config) { }
- virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
- if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
- || (bm->width() != fInfo.fWidth)
- || (bm->height() != fInfo.fHeight)) {
- return false;
+ bool isReady() { return (fTarget != NULL); }
+
+ virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
+ if ((NULL == fTarget)
+ || (fConfig != bm->config())
+ || (fWidth != bm->width())
+ || (fHeight != bm->height())
+ || (ct != NULL)) {
+ // Call default allocator.
+ return bm->allocPixels(NULL, ct);
}
- bm->setConfig(bm->config(), bm->width(), bm->height(),
- fRowBytes, bm->alphaType());
- bm->setPixels(fTarget, ct);
+ // make sure fRowBytes is correct.
+ bm->setConfig(fConfig, fWidth, fHeight, fRowBytes, bm->alphaType());
+ // TODO(halcanary): verify that all callers of this function
+ // will respect new RowBytes. Will be moot once rowbytes belongs
+ // to PixelRef.
+ bm->setPixels(fTarget, NULL);
+ fTarget = NULL; // never alloc same pixels twice!
return true;
}
private:
- void* fTarget;
- size_t fRowBytes;
- SkImageInfo fInfo;
+ void* fTarget; // Block of memory to be supplied as pixel memory
+ // in allocPixelRef. Must be large enough to hold
+ // a bitmap described by fWidth, fHeight, and
+ // fRowBytes.
+ size_t fRowBytes; // rowbytes for the destination bitmap
+ int fWidth; // Along with fHeight and fConfig, the information
+ int fHeight; // about the bitmap whose pixels this allocator is
+ // expected to allocate. If they do not match the
+ // bitmap passed to allocPixelRef, it is assumed
+ // that the bitmap will be copied to a bitmap with
+ // the correct info using this allocator, so the
+ // default allocator will be used instead of
+ // fTarget.
+ SkBitmap::Config fConfig;
typedef SkBitmap::Allocator INHERITED;
};
+
+// 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
+
+#ifdef SK_DEBUG
+inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
+ return ((reported == actual)
+ || ((reported == kPremul_SkAlphaType)
+ && (actual == kOpaque_SkAlphaType)));
+}
+#endif // SK_DEBUG
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
-SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
+SkDecodingImageGenerator::SkDecodingImageGenerator(
+ SkData* data,
+ SkStreamRewindable* stream,
+ const SkImageInfo& info,
+ int sampleSize,
+ bool ditherImage,
+ SkBitmap::Config requestedConfig)
: 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());
+ , fInfo(info)
+ , fSampleSize(sampleSize)
+ , fDitherImage(ditherImage)
+ , fRequestedConfig(requestedConfig) {
+ SkASSERT(stream != NULL);
+ SkSafeRef(fData); // may be NULL.
}
SkDecodingImageGenerator::~SkDecodingImageGenerator() {
@@ -71,15 +111,16 @@ SkDecodingImageGenerator::~SkDecodingImageGenerator() {
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
+bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
+ if (info != NULL) {
+ *info = fInfo;
+ }
+ return true;
+}
SkData* SkDecodingImageGenerator::refEncodedData() {
// This functionality is used in `gm --serialize`
+ // Does not encode options.
if (fData != NULL) {
return SkSafeRef(fData);
}
@@ -98,111 +139,149 @@ SkData* SkDecodingImageGenerator::refEncodedData() {
return SkSafeRef(fData);
}
-bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
- // 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 (!bitmap.asImageInfo(&fInfo)) {
- // We can't use bitmap.config() as is.
- if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
- 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) {
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.
+ // The caller has specified a different info. This is an
+ // error for this kind of SkImageGenerator. Use the Options
+ // to change the settings.
return false;
}
- int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
+ int bpp = SkBitmap::ComputeBytesPerPixel(fRequestedConfig);
if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
+ // The caller has specified a bad rowBytes.
return false;
}
- SkBitmap bitmap;
- if (!bitmap.setConfig(info, rowBytes)) {
+
+ SkAssertResult(fStream->rewind());
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+ if (NULL == decoder.get()) {
return false;
}
+ decoder->setDitherImage(fDitherImage);
+ decoder->setSampleSize(fSampleSize);
- TargetAllocator allocator(pixels, rowBytes, info);
- if (!fDoCopyTo) {
- decoder->setAllocator(&allocator);
- }
- bool success = decoder->decode(fStream, &bitmap,
+ SkBitmap bitmap;
+ TargetAllocator allocator(pixels, rowBytes, info.fWidth,
+ info.fHeight, fRequestedConfig);
+ decoder->setAllocator(&allocator);
+ bool success = decoder->decode(fStream, &bitmap, fRequestedConfig,
SkImageDecoder::kDecodePixels_Mode);
decoder->setAllocator(NULL);
if (!success) {
return false;
}
- if (fDoCopyTo) {
- SkBitmap bm8888;
- bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
+ if (allocator.isReady()) { // Did not use pixels!
+ SkBitmap bm;
+ SkASSERT(bitmap.canCopyTo(fRequestedConfig));
+ if (!bitmap.copyTo(&bm, fRequestedConfig, &allocator)
+ || allocator.isReady()) {
+ SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
+ // Earlier we checked canCopyto(); we expect consistency.
+ return false;
+ }
+ SkASSERT(check_alpha(fInfo.fAlphaType, bm.alphaType()));
+ } else {
+ SkASSERT(check_alpha(fInfo.fAlphaType, bitmap.alphaType()));
}
return true;
}
-bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
- SkDiscardableMemory::Factory* factory) {
+
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkData* data,
+ const SkDecodingImageGenerator::Options& opts) {
SkASSERT(data != NULL);
- SkASSERT(dst != NULL);
- SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
- return SkInstallDiscardablePixelRef(gen, dst, factory);
+ if (NULL == data) {
+ return NULL;
+ }
+ SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
+ SkASSERT(stream != NULL);
+ SkASSERT(stream->unique());
+ return SkDecodingImageGenerator::Create(data, stream, opts);
}
-bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
- SkBitmap* dst,
- SkDiscardableMemory::Factory* factory) {
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkStreamRewindable* stream,
+ const SkDecodingImageGenerator::Options& opts) {
SkASSERT(stream != NULL);
- SkASSERT(dst != NULL);
+ SkASSERT(stream->unique());
if ((stream == NULL) || !stream->unique()) {
SkSafeUnref(stream);
- return false;
+ return NULL;
+ }
+ return SkDecodingImageGenerator::Create(NULL, stream, opts);
+}
+
+// A contructor-type function that returns NULL on failure. This
+// prevents the returned SkImageGenerator from ever being in a bad
+// state. Called by both Create() functions
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkData* data,
+ SkStreamRewindable* stream,
+ const SkDecodingImageGenerator::Options& opts) {
+ SkASSERT(stream);
+ SkAutoTUnref<SkStreamRewindable> autoStream(stream); // always unref this.
+ if (opts.fUseRequestedColorType &&
+ (kIndex_8_SkColorType == opts.fRequestedColorType)) {
+ // We do not support indexed color with SkImageGenerators,
+ return NULL;
+ }
+ SkAssertResult(autoStream->rewind());
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
+ if (NULL == decoder.get()) {
+ return NULL;
+ }
+ SkBitmap bitmap;
+ decoder->setSampleSize(opts.fSampleSize);
+ if (!decoder->decode(stream, &bitmap,
+ SkImageDecoder::kDecodeBounds_Mode)) {
+ return NULL;
+ }
+ if (bitmap.config() == SkBitmap::kNo_Config) {
+ return NULL;
+ }
+
+ SkImageInfo info;
+ SkBitmap::Config config;
+
+ if (!opts.fUseRequestedColorType) {
+ // Use default config.
+ if (SkBitmap::kIndex8_Config == bitmap.config()) {
+ // We don't support kIndex8 because we don't support
+ // colortables in this workflow.
+ config = SkBitmap::kARGB_8888_Config;
+ info.fWidth = bitmap.width();
+ info.fHeight = bitmap.height();
+ info.fColorType = kPMColor_SkColorType;
+ info.fAlphaType = bitmap.alphaType();
+ } else {
+ config = bitmap.config(); // Save for later!
+ if (!bitmap.asImageInfo(&info)) {
+ SkDEBUGFAIL("Getting SkImageInfo from bitmap failed.");
+ return NULL;
+ }
+ }
+ } else {
+ config = SkColorTypeToBitmapConfig(opts.fRequestedColorType);
+ if (!bitmap.canCopyTo(config)) {
+ SkASSERT(bitmap.config() != config);
+ return NULL; // Can not translate to needed config.
+ }
+ info.fWidth = bitmap.width();
+ info.fHeight = bitmap.height();
+ info.fColorType = opts.fRequestedColorType;
+ info.fAlphaType = bitmap.alphaType();
+
+ // Sanity check.
+ SkDEBUGCODE(SkColorType tmp;)
+ SkASSERT(SkBitmapConfigToColorType(config, &tmp));
+ SkASSERT(tmp == opts.fRequestedColorType);
}
- SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
- return SkInstallDiscardablePixelRef(gen, dst, factory);
+ return SkNEW_ARGS(SkDecodingImageGenerator,
+ (data, autoStream.detach(), info,
+ opts.fSampleSize, opts.fDitherImage, config));
}
diff --git a/src/images/SkDecodingImageGenerator.h b/src/images/SkDecodingImageGenerator.h
index dba234bcf1..12a49d59c4 100644
--- a/src/images/SkDecodingImageGenerator.h
+++ b/src/images/SkDecodingImageGenerator.h
@@ -8,113 +8,134 @@
#ifndef SkDecodingImageGenerator_DEFINED
#define SkDecodingImageGenerator_DEFINED
-#include "SkDiscardableMemory.h"
+#include "SkBitmap.h"
#include "SkImageGenerator.h"
-#include "SkImageInfo.h"
-class SkBitmap;
+class SkData;
class SkStreamRewindable;
/**
- * Calls into SkImageDecoder::DecodeMemoryToTarget to implement a
- * SkImageGenerator
+ * An implementation of SkImageGenerator that calls into
+ * SkImageDecoder.
*/
class SkDecodingImageGenerator : public SkImageGenerator {
public:
- /*
- * The constructor will take a reference to the SkData. The
- * destructor will unref() it.
- */
- explicit SkDecodingImageGenerator(SkData* data);
-
- /*
- * The SkData version of this constructor is preferred. If the
- * stream has an underlying SkData (such as a SkMemoryStream)
- * pass that in.
- *
- * This object will unref the stream when done. Since streams
- * have internal state (position), the caller should not pass a
- * shared stream in. Pass either a new duplicated stream in or
- * transfer ownership of the stream. In the latter case, be sure
- * that there are no other consumers of the stream who will
- * modify the stream's position. This constructor asserts
- * stream->unique().
- *
- * For example:
- * SkStreamRewindable* stream;
- * ...
- * SkImageGenerator* gen
- * = SkNEW_ARGS(SkDecodingImageGenerator,
- * (stream->duplicate()));
- * ...
- * SkDELETE(gen);
- */
- explicit SkDecodingImageGenerator(SkStreamRewindable* stream);
-
virtual ~SkDecodingImageGenerator();
-
virtual SkData* refEncodedData() SK_OVERRIDE;
-
+ // This implementaion of getInfo() always returns true.
virtual bool getInfo(SkImageInfo* info) SK_OVERRIDE;
-
virtual bool getPixels(const SkImageInfo& info,
void* pixels,
size_t rowBytes) SK_OVERRIDE;
-
/**
- * Install the SkData into the destination bitmap, using a new
- * SkDiscardablePixelRef and a new SkDecodingImageGenerator.
- *
- * @param data Contains the encoded image data that will be used
- * by the SkDecodingImageGenerator. Will be ref()ed.
+ * These options will be passed on to the image decoder. The
+ * defaults are sensible.
*
- * @param destination Upon success, this bitmap will be
- * configured and have a pixelref installed.
+ * @param fSampleSize If set to > 1, tells the decoder to return a
+ * smaller than original bitmap, sampling 1 pixel for
+ * every size pixels. e.g. if sample size is set to 3,
+ * then the returned bitmap will be 1/3 as wide and high,
+ * and will contain 1/9 as many pixels as the original.
+ * Note: this is a hint, and the codec may choose to
+ * ignore this, or only approximate the sample size.
*
- * @param factory If not NULL, this object will be used as a
- * source of discardable memory when decoding. If NULL, then
- * SkDiscardableMemory::Create() will be called.
+ * @param fDitherImage Set to true if the the decoder should try to
+ * dither the resulting image when decoding to a smaller
+ * color-space. The default is true.
*
- * @return true iff successful.
+ * @param fRequestedColorType If not given, then use whichever
+ * config the decoder wants. Else try to use this color
+ * type. If the decoder won't support this color type,
+ * SkDecodingImageGenerator::Create will return
+ * NULL. kIndex_8_SkColorType is not supported.
*/
- static bool Install(SkData* data, SkBitmap* destination,
- SkDiscardableMemory::Factory* factory = NULL);
+ struct Options {
+ Options()
+ : fSampleSize(1)
+ , fDitherImage(true)
+ , fUseRequestedColorType(false)
+ , fRequestedColorType() { }
+ Options(int sampleSize, bool dither)
+ : fSampleSize(sampleSize)
+ , fDitherImage(dither)
+ , fUseRequestedColorType(false)
+ , fRequestedColorType() { }
+ Options(int sampleSize, bool dither, SkColorType colorType)
+ : fSampleSize(sampleSize)
+ , fDitherImage(dither)
+ , fUseRequestedColorType(true)
+ , fRequestedColorType(colorType) { }
+ const int fSampleSize;
+ const bool fDitherImage;
+ const bool fUseRequestedColorType;
+ const SkColorType fRequestedColorType;
+ };
+
/**
- * Install the stream into the destination bitmap, using a new
- * SkDiscardablePixelRef and a new SkDecodingImageGenerator.
+ * These two functions return a SkImageGenerator that calls into
+ * SkImageDecoder. They return NULL on failure.
*
- * The SkData version of this function is preferred. If the
- * stream has an underlying SkData (such as a SkMemoryStream)
- * pass that in.
+ * The SkData version of this function is preferred. If the stream
+ * has an underlying SkData (such as a SkMemoryStream) pass that in.
*
- * @param stream The source of encoded data that will be passed
- * to the decoder. The installed SkDecodingImageGenerator will
- * unref the stream when done. If false is returned, this
- * function will perform the unref. Since streams have internal
- * state (position), the caller should not pass a shared stream
- * in. Pass either a new duplicated stream in or transfer
- * ownership of the stream. In the latter case, be sure that
- * there are no other consumers of the stream who will modify the
- * stream's position. This function will fail if
- * (!stream->unique()).
+ * This object will unref the stream when done or on failure. Since
+ * streams have internal state (position), the caller should not pass
+ * a shared stream in. Pass either a new duplicated stream in or
+ * transfer ownership of the stream. This factory asserts
+ * stream->unique().
*
- * @param destination Upon success, this bitmap will be
- * configured and have a pixelref installed.
+ * For example:
+ * SkStreamRewindable* stream;
+ * ...
+ * SkImageGenerator* gen
+ * = SkDecodingImageGenerator::Create(
+ * stream->duplicate(), SkDecodingImageGenerator::Options());
+ * ...
+ * SkDELETE(gen);
*
- * @param factory If not NULL, this object will be used as a
- * source of discardable memory when decoding. If NULL, then
- * SkDiscardableMemory::Create() will be called.
+ * @param Options (see above)
*
- * @return true iff successful.
+ * @return NULL on failure, a new SkImageGenerator on success.
*/
- static bool Install(SkStreamRewindable* stream, SkBitmap* destination,
- SkDiscardableMemory::Factory* factory = NULL);
+ static SkImageGenerator* Create(SkStreamRewindable* stream,
+ const Options& opt);
+
+ /**
+ * @param data Contains the encoded image data that will be used by
+ * the SkDecodingImageGenerator. Will be ref()ed by the
+ * SkImageGenerator constructor and and unref()ed on deletion.
+ */
+ static SkImageGenerator* Create(SkData* data, const Options& opt);
private:
- SkData* fData;
- SkStreamRewindable* fStream;
- SkImageInfo fInfo;
- bool fHasInfo;
- bool fDoCopyTo;
+ SkData* fData;
+ SkStreamRewindable* fStream;
+ const SkImageInfo fInfo;
+ const int fSampleSize;
+ const bool fDitherImage;
+ const SkBitmap::Config fRequestedConfig;
+ SkDecodingImageGenerator(SkData* data,
+ SkStreamRewindable* stream,
+ const SkImageInfo& info,
+ int sampleSize,
+ bool ditherImage,
+ SkBitmap::Config requestedConfig);
+ static SkImageGenerator* Create(SkData*, SkStreamRewindable*,
+ const Options&);
+ typedef SkImageGenerator INHERITED;
};
+
+// // Example of most basic use case:
+//
+// bool install_data(SkData* data, SkBitmap* dst) {
+// return SkInstallDiscardablePixelRef(
+// SkDecodingImageGenerator::Create(
+// data, SkDecodingImageGenerator::Options()), dst, NULL);
+// }
+// bool install_stream(SkStreamRewindable* stream, SkBitmap* dst) {
+// return SkInstallDiscardablePixelRef(
+// SkDecodingImageGenerator::Create(
+// stream, SkDecodingImageGenerator::Options()), dst, NULL);
+// }
+
#endif // SkDecodingImageGenerator_DEFINED
diff --git a/src/lazy/SkCachingPixelRef.cpp b/src/lazy/SkCachingPixelRef.cpp
index 668f57ef30..fb30d051e1 100644
--- a/src/lazy/SkCachingPixelRef.cpp
+++ b/src/lazy/SkCachingPixelRef.cpp
@@ -12,7 +12,6 @@
bool SkCachingPixelRef::Install(SkImageGenerator* generator,
SkBitmap* dst) {
SkImageInfo info;
- SkASSERT(generator != NULL);
SkASSERT(dst != NULL);
if ((NULL == generator)
|| !(generator->getInfo(&info))
diff --git a/src/lazy/SkDiscardablePixelRef.cpp b/src/lazy/SkDiscardablePixelRef.cpp
index 160ca5b4fb..2886156102 100644
--- a/src/lazy/SkDiscardablePixelRef.cpp
+++ b/src/lazy/SkDiscardablePixelRef.cpp
@@ -72,20 +72,19 @@ bool SkInstallDiscardablePixelRef(SkImageGenerator* generator,
SkBitmap* dst,
SkDiscardableMemory::Factory* factory) {
SkImageInfo info;
- SkASSERT(generator != NULL);
- if ((NULL == generator)
- || (!generator->getInfo(&info))
+ SkAutoTDelete<SkImageGenerator> autoGenerator(generator);
+ if ((NULL == autoGenerator.get())
+ || (!autoGenerator->getInfo(&info))
|| (!dst->setConfig(info, 0))) {
- SkDELETE(generator);
return false;
}
SkASSERT(dst->config() != SkBitmap::kNo_Config);
- if (dst->empty()) { // Use a normal pixelref.
- SkDELETE(generator); // Do not need this anymore.
+ if (dst->empty()) { // Use a normal pixelref.
return dst->allocPixels(NULL, NULL);
}
- SkAutoTUnref<SkDiscardablePixelRef> ref(SkNEW_ARGS(SkDiscardablePixelRef,
- (info, generator, dst->rowBytes(), factory)));
+ SkAutoTUnref<SkDiscardablePixelRef> ref(
+ SkNEW_ARGS(SkDiscardablePixelRef,
+ (info, autoGenerator.detach(), dst->rowBytes(), factory)));
dst->setPixelRef(ref);
return true;
}
diff --git a/src/lazy/SkDiscardablePixelRef.h b/src/lazy/SkDiscardablePixelRef.h
index 4b6693837d..3367096c26 100644
--- a/src/lazy/SkDiscardablePixelRef.h
+++ b/src/lazy/SkDiscardablePixelRef.h
@@ -13,6 +13,15 @@
#include "SkImageInfo.h"
#include "SkPixelRef.h"
+/**
+ * A PixelRef backed by SkDiscardableMemory, with the ability to
+ * re-generate the pixels (via a SkImageGenerator) if the DM is
+ * purged.
+ *
+ * Since SkColorTable is reference-counted, we do not support indexed
+ * color with this class; there would be no way for the discardable
+ * memory system to unref the color table.
+ */
class SkDiscardablePixelRef : public SkPixelRef {
public:
SK_DECLARE_UNFLATTENABLE_OBJECT()