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