1ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com/*
2ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com * Copyright 2013 Google Inc.
3ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com *
4ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com * Use of this source code is governed by a BSD-style license that can be
5ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com * found in the LICENSE file.
6ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com */
7ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com
81ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org#include "SkData.h"
93d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#include "SkDecodingImageGenerator.h"
10ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com#include "SkImageDecoder.h"
113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#include "SkImageInfo.h"
12edd370f949a457f5d8f7a62efdaf685d4caf46fehalcanary@google.com#include "SkImageGenerator.h"
1329d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com#include "SkImagePriv.h"
1429d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com#include "SkStream.h"
153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#include "SkUtils.h"
1629d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com
171f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgnamespace {
181f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgbool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
198a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    return a.width() == b.width() && a.height() == b.height() &&
208a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org           a.colorType() == b.colorType();
218a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org}
228a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org
231f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgclass DecodingImageGenerator : public SkImageGenerator {
241f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgpublic:
251f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    virtual ~DecodingImageGenerator();
261f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
271f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkData*                fData;
281f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkStreamRewindable*    fStream;
291f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    const SkImageInfo      fInfo;
301f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    const int              fSampleSize;
311f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    const bool             fDitherImage;
321f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
331f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    DecodingImageGenerator(SkData* data,
341f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org                           SkStreamRewindable* stream,
351f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org                           const SkImageInfo& info,
361f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org                           int sampleSize,
371f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org                           bool ditherImage);
3800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org
3900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.orgprotected:
4000f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    virtual SkData* onRefEncodedData() SK_OVERRIDE;
4100f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
4200f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        *info = fInfo;
4300f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        return true;
4400f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    }
4500f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    virtual bool onGetPixels(const SkImageInfo& info,
4600f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org                             void* pixels, size_t rowBytes,
4700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org                             SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
4800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org
4900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.orgprivate:
501f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    typedef SkImageGenerator INHERITED;
511f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org};
521f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
5329d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com/**
5429d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com *  Special allocator used by getPixels(). Uses preallocated memory
558a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org *  provided if possible, else fall-back on the default allocator
5629d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com */
5729d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.comclass TargetAllocator : public SkBitmap::Allocator {
5829d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.compublic:
598a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    TargetAllocator(const SkImageInfo& info,
608a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org                    void* target,
618a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org                    size_t rowBytes)
628a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        : fInfo(info)
638a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        , fTarget(target)
6429d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com        , fRowBytes(rowBytes)
658a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    {}
66d665dc4c100f73272422dd17b4dd2c5d57a6b6dehalcanary@google.com
673d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    bool isReady() { return (fTarget != NULL); }
683d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
693d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
708a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
713d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            // Call default allocator.
72848250415eddc54075f7eb8795e8db79e749c6abreed            return bm->tryAllocPixels(NULL, ct);
7329d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com        }
7486cbf99a5122cd419eb76fd07cea80499f31a383skia.committer@gmail.com
753d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // TODO(halcanary): verify that all callers of this function
763d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // will respect new RowBytes.  Will be moot once rowbytes belongs
773d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // to PixelRef.
7800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
798a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org
803d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        fTarget = NULL;  // never alloc same pixels twice!
8129d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com        return true;
8229d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    }
8329d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com
8429d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.comprivate:
858a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    const SkImageInfo fInfo;
863d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    void* fTarget;  // Block of memory to be supplied as pixel memory
873d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    // in allocPixelRef.  Must be large enough to hold
888a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org                    // a bitmap described by fInfo and fRowBytes
898a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    const size_t fRowBytes;  // rowbytes for the destination bitmap
908a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org
9129d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    typedef SkBitmap::Allocator INHERITED;
9229d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com};
933d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
943d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
953d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#ifdef SK_DEBUG
963d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
973d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#else
983d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #define SkCheckResult(expr, value)  (void)(expr)
993d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#endif
1003d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
1013d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#ifdef SK_DEBUG
1023d50ea1b87132833d7eab38964f40315ba553205halcanary@google.cominline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
1033d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    return ((reported == actual)
1043d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            || ((reported == kPremul_SkAlphaType)
1053d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                && (actual == kOpaque_SkAlphaType)));
1063d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
1073d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#endif  // SK_DEBUG
1083d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
10929d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com////////////////////////////////////////////////////////////////////////////////
110ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com
1111f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgDecodingImageGenerator::DecodingImageGenerator(
1123d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkData* data,
1133d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkStreamRewindable* stream,
1143d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        const SkImageInfo& info,
1153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        int sampleSize,
1168a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        bool ditherImage)
11729d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    : fData(data)
11829d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    , fStream(stream)
1193d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    , fInfo(info)
1203d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    , fSampleSize(sampleSize)
1213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    , fDitherImage(ditherImage)
1228a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org{
1233d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkASSERT(stream != NULL);
1243d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkSafeRef(fData);  // may be NULL.
12529d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com}
12629d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com
1271f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgDecodingImageGenerator::~DecodingImageGenerator() {
12829d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    SkSafeUnref(fData);
12929d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    fStream->unref();
130ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com}
131ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com
13200f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.orgSkData* DecodingImageGenerator::onRefEncodedData() {
1332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // This functionality is used in `gm --serialize`
1343d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    // Does not encode options.
13533a30503d76fdd989358cedd78445ba96bb809ddreed    if (NULL == fData) {
13633a30503d76fdd989358cedd78445ba96bb809ddreed        // TODO(halcanary): SkStreamRewindable needs a refData() function
13733a30503d76fdd989358cedd78445ba96bb809ddreed        // which returns a cheap copy of the underlying data.
13833a30503d76fdd989358cedd78445ba96bb809ddreed        if (!fStream->rewind()) {
13933a30503d76fdd989358cedd78445ba96bb809ddreed            return NULL;
14033a30503d76fdd989358cedd78445ba96bb809ddreed        }
14133a30503d76fdd989358cedd78445ba96bb809ddreed        size_t length = fStream->getLength();
1429594da111dc1c36c1912eb61207aaa54c17ea550reed        if (length) {
1439594da111dc1c36c1912eb61207aaa54c17ea550reed            fData = SkData::NewFromStream(fStream, length);
14433a30503d76fdd989358cedd78445ba96bb809ddreed        }
14529d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    }
1469594da111dc1c36c1912eb61207aaa54c17ea550reed    return SkSafeRef(fData);
147ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com}
148ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com
14900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.orgbool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
15000f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org                                         void* pixels, size_t rowBytes,
15100f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org                                         SkPMColor ctableEntries[], int* ctableCount) {
1521ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org    if (fInfo != info) {
1533d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // The caller has specified a different info.  This is an
1543d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // error for this kind of SkImageGenerator.  Use the Options
1553d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // to change the settings.
1561ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org        return false;
1571ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org    }
1583d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
1593d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAssertResult(fStream->rewind());
1603d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
1613d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (NULL == decoder.get()) {
1621ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org        return false;
1631ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org    }
1643d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    decoder->setDitherImage(fDitherImage);
1653d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    decoder->setSampleSize(fSampleSize);
166e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    decoder->setRequireUnpremultipliedColors(info.alphaType() == kUnpremul_SkAlphaType);
1671ad518bf38184ae820f31f9b79dfb4e4daf5841acommit-bot@chromium.org
1683d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkBitmap bitmap;
1698a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    TargetAllocator allocator(fInfo, pixels, rowBytes);
1703d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    decoder->setAllocator(&allocator);
171bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    bool success = decoder->decode(fStream, &bitmap, info.colorType(),
17229d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com                                   SkImageDecoder::kDecodePixels_Mode);
17329d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    decoder->setAllocator(NULL);
17429d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    if (!success) {
17529d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com        return false;
17629d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    }
1773d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (allocator.isReady()) {  // Did not use pixels!
1783d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkBitmap bm;
1798a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        SkASSERT(bitmap.canCopyTo(info.colorType()));
1808a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
1818a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        if (!copySuccess || allocator.isReady()) {
1823d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
1833d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            // Earlier we checked canCopyto(); we expect consistency.
1843d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            return false;
1853d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
1868a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
1873d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    } else {
1888a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
18929d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    }
19000f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org
19100f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    if (kIndex_8_SkColorType == info.colorType()) {
19200f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        if (kIndex_8_SkColorType != bitmap.colorType()) {
19300f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org            return false;   // they asked for Index8, but we didn't receive that from decoder
19400f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        }
19500f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        SkColorTable* ctable = bitmap.getColorTable();
19600f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        if (NULL == ctable) {
19700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org            return false;
19800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        }
19900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        const int count = ctable->count();
20000f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
20100f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        ctable->unlockColors();
20200f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org        *ctableCount = count;
20300f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    }
20429d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    return true;
205ad04eb49f5d3f324e6b85411c776d7466c1fef92halcanary@google.com}
2063d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
2073d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com// A contructor-type function that returns NULL on failure.  This
2083d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com// prevents the returned SkImageGenerator from ever being in a bad
2093d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com// state.  Called by both Create() functions
2101f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgSkImageGenerator* CreateDecodingImageGenerator(
2113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkData* data,
2123d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkStreamRewindable* stream,
2133d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        const SkDecodingImageGenerator::Options& opts) {
2143d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkASSERT(stream);
2153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAutoTUnref<SkStreamRewindable> autoStream(stream);  // always unref this.
2163d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAssertResult(autoStream->rewind());
2173d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
2183d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (NULL == decoder.get()) {
2193d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return NULL;
2203d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
2213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkBitmap bitmap;
2223d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    decoder->setSampleSize(opts.fSampleSize);
2231ae492f19bc3e1ddbe97b5be6380c82f9e6eacb8commit-bot@chromium.org    decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
22400f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
2253d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return NULL;
2263d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
22700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    if (kUnknown_SkColorType == bitmap.colorType()) {
2283d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return NULL;
2293d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
2303d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
2318a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org    SkImageInfo info = bitmap.info();
2323d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
23300f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
2348a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
2358a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org            SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
2363d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            return NULL;  // Can not translate to needed config.
2373d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
238e5ea500d4714a7d84de2bf913e81be3b65d2de68reed        info = info.makeColorType(opts.fRequestedColorType);
23929d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com    }
2401ae492f19bc3e1ddbe97b5be6380c82f9e6eacb8commit-bot@chromium.org
241e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (opts.fRequireUnpremul && info.alphaType() != kOpaque_SkAlphaType) {
242e5ea500d4714a7d84de2bf913e81be3b65d2de68reed        info = info.makeAlphaType(kUnpremul_SkAlphaType);
2431ae492f19bc3e1ddbe97b5be6380c82f9e6eacb8commit-bot@chromium.org    }
2442fd0d14b9be34a7a945942733c3516d97d07f516scroggo
245e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    SkAlphaType newAlphaType = info.alphaType();
246e5ea500d4714a7d84de2bf913e81be3b65d2de68reed    if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType)) {
2472fd0d14b9be34a7a945942733c3516d97d07f516scroggo        return NULL;
2482fd0d14b9be34a7a945942733c3516d97d07f516scroggo    }
2492fd0d14b9be34a7a945942733c3516d97d07f516scroggo
2501f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    return SkNEW_ARGS(DecodingImageGenerator,
251e5ea500d4714a7d84de2bf913e81be3b65d2de68reed                      (data, autoStream.detach(), info.makeAlphaType(newAlphaType),
2528a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org                       opts.fSampleSize, opts.fDitherImage));
25329d96935ae34dfcd6e403f9beefa7436e226836ehalcanary@google.com}
2541f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
2551f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org}  // namespace
2561f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
2571f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
2581f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
2591f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgSkImageGenerator* SkDecodingImageGenerator::Create(
2601f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        SkData* data,
2611f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        const SkDecodingImageGenerator::Options& opts) {
2621f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkASSERT(data != NULL);
2631f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    if (NULL == data) {
2641f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        return NULL;
2651f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    }
2661f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
2671f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkASSERT(stream != NULL);
2681f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkASSERT(stream->unique());
2691f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    return CreateDecodingImageGenerator(data, stream, opts);
2701f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org}
2711f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org
2721f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.orgSkImageGenerator* SkDecodingImageGenerator::Create(
2731f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        SkStreamRewindable* stream,
2741f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        const SkDecodingImageGenerator::Options& opts) {
2751f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkASSERT(stream != NULL);
2761f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    SkASSERT(stream->unique());
2771f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    if ((stream == NULL) || !stream->unique()) {
2781f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        SkSafeUnref(stream);
2791f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org        return NULL;
2801f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    }
2811f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org    return CreateDecodingImageGenerator(NULL, stream, opts);
2821f2d357436c7d133873b8f7d497c01afa70a6f32commit-bot@chromium.org}
283