Home | History | Annotate | Download | only in images
      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