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