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 "SkData.h" 9 #include "SkDecodingImageGenerator.h" 10 #include "SkImageDecoder.h" 11 #include "SkImageInfo.h" 12 #include "SkImageGenerator.h" 13 #include "SkImagePriv.h" 14 #include "SkStream.h" 15 #include "SkUtils.h" 16 17 namespace { 18 bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) { 19 return a.width() == b.width() && a.height() == b.height() && 20 a.colorType() == b.colorType(); 21 } 22 23 class DecodingImageGenerator : public SkImageGenerator { 24 public: 25 virtual ~DecodingImageGenerator(); 26 27 SkData* fData; 28 SkAutoTDelete<SkStreamRewindable> fStream; 29 const SkImageInfo fInfo; 30 const int fSampleSize; 31 const bool fDitherImage; 32 33 DecodingImageGenerator(SkData* data, 34 SkStreamRewindable* stream, 35 const SkImageInfo& info, 36 int sampleSize, 37 bool ditherImage); 38 39 protected: 40 SkData* onRefEncodedData() override; 41 Result onGetPixels(const SkImageInfo& info, 42 void* pixels, size_t rowBytes, const Options&, 43 SkPMColor ctable[], int* ctableCount) override; 44 bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3], 45 SkYUVColorSpace* colorSpace) override; 46 47 private: 48 typedef SkImageGenerator INHERITED; 49 }; 50 51 /** 52 * Special allocator used by getPixels(). Uses preallocated memory 53 * provided if possible, else fall-back on the default allocator 54 */ 55 class TargetAllocator : public SkBitmap::Allocator { 56 public: 57 TargetAllocator(const SkImageInfo& info, 58 void* target, 59 size_t rowBytes) 60 : fInfo(info) 61 , fTarget(target) 62 , fRowBytes(rowBytes) 63 {} 64 65 bool isReady() { return (fTarget != NULL); } 66 67 virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) { 68 if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) { 69 // Call default allocator. 70 return bm->tryAllocPixels(NULL, ct); 71 } 72 73 // TODO(halcanary): verify that all callers of this function 74 // will respect new RowBytes. Will be moot once rowbytes belongs 75 // to PixelRef. 76 bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL); 77 78 fTarget = NULL; // never alloc same pixels twice! 79 return true; 80 } 81 82 private: 83 const SkImageInfo fInfo; 84 void* fTarget; // Block of memory to be supplied as pixel memory 85 // in allocPixelRef. Must be large enough to hold 86 // a bitmap described by fInfo and fRowBytes 87 const size_t fRowBytes; // rowbytes for the destination bitmap 88 89 typedef SkBitmap::Allocator INHERITED; 90 }; 91 92 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h 93 #ifdef SK_DEBUG 94 #define SkCheckResult(expr, value) SkASSERT((value) == (expr)) 95 #else 96 #define SkCheckResult(expr, value) (void)(expr) 97 #endif 98 99 #ifdef SK_DEBUG 100 inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) { 101 return ((reported == actual) 102 || ((reported == kPremul_SkAlphaType) 103 && (actual == kOpaque_SkAlphaType))); 104 } 105 #endif // SK_DEBUG 106 107 //////////////////////////////////////////////////////////////////////////////// 108 109 DecodingImageGenerator::DecodingImageGenerator( 110 SkData* data, 111 SkStreamRewindable* stream, 112 const SkImageInfo& info, 113 int sampleSize, 114 bool ditherImage) 115 : INHERITED(info) 116 , fData(data) 117 , fStream(stream) 118 , fInfo(info) 119 , fSampleSize(sampleSize) 120 , fDitherImage(ditherImage) 121 { 122 SkASSERT(stream != NULL); 123 SkSafeRef(fData); // may be NULL. 124 } 125 126 DecodingImageGenerator::~DecodingImageGenerator() { 127 SkSafeUnref(fData); 128 } 129 130 SkData* DecodingImageGenerator::onRefEncodedData() { 131 // This functionality is used in `gm --serialize` 132 // Does not encode options. 133 if (NULL == fData) { 134 // TODO(halcanary): SkStreamRewindable needs a refData() function 135 // which returns a cheap copy of the underlying data. 136 if (!fStream->rewind()) { 137 return NULL; 138 } 139 size_t length = fStream->getLength(); 140 if (length) { 141 fData = SkData::NewFromStream(fStream, length); 142 } 143 } 144 return SkSafeRef(fData); 145 } 146 147 SkImageGenerator::Result DecodingImageGenerator::onGetPixels(const SkImageInfo& info, 148 void* pixels, size_t rowBytes, const Options& options, SkPMColor ctableEntries[], 149 int* ctableCount) { 150 if (fInfo != info) { 151 // The caller has specified a different info. This is an 152 // error for this kind of SkImageGenerator. Use the Options 153 // to change the settings. 154 if (info.dimensions() != fInfo.dimensions()) { 155 return kInvalidScale; 156 } 157 return kInvalidConversion; 158 } 159 160 SkAssertResult(fStream->rewind()); 161 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); 162 if (NULL == decoder.get()) { 163 return kInvalidInput; 164 } 165 decoder->setDitherImage(fDitherImage); 166 decoder->setSampleSize(fSampleSize); 167 decoder->setRequireUnpremultipliedColors(info.alphaType() == kUnpremul_SkAlphaType); 168 169 SkBitmap bitmap; 170 TargetAllocator allocator(fInfo, pixels, rowBytes); 171 decoder->setAllocator(&allocator); 172 const SkImageDecoder::Result decodeResult = decoder->decode(fStream, &bitmap, info.colorType(), 173 SkImageDecoder::kDecodePixels_Mode); 174 decoder->setAllocator(NULL); 175 if (SkImageDecoder::kFailure == decodeResult) { 176 return kInvalidInput; 177 } 178 if (allocator.isReady()) { // Did not use pixels! 179 SkBitmap bm; 180 SkASSERT(bitmap.canCopyTo(info.colorType())); 181 bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator); 182 if (!copySuccess || allocator.isReady()) { 183 SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed."); 184 // Earlier we checked canCopyto(); we expect consistency. 185 return kInvalidConversion; 186 } 187 SkASSERT(check_alpha(info.alphaType(), bm.alphaType())); 188 } else { 189 SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType())); 190 } 191 192 if (kIndex_8_SkColorType == info.colorType()) { 193 if (kIndex_8_SkColorType != bitmap.colorType()) { 194 // they asked for Index8, but we didn't receive that from decoder 195 return kInvalidConversion; 196 } 197 SkColorTable* ctable = bitmap.getColorTable(); 198 if (NULL == ctable) { 199 return kInvalidConversion; 200 } 201 const int count = ctable->count(); 202 memcpy(ctableEntries, ctable->readColors(), count * sizeof(SkPMColor)); 203 *ctableCount = count; 204 } 205 if (SkImageDecoder::kPartialSuccess == decodeResult) { 206 return kIncompleteInput; 207 } 208 return kSuccess; 209 } 210 211 bool DecodingImageGenerator::onGetYUV8Planes(SkISize sizes[3], void* planes[3], 212 size_t rowBytes[3], SkYUVColorSpace* colorSpace) { 213 if (!fStream->rewind()) { 214 return false; 215 } 216 217 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); 218 if (NULL == decoder.get()) { 219 return false; 220 } 221 222 return decoder->decodeYUV8Planes(fStream, sizes, planes, rowBytes, colorSpace); 223 } 224 225 // A contructor-type function that returns NULL on failure. This 226 // prevents the returned SkImageGenerator from ever being in a bad 227 // state. Called by both Create() functions 228 SkImageGenerator* CreateDecodingImageGenerator( 229 SkData* data, 230 SkStreamRewindable* stream, 231 const SkDecodingImageGenerator::Options& opts) { 232 SkASSERT(stream); 233 SkAutoTDelete<SkStreamRewindable> autoStream(stream); // always delete this 234 SkAssertResult(autoStream->rewind()); 235 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream)); 236 if (NULL == decoder.get()) { 237 return NULL; 238 } 239 SkBitmap bitmap; 240 decoder->setSampleSize(opts.fSampleSize); 241 decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul); 242 if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) { 243 return NULL; 244 } 245 if (kUnknown_SkColorType == bitmap.colorType()) { 246 return NULL; 247 } 248 249 SkImageInfo info = bitmap.info(); 250 251 if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) { 252 if (!bitmap.canCopyTo(opts.fRequestedColorType)) { 253 SkASSERT(bitmap.colorType() != opts.fRequestedColorType); 254 return NULL; // Can not translate to needed config. 255 } 256 info = info.makeColorType(opts.fRequestedColorType); 257 } 258 259 if (opts.fRequireUnpremul && info.alphaType() != kOpaque_SkAlphaType) { 260 info = info.makeAlphaType(kUnpremul_SkAlphaType); 261 } 262 263 SkAlphaType newAlphaType = info.alphaType(); 264 if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType)) { 265 return NULL; 266 } 267 268 return SkNEW_ARGS(DecodingImageGenerator, 269 (data, autoStream.detach(), info.makeAlphaType(newAlphaType), 270 opts.fSampleSize, opts.fDitherImage)); 271 } 272 273 } // namespace 274 275 //////////////////////////////////////////////////////////////////////////////// 276 277 SkImageGenerator* SkDecodingImageGenerator::Create( 278 SkData* data, 279 const SkDecodingImageGenerator::Options& opts) { 280 SkASSERT(data != NULL); 281 if (NULL == data) { 282 return NULL; 283 } 284 SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data)); 285 SkASSERT(stream != NULL); 286 return CreateDecodingImageGenerator(data, stream, opts); 287 } 288 289 SkImageGenerator* SkDecodingImageGenerator::Create( 290 SkStreamRewindable* stream, 291 const SkDecodingImageGenerator::Options& opts) { 292 SkASSERT(stream != NULL); 293 if (stream == NULL) { 294 return NULL; 295 } 296 return CreateDecodingImageGenerator(NULL, stream, opts); 297 } 298