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