16ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com/*
26ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com * Copyright 2013 Google Inc.
36ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com *
46ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com * Use of this source code is governed by a BSD-style license that can be
56ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com * found in the LICENSE file.
66ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com */
76ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
86ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com#include "SkDecodingImageGenerator.h"
96ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com#include "SkData.h"
106ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com#include "SkImageDecoder.h"
116168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com#include "SkImageGenerator.h"
12f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com#include "SkImagePriv.h"
13f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com#include "SkStream.h"
14f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
15f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
16f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.comnamespace {
17f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com/**
18f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com *  Special allocator used by getPixels(). Uses preallocated memory
19f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com *  provided.
20f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com */
21f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.comclass TargetAllocator : public SkBitmap::Allocator {
22f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.compublic:
23f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
24f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        : fTarget(target)
25f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        , fRowBytes(rowBytes)
26f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        , fInfo(info) { }
27f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
28f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
29f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
30f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com            || (bm->width() != fInfo.fWidth)
31f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com            || (bm->height() != fInfo.fHeight)) {
32f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com            return false;
33f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        }
34f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        bm->setConfig(bm->config(), bm->width(), bm->height(),
35f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com                      fRowBytes, bm->alphaType());
36f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        bm->setPixels(fTarget, ct);
37f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return true;
38f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
39f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
40f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.comprivate:
41f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    void* fTarget;
42f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    size_t fRowBytes;
43f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkImageInfo fInfo;
44f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    typedef SkBitmap::Allocator INHERITED;
45f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com};
46f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com}  // namespace
47f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com////////////////////////////////////////////////////////////////////////////////
486ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
496ac702e890656e801469060c1b9474912a5b704ahalcanary@google.comSkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
50f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    : fData(data)
51f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    , fHasInfo(false)
52f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    , fDoCopyTo(false) {
536ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkASSERT(fData != NULL);
54f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    fStream = SkNEW_ARGS(SkMemoryStream, (fData));
55f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkASSERT(fStream != NULL);
56f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkASSERT(fStream->unique());
576ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    fData->ref();
586ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
596ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
60f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.comSkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream)
61f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    : fData(NULL)
62f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    , fStream(stream)
63f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    , fHasInfo(false)
64f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    , fDoCopyTo(false) {
65f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkASSERT(fStream != NULL);
66f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkASSERT(fStream->unique());
67f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com}
68f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
696ac702e890656e801469060c1b9474912a5b704ahalcanary@google.comSkDecodingImageGenerator::~SkDecodingImageGenerator() {
70f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkSafeUnref(fData);
71f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    fStream->unref();
726ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
736ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
74f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
75f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com#ifdef SK_DEBUG
76f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
77f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com#else
78f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    #define SkCheckResult(expr, value)  (void)(expr)
79f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com#endif
80f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
816ac702e890656e801469060c1b9474912a5b704ahalcanary@google.comSkData* SkDecodingImageGenerator::refEncodedData() {
829ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com    // This functionality is used in `gm --serialize`
83f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (fData != NULL) {
84f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return SkSafeRef(fData);
85f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
86f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    // TODO(halcanary): SkStreamRewindable needs a refData() function
87f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    // which returns a cheap copy of the underlying data.
88f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (!fStream->rewind()) {
89f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return NULL;
90f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
91f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    size_t length = fStream->getLength();
92f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (0 == length) {
93f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return NULL;
94f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
95f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    void* buffer = sk_malloc_flags(length, 0);
96f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkCheckResult(fStream->read(buffer, length), length);
97f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    fData = SkData::NewFromMalloc(buffer, length);
98f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    return SkSafeRef(fData);
996ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
1006ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
1016ac702e890656e801469060c1b9474912a5b704ahalcanary@google.combool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
102f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    // info can be NULL.  If so, will update fInfo, fDoCopyTo, and fHasInfo.
103f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (fHasInfo) {
104f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        if (info != NULL) {
105f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com            *info = fInfo;
106f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        }
107f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return true;
108f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
109f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkAssertResult(fStream->rewind());
110f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
111f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (NULL == decoder.get()) {
112f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
113f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
114f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkBitmap bitmap;
115f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (!decoder->decode(fStream, &bitmap,
116f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com                         SkImageDecoder::kDecodeBounds_Mode)) {
117f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
118f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
119f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (bitmap.config() == SkBitmap::kNo_Config) {
120f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
121f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
122229ce27ff710068fd47f8da7361f508dfbc700aareed@google.com    if (!bitmap.asImageInfo(&fInfo)) {
123f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        // We can't use bitmap.config() as is.
124f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
125f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com            SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)");
126f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com            return false;
127f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        }
128f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        fDoCopyTo = true;
129f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        fInfo.fWidth = bitmap.width();
130f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        fInfo.fHeight = bitmap.height();
131f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        fInfo.fColorType = kPMColor_SkColorType;
132f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        fInfo.fAlphaType = bitmap.alphaType();
133f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
134f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (info != NULL) {
135f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        *info = fInfo;
136f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
137f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    fHasInfo = true;
138f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    return true;
1396ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
1406ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com
1416ac702e890656e801469060c1b9474912a5b704ahalcanary@google.combool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
1426ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com                                         void* pixels,
1436ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com                                         size_t rowBytes) {
144f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (NULL == pixels) {
145f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
146f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
147f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (!this->getInfo(NULL)) {
148f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
149f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
150f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
151f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;  // Unsupported SkColorType.
152f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
153f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkAssertResult(fStream->rewind());
154f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
155f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (NULL == decoder.get()) {
156f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
157f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
158f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (fInfo != info) {
159f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        // The caller has specified a different info.  For now, this
160f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        // is an error.  In the future, we will check to see if we can
161f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        // convert.
162f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
163f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
164f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
165f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
166f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
167f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
168f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkBitmap bitmap;
169f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (!bitmap.setConfig(info, rowBytes)) {
170f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
171f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
172f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
173f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    TargetAllocator allocator(pixels, rowBytes, info);
174f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (!fDoCopyTo) {
175f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        decoder->setAllocator(&allocator);
176f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
177f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    bool success = decoder->decode(fStream, &bitmap,
178f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com                                   SkImageDecoder::kDecodePixels_Mode);
179f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    decoder->setAllocator(NULL);
180f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (!success) {
181f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
182f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
183f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if (fDoCopyTo) {
184f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        SkBitmap bm8888;
185f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
186f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
187f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    return true;
1886ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
1899ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.combool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
1909ab9c97883d0a0b7084cbb91eaf1ba6fb4c46affhalcanary@google.com                                       SkDiscardableMemory::Factory* factory) {
1916ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkASSERT(data != NULL);
1926ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkASSERT(dst != NULL);
1936ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com    SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
1946168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com    return SkInstallDiscardablePixelRef(gen, dst, factory);
1956ac702e890656e801469060c1b9474912a5b704ahalcanary@google.com}
196f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com
197f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.combool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
198f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com                                       SkBitmap* dst,
199f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com                                       SkDiscardableMemory::Factory* factory) {
200f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkASSERT(stream != NULL);
201f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkASSERT(dst != NULL);
202f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    if ((stream == NULL) || !stream->unique()) {
203f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        SkSafeUnref(stream);
204f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com        return false;
205f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    }
206f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com    SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
2076168ea7d412448c88169a565f40bf86379d4bf9ahalcanary@google.com    return SkInstallDiscardablePixelRef(gen, dst, factory);
208f2a3af42091738eee3970172d373ec34c5b5c7e1halcanary@google.com}
209