1 /* 2 * Copyright 2006 The Android Open Source Project 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 9 #include "SkImageDecoder.h" 10 #include "SkBitmap.h" 11 #include "SkImagePriv.h" 12 #include "SkPixelRef.h" 13 #include "SkStream.h" 14 #include "SkTemplates.h" 15 #include "SkCanvas.h" 16 17 SkImageDecoder::SkImageDecoder() 18 : fPeeker(NULL) 19 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 20 , fChooser(NULL) 21 #endif 22 , fAllocator(NULL) 23 , fSampleSize(1) 24 , fDefaultPref(kUnknown_SkColorType) 25 , fDitherImage(true) 26 #ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 27 , fUsePrefTable(false) 28 #endif 29 , fSkipWritingZeroes(false) 30 , fPreferQualityOverSpeed(false) 31 , fRequireUnpremultipliedColors(false) { 32 } 33 34 SkImageDecoder::~SkImageDecoder() { 35 SkSafeUnref(fPeeker); 36 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 37 SkSafeUnref(fChooser); 38 #endif 39 SkSafeUnref(fAllocator); 40 } 41 42 void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) { 43 if (NULL == other) { 44 return; 45 } 46 other->setPeeker(fPeeker); 47 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 48 other->setChooser(fChooser); 49 #endif 50 other->setAllocator(fAllocator); 51 other->setSampleSize(fSampleSize); 52 #ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 53 if (fUsePrefTable) { 54 other->setPrefConfigTable(fPrefTable); 55 } else { 56 other->fDefaultPref = fDefaultPref; 57 } 58 #endif 59 other->setDitherImage(fDitherImage); 60 other->setSkipWritingZeroes(fSkipWritingZeroes); 61 other->setPreferQualityOverSpeed(fPreferQualityOverSpeed); 62 other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors); 63 } 64 65 SkImageDecoder::Format SkImageDecoder::getFormat() const { 66 return kUnknown_Format; 67 } 68 69 const char* SkImageDecoder::getFormatName() const { 70 return GetFormatName(this->getFormat()); 71 } 72 73 const char* SkImageDecoder::GetFormatName(Format format) { 74 switch (format) { 75 case kUnknown_Format: 76 return "Unknown Format"; 77 case kBMP_Format: 78 return "BMP"; 79 case kGIF_Format: 80 return "GIF"; 81 case kICO_Format: 82 return "ICO"; 83 case kPKM_Format: 84 return "PKM"; 85 case kKTX_Format: 86 return "KTX"; 87 case kJPEG_Format: 88 return "JPEG"; 89 case kPNG_Format: 90 return "PNG"; 91 case kWBMP_Format: 92 return "WBMP"; 93 case kWEBP_Format: 94 return "WEBP"; 95 default: 96 SkDEBUGFAIL("Invalid format type!"); 97 } 98 return "Unknown Format"; 99 } 100 101 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { 102 SkRefCnt_SafeAssign(fPeeker, peeker); 103 return peeker; 104 } 105 106 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 107 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { 108 SkRefCnt_SafeAssign(fChooser, chooser); 109 return chooser; 110 } 111 #endif 112 113 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { 114 SkRefCnt_SafeAssign(fAllocator, alloc); 115 return alloc; 116 } 117 118 void SkImageDecoder::setSampleSize(int size) { 119 if (size < 1) { 120 size = 1; 121 } 122 fSampleSize = size; 123 } 124 125 #ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 126 // TODO: change Chooser virtual to take colorType, so we can stop calling SkColorTypeToBitmapConfig 127 // 128 bool SkImageDecoder::chooseFromOneChoice(SkColorType colorType, int width, int height) const { 129 Chooser* chooser = fChooser; 130 131 if (NULL == chooser) { // no chooser, we just say YES to decoding :) 132 return true; 133 } 134 chooser->begin(1); 135 chooser->inspect(0, SkColorTypeToBitmapConfig(colorType), width, height); 136 return chooser->choose() == 0; 137 } 138 #endif 139 140 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, 141 SkColorTable* ctable) const { 142 return bitmap->allocPixels(fAllocator, ctable); 143 } 144 145 /////////////////////////////////////////////////////////////////////////////// 146 147 #ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 148 void SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) { 149 fUsePrefTable = true; 150 fPrefTable = prefTable; 151 } 152 #endif 153 154 // TODO: use colortype in fPrefTable, fDefaultPref so we can stop using SkBitmapConfigToColorType() 155 // 156 SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const { 157 SkColorType ct = fDefaultPref; 158 #ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG 159 160 if (fUsePrefTable) { 161 // Until we kill or change the PrefTable, we have to go into Config land for a moment. 162 SkBitmap::Config config = SkBitmap::kNo_Config; 163 switch (srcDepth) { 164 case kIndex_SrcDepth: 165 config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src 166 : fPrefTable.fPrefFor_8Index_NoAlpha_src; 167 break; 168 case k8BitGray_SrcDepth: 169 config = fPrefTable.fPrefFor_8Gray_src; 170 break; 171 case k32Bit_SrcDepth: 172 config = srcHasAlpha ? fPrefTable.fPrefFor_8bpc_YesAlpha_src 173 : fPrefTable.fPrefFor_8bpc_NoAlpha_src; 174 break; 175 } 176 // now return to SkColorType land 177 ct = SkBitmapConfigToColorType(config); 178 } 179 #endif 180 return ct; 181 } 182 183 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, Mode mode) { 184 // we reset this to false before calling onDecode 185 fShouldCancelDecode = false; 186 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 187 fDefaultPref = pref; 188 189 // pass a temporary bitmap, so that if we return false, we are assured of 190 // leaving the caller's bitmap untouched. 191 SkBitmap tmp; 192 if (!this->onDecode(stream, &tmp, mode)) { 193 return false; 194 } 195 bm->swap(tmp); 196 return true; 197 } 198 199 bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) { 200 // we reset this to false before calling onDecodeSubset 201 fShouldCancelDecode = false; 202 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 203 fDefaultPref = pref; 204 205 return this->onDecodeSubset(bm, rect); 206 } 207 208 bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) { 209 // we reset this to false before calling onBuildTileIndex 210 fShouldCancelDecode = false; 211 212 return this->onBuildTileIndex(stream, width, height); 213 } 214 215 bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, 216 int dstX, int dstY, int width, int height, 217 int srcX, int srcY) { 218 int w = width / sampleSize; 219 int h = height / sampleSize; 220 if (src->colorType() == kIndex_8_SkColorType) { 221 // kIndex8 does not allow drawing via an SkCanvas, as is done below. 222 // Instead, use extractSubset. Note that this shares the SkPixelRef and 223 // SkColorTable. 224 // FIXME: Since src is discarded in practice, this holds on to more 225 // pixels than is strictly necessary. Switch to a copy if memory 226 // savings are more important than speed here. This also means 227 // that the pixels in dst can not be reused (though there is no 228 // allocation, which was already done on src). 229 int x = (dstX - srcX) / sampleSize; 230 int y = (dstY - srcY) / sampleSize; 231 SkIRect subset = SkIRect::MakeXYWH(x, y, w, h); 232 return src->extractSubset(dst, subset); 233 } 234 // if the destination has no pixels then we must allocate them. 235 if (dst->isNull()) { 236 dst->setInfo(src->info().makeWH(w, h)); 237 238 if (!this->allocPixelRef(dst, NULL)) { 239 SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); 240 return false; 241 } 242 } 243 // check to see if the destination is large enough to decode the desired 244 // region. If this assert fails we will just draw as much of the source 245 // into the destination that we can. 246 if (dst->width() < w || dst->height() < h) { 247 SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n")); 248 } 249 250 // Set the Src_Mode for the paint to prevent transparency issue in the 251 // dest in the event that the dest was being re-used. 252 SkPaint paint; 253 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 254 255 SkCanvas canvas(*dst); 256 canvas.drawSprite(*src, (srcX - dstX) / sampleSize, 257 (srcY - dstY) / sampleSize, 258 &paint); 259 return true; 260 } 261 262 /////////////////////////////////////////////////////////////////////////////// 263 264 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode, 265 Format* format) { 266 SkASSERT(file); 267 SkASSERT(bm); 268 269 SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file)); 270 if (stream.get()) { 271 if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) { 272 bm->pixelRef()->setURI(file); 273 return true; 274 } 275 } 276 return false; 277 } 278 279 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref, 280 Mode mode, Format* format) { 281 if (0 == size) { 282 return false; 283 } 284 SkASSERT(buffer); 285 286 SkMemoryStream stream(buffer, size); 287 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); 288 } 289 290 bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref, 291 Mode mode, Format* format) { 292 SkASSERT(stream); 293 SkASSERT(bm); 294 295 bool success = false; 296 SkImageDecoder* codec = SkImageDecoder::Factory(stream); 297 298 if (NULL != codec) { 299 success = codec->decode(stream, bm, pref, mode); 300 if (success && format) { 301 *format = codec->getFormat(); 302 if (kUnknown_Format == *format) { 303 if (stream->rewind()) { 304 *format = GetStreamFormat(stream); 305 } 306 } 307 } 308 delete codec; 309 } 310 return success; 311 } 312