1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkImageDecoder.h" 11 #include "SkBitmap.h" 12 #include "SkPixelRef.h" 13 #include "SkStream.h" 14 #include "SkTemplates.h" 15 #include "SkCanvas.h" 16 17 SK_DEFINE_INST_COUNT(SkImageDecoder::Peeker) 18 SK_DEFINE_INST_COUNT(SkImageDecoder::Chooser) 19 SK_DEFINE_INST_COUNT(SkImageDecoderFactory) 20 21 SkVMMemoryReporter::~SkVMMemoryReporter() { 22 } 23 24 const char *SkImageDecoder::kFormatName[] = { 25 "Unknown Format", 26 "BMP", 27 "GIF", 28 "ICO", 29 "JPEG", 30 "PNG", 31 "WBMP", 32 "WEBP", 33 }; 34 35 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config; 36 37 SkBitmap::Config SkImageDecoder::GetDeviceConfig() 38 { 39 return gDeviceConfig; 40 } 41 42 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config) 43 { 44 gDeviceConfig = config; 45 } 46 47 /////////////////////////////////////////////////////////////////////////////// 48 49 SkImageDecoder::SkImageDecoder() 50 : fReporter(NULL), fPeeker(NULL), fChooser(NULL), fAllocator(NULL), 51 fSampleSize(1), fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true), 52 fUsePrefTable(false),fPreferQualityOverSpeed(false) { 53 } 54 55 SkImageDecoder::~SkImageDecoder() { 56 SkSafeUnref(fPeeker); 57 SkSafeUnref(fChooser); 58 SkSafeUnref(fAllocator); 59 SkSafeUnref(fReporter); 60 } 61 62 SkImageDecoder::Format SkImageDecoder::getFormat() const { 63 return kUnknown_Format; 64 } 65 66 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { 67 SkRefCnt_SafeAssign(fPeeker, peeker); 68 return peeker; 69 } 70 71 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { 72 SkRefCnt_SafeAssign(fChooser, chooser); 73 return chooser; 74 } 75 76 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { 77 SkRefCnt_SafeAssign(fAllocator, alloc); 78 return alloc; 79 } 80 81 SkVMMemoryReporter* SkImageDecoder::setReporter(SkVMMemoryReporter* reporter) { 82 SkRefCnt_SafeAssign(fReporter, reporter); 83 return reporter; 84 } 85 86 void SkImageDecoder::setSampleSize(int size) { 87 if (size < 1) { 88 size = 1; 89 } 90 fSampleSize = size; 91 } 92 93 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width, 94 int height) const { 95 Chooser* chooser = fChooser; 96 97 if (NULL == chooser) { // no chooser, we just say YES to decoding :) 98 return true; 99 } 100 chooser->begin(1); 101 chooser->inspect(0, config, width, height); 102 return chooser->choose() == 0; 103 } 104 105 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, 106 SkColorTable* ctable) const { 107 return bitmap->allocPixels(fAllocator, ctable); 108 } 109 110 /////////////////////////////////////////////////////////////////////////////// 111 112 void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) { 113 if (NULL == pref) { 114 fUsePrefTable = false; 115 } else { 116 fUsePrefTable = true; 117 memcpy(fPrefTable, pref, sizeof(fPrefTable)); 118 } 119 } 120 121 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth, 122 bool srcHasAlpha) const { 123 SkBitmap::Config config; 124 125 if (fUsePrefTable) { 126 int index = 0; 127 switch (srcDepth) { 128 case kIndex_SrcDepth: 129 index = 0; 130 break; 131 case k16Bit_SrcDepth: 132 index = 2; 133 break; 134 case k32Bit_SrcDepth: 135 index = 4; 136 break; 137 } 138 if (srcHasAlpha) { 139 index += 1; 140 } 141 config = fPrefTable[index]; 142 } else { 143 config = fDefaultPref; 144 } 145 146 if (SkBitmap::kNo_Config == config) { 147 config = SkImageDecoder::GetDeviceConfig(); 148 } 149 return config; 150 } 151 152 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, 153 SkBitmap::Config pref, Mode mode, bool reuseBitmap) { 154 // pass a temporary bitmap, so that if we return false, we are assured of 155 // leaving the caller's bitmap untouched. 156 SkBitmap tmp; 157 158 // we reset this to false before calling onDecode 159 fShouldCancelDecode = false; 160 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false 161 fDefaultPref = pref; 162 163 if (reuseBitmap) { 164 SkAutoLockPixels alp(*bm); 165 if (bm->getPixels() != NULL) { 166 return this->onDecode(stream, bm, mode); 167 } 168 } 169 if (!this->onDecode(stream, &tmp, mode)) { 170 return false; 171 } 172 bm->swap(tmp); 173 return true; 174 } 175 176 bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect, 177 SkBitmap::Config pref) { 178 // we reset this to false before calling onDecodeRegion 179 fShouldCancelDecode = false; 180 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false 181 fDefaultPref = pref; 182 183 if (!this->onDecodeRegion(bm, rect)) { 184 return false; 185 } 186 return true; 187 } 188 189 bool SkImageDecoder::buildTileIndex(SkStream* stream, 190 int *width, int *height) { 191 // we reset this to false before calling onBuildTileIndex 192 fShouldCancelDecode = false; 193 194 return this->onBuildTileIndex(stream, width, height); 195 } 196 197 void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src, 198 int sampleSize, int destX, int destY, 199 int width, int height, int srcX, int srcY) { 200 int w = width / sampleSize; 201 int h = height / sampleSize; 202 // if the destination has no pixels then we must allocate them. 203 if (dest->isNull()) { 204 dest->setConfig(src->getConfig(), w, h); 205 dest->setIsOpaque(src->isOpaque()); 206 207 if (!this->allocPixelRef(dest, NULL)) { 208 SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); 209 return; 210 } 211 } 212 // check to see if the destination is large enough to decode the desired 213 // region. If this assert fails we will just draw as much of the source 214 // into the destination that we can. 215 SkASSERT(dest->width() >= w && dest->height() >= h); 216 217 // Set the Src_Mode for the paint to prevent transparency issue in the 218 // dest in the event that the dest was being re-used. 219 SkPaint paint; 220 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 221 222 SkCanvas canvas(*dest); 223 canvas.drawSprite(*src, (srcX - destX) / sampleSize, 224 (srcY - destY) / sampleSize, 225 &paint); 226 } 227 228 /////////////////////////////////////////////////////////////////////////////// 229 230 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, 231 SkBitmap::Config pref, Mode mode, Format* format) { 232 SkASSERT(file); 233 SkASSERT(bm); 234 235 SkFILEStream stream(file); 236 if (stream.isValid()) { 237 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) { 238 bm->pixelRef()->setURI(file); 239 return true; 240 } 241 } 242 return false; 243 } 244 245 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, 246 SkBitmap::Config pref, Mode mode, Format* format) { 247 if (0 == size) { 248 return false; 249 } 250 SkASSERT(buffer); 251 252 SkMemoryStream stream(buffer, size); 253 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); 254 } 255 256 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, 257 SkBitmap::Config pref, Mode mode, Format* format) { 258 SkASSERT(stream); 259 SkASSERT(bm); 260 261 bool success = false; 262 SkImageDecoder* codec = SkImageDecoder::Factory(stream); 263 264 if (NULL != codec) { 265 success = codec->decode(stream, bm, pref, mode); 266 if (success && format) { 267 *format = codec->getFormat(); 268 } 269 delete codec; 270 } 271 return success; 272 } 273