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