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