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 17SkImageDecoder::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 34SkImageDecoder::~SkImageDecoder() { 35 SkSafeUnref(fPeeker); 36#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 37 SkSafeUnref(fChooser); 38#endif 39 SkSafeUnref(fAllocator); 40} 41 42void 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 65SkImageDecoder::Format SkImageDecoder::getFormat() const { 66 return kUnknown_Format; 67} 68 69const char* SkImageDecoder::getFormatName() const { 70 return GetFormatName(this->getFormat()); 71} 72 73const 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 101SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { 102 SkRefCnt_SafeAssign(fPeeker, peeker); 103 return peeker; 104} 105 106#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER 107SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { 108 SkRefCnt_SafeAssign(fChooser, chooser); 109 return chooser; 110} 111#endif 112 113SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { 114 SkRefCnt_SafeAssign(fAllocator, alloc); 115 return alloc; 116} 117 118void 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// 128bool 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 140bool 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 148void 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// 156SkColorType 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 183SkImageDecoder::Result SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, 184 Mode mode) { 185 // we reset this to false before calling onDecode 186 fShouldCancelDecode = false; 187 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 188 fDefaultPref = pref; 189 190 // pass a temporary bitmap, so that if we return false, we are assured of 191 // leaving the caller's bitmap untouched. 192 SkBitmap tmp; 193 const Result result = this->onDecode(stream, &tmp, mode); 194 if (kFailure != result) { 195 bm->swap(tmp); 196 } 197 return result; 198} 199 200bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) { 201 // we reset this to false before calling onDecodeSubset 202 fShouldCancelDecode = false; 203 // assign this, for use by getPrefColorType(), in case fUsePrefTable is false 204 fDefaultPref = pref; 205 206 return this->onDecodeSubset(bm, rect); 207} 208 209bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) { 210 // we reset this to false before calling onBuildTileIndex 211 fShouldCancelDecode = false; 212 213 return this->onBuildTileIndex(stream, width, height); 214} 215 216bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, 217 int dstX, int dstY, int width, int height, 218 int srcX, int srcY) { 219 int w = width / sampleSize; 220 int h = height / sampleSize; 221 if (src->colorType() == kIndex_8_SkColorType) { 222 // kIndex8 does not allow drawing via an SkCanvas, as is done below. 223 // Instead, use extractSubset. Note that this shares the SkPixelRef and 224 // SkColorTable. 225 // FIXME: Since src is discarded in practice, this holds on to more 226 // pixels than is strictly necessary. Switch to a copy if memory 227 // savings are more important than speed here. This also means 228 // that the pixels in dst can not be reused (though there is no 229 // allocation, which was already done on src). 230 int x = (dstX - srcX) / sampleSize; 231 int y = (dstY - srcY) / sampleSize; 232 SkIRect subset = SkIRect::MakeXYWH(x, y, w, h); 233 return src->extractSubset(dst, subset); 234 } 235 // if the destination has no pixels then we must allocate them. 236 if (dst->isNull()) { 237 dst->setInfo(src->info().makeWH(w, h)); 238 239 if (!this->allocPixelRef(dst, NULL)) { 240 SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); 241 return false; 242 } 243 } 244 // check to see if the destination is large enough to decode the desired 245 // region. If this assert fails we will just draw as much of the source 246 // into the destination that we can. 247 if (dst->width() < w || dst->height() < h) { 248 SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n")); 249 } 250 251 // Set the Src_Mode for the paint to prevent transparency issue in the 252 // dest in the event that the dest was being re-used. 253 SkPaint paint; 254 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 255 256 SkCanvas canvas(*dst); 257 canvas.drawSprite(*src, (srcX - dstX) / sampleSize, 258 (srcY - dstY) / sampleSize, 259 &paint); 260 return true; 261} 262 263/////////////////////////////////////////////////////////////////////////////// 264 265bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode, 266 Format* format) { 267 SkASSERT(file); 268 SkASSERT(bm); 269 270 SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file)); 271 if (stream.get()) { 272 if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) { 273 bm->pixelRef()->setURI(file); 274 return true; 275 } 276 } 277 return false; 278} 279 280bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref, 281 Mode mode, Format* format) { 282 if (0 == size) { 283 return false; 284 } 285 SkASSERT(buffer); 286 287 SkMemoryStream stream(buffer, size); 288 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); 289} 290 291bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref, 292 Mode mode, Format* format) { 293 SkASSERT(stream); 294 SkASSERT(bm); 295 296 bool success = false; 297 SkImageDecoder* codec = SkImageDecoder::Factory(stream); 298 299 if (NULL != codec) { 300 success = codec->decode(stream, bm, pref, mode); 301 if (success && format) { 302 *format = codec->getFormat(); 303 if (kUnknown_Format == *format) { 304 if (stream->rewind()) { 305 *format = GetStreamFormat(stream); 306 } 307 } 308 } 309 delete codec; 310 } 311 return success; 312} 313