1 /* libs/graphics/images/SkImageDecoder.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkImageDecoder.h" 19 #include "SkBitmap.h" 20 #include "SkPixelRef.h" 21 #include "SkStream.h" 22 #include "SkTemplates.h" 23 #include "SkCanvas.h" 24 25 SkVMMemoryReporter::~SkVMMemoryReporter() { 26 } 27 28 const char *SkImageDecoder::kFormatName[] = { 29 "Unknown Format", 30 "BMP", 31 "GIF", 32 "ICO", 33 "JPEG", 34 "PNG", 35 "WBMP", 36 "WEBP", 37 }; 38 39 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config; 40 41 SkBitmap::Config SkImageDecoder::GetDeviceConfig() 42 { 43 return gDeviceConfig; 44 } 45 46 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config) 47 { 48 gDeviceConfig = config; 49 } 50 51 /////////////////////////////////////////////////////////////////////////////// 52 53 SkImageDecoder::SkImageDecoder() 54 : fReporter(NULL), fPeeker(NULL), fChooser(NULL), fAllocator(NULL), 55 fSampleSize(1), fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true), 56 fUsePrefTable(false) { 57 } 58 59 SkImageDecoder::~SkImageDecoder() { 60 SkSafeUnref(fPeeker); 61 SkSafeUnref(fChooser); 62 SkSafeUnref(fAllocator); 63 SkSafeUnref(fReporter); 64 } 65 66 SkImageDecoder::Format SkImageDecoder::getFormat() const { 67 return kUnknown_Format; 68 } 69 70 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { 71 SkRefCnt_SafeAssign(fPeeker, peeker); 72 return peeker; 73 } 74 75 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { 76 SkRefCnt_SafeAssign(fChooser, chooser); 77 return chooser; 78 } 79 80 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { 81 SkRefCnt_SafeAssign(fAllocator, alloc); 82 return alloc; 83 } 84 85 SkVMMemoryReporter* SkImageDecoder::setReporter(SkVMMemoryReporter* reporter) { 86 SkRefCnt_SafeAssign(fReporter, reporter); 87 return reporter; 88 } 89 90 void SkImageDecoder::setSampleSize(int size) { 91 if (size < 1) { 92 size = 1; 93 } 94 fSampleSize = size; 95 } 96 97 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width, 98 int height) const { 99 Chooser* chooser = fChooser; 100 101 if (NULL == chooser) { // no chooser, we just say YES to decoding :) 102 return true; 103 } 104 chooser->begin(1); 105 chooser->inspect(0, config, width, height); 106 return chooser->choose() == 0; 107 } 108 109 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, 110 SkColorTable* ctable) const { 111 return bitmap->allocPixels(fAllocator, ctable); 112 } 113 114 /////////////////////////////////////////////////////////////////////////////// 115 116 void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) { 117 if (NULL == pref) { 118 fUsePrefTable = false; 119 } else { 120 fUsePrefTable = true; 121 memcpy(fPrefTable, pref, sizeof(fPrefTable)); 122 } 123 } 124 125 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth, 126 bool srcHasAlpha) const { 127 SkBitmap::Config config; 128 129 if (fUsePrefTable) { 130 int index = 0; 131 switch (srcDepth) { 132 case kIndex_SrcDepth: 133 index = 0; 134 break; 135 case k16Bit_SrcDepth: 136 index = 2; 137 break; 138 case k32Bit_SrcDepth: 139 index = 4; 140 break; 141 } 142 if (srcHasAlpha) { 143 index += 1; 144 } 145 config = fPrefTable[index]; 146 } else { 147 config = fDefaultPref; 148 } 149 150 if (SkBitmap::kNo_Config == config) { 151 config = SkImageDecoder::GetDeviceConfig(); 152 } 153 return config; 154 } 155 156 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, 157 SkBitmap::Config pref, Mode mode, bool reuseBitmap) { 158 // pass a temporary bitmap, so that if we return false, we are assured of 159 // leaving the caller's bitmap untouched. 160 SkBitmap tmp; 161 162 // we reset this to false before calling onDecode 163 fShouldCancelDecode = false; 164 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false 165 fDefaultPref = pref; 166 167 if (reuseBitmap) { 168 SkAutoLockPixels alp(*bm); 169 if (bm->getPixels() != NULL) { 170 return this->onDecode(stream, bm, mode); 171 } 172 } 173 if (!this->onDecode(stream, &tmp, mode)) { 174 return false; 175 } 176 bm->swap(tmp); 177 return true; 178 } 179 180 bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect, 181 SkBitmap::Config pref) { 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 186 // we reset this to false before calling onDecodeRegion 187 fShouldCancelDecode = false; 188 // assign this, for use by getPrefConfig(), in case fUsePrefTable is false 189 fDefaultPref = pref; 190 191 if (!this->onDecodeRegion(&tmp, rect)) { 192 return false; 193 } 194 bm->swap(tmp); 195 return true; 196 } 197 198 bool SkImageDecoder::buildTileIndex(SkStream* stream, 199 int *width, int *height) { 200 // we reset this to false before calling onBuildTileIndex 201 fShouldCancelDecode = false; 202 203 return this->onBuildTileIndex(stream, width, height); 204 } 205 206 void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src, 207 int sampleSize, int destX, int destY, 208 int width, int height, int srcX, int srcY) { 209 int w = width / sampleSize; 210 int h = height / sampleSize; 211 if (w == src->width() && h == src->height() && 212 (srcX - destX) / sampleSize == 0 && (srcY - destY) / sampleSize == 0) { 213 // The output rect is the same as the decode result 214 dest->swap(*src); 215 return; 216 } 217 dest->setConfig(src->getConfig(), w, h); 218 dest->setIsOpaque(src->isOpaque()); 219 this->allocPixelRef(dest, NULL); 220 221 SkCanvas canvas(*dest); 222 canvas.drawBitmap(*src, (srcX - destX) / sampleSize, 223 (srcY - destY) / sampleSize); 224 } 225 226 /////////////////////////////////////////////////////////////////////////////// 227 228 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, 229 SkBitmap::Config pref, Mode mode, Format* format) { 230 SkASSERT(file); 231 SkASSERT(bm); 232 233 SkFILEStream stream(file); 234 if (stream.isValid()) { 235 if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) { 236 bm->pixelRef()->setURI(file); 237 } 238 return true; 239 } 240 return false; 241 } 242 243 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, 244 SkBitmap::Config pref, Mode mode, Format* format) { 245 if (0 == size) { 246 return false; 247 } 248 SkASSERT(buffer); 249 250 SkMemoryStream stream(buffer, size); 251 return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); 252 } 253 254 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, 255 SkBitmap::Config pref, Mode mode, Format* format) { 256 SkASSERT(stream); 257 SkASSERT(bm); 258 259 bool success = false; 260 SkImageDecoder* codec = SkImageDecoder::Factory(stream); 261 262 if (NULL != codec) { 263 success = codec->decode(stream, bm, pref, mode); 264 if (success && format) { 265 *format = codec->getFormat(); 266 } 267 delete codec; 268 } 269 return success; 270 } 271