Home | History | Annotate | Download | only in images
      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 
     17 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
     18 
     19 SkBitmap::Config SkImageDecoder::GetDeviceConfig()
     20 {
     21     return gDeviceConfig;
     22 }
     23 
     24 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
     25 {
     26     gDeviceConfig = config;
     27 }
     28 
     29 ///////////////////////////////////////////////////////////////////////////////
     30 
     31 SkImageDecoder::SkImageDecoder()
     32     : fPeeker(NULL)
     33     , fChooser(NULL)
     34     , fAllocator(NULL)
     35     , fSampleSize(1)
     36     , fDefaultPref(SkBitmap::kNo_Config)
     37     , fDitherImage(true)
     38     , fUsePrefTable(false)
     39     , fSkipWritingZeroes(false)
     40     , fPreferQualityOverSpeed(false)
     41     , fRequireUnpremultipliedColors(false) {
     42 }
     43 
     44 SkImageDecoder::~SkImageDecoder() {
     45     SkSafeUnref(fPeeker);
     46     SkSafeUnref(fChooser);
     47     SkSafeUnref(fAllocator);
     48 }
     49 
     50 void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
     51     if (NULL == other) {
     52         return;
     53     }
     54     other->setPeeker(fPeeker);
     55     other->setChooser(fChooser);
     56     other->setAllocator(fAllocator);
     57     other->setSampleSize(fSampleSize);
     58     if (fUsePrefTable) {
     59         other->setPrefConfigTable(fPrefTable);
     60     } else {
     61         other->fDefaultPref = fDefaultPref;
     62     }
     63     other->setDitherImage(fDitherImage);
     64     other->setSkipWritingZeroes(fSkipWritingZeroes);
     65     other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
     66     other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
     67 }
     68 
     69 SkImageDecoder::Format SkImageDecoder::getFormat() const {
     70     return kUnknown_Format;
     71 }
     72 
     73 const char* SkImageDecoder::getFormatName() const {
     74     return GetFormatName(this->getFormat());
     75 }
     76 
     77 const char* SkImageDecoder::GetFormatName(Format format) {
     78     switch (format) {
     79         case kUnknown_Format:
     80             return "Unknown Format";
     81         case kBMP_Format:
     82             return "BMP";
     83         case kGIF_Format:
     84             return "GIF";
     85         case kICO_Format:
     86             return "ICO";
     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 
    101 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
    102     SkRefCnt_SafeAssign(fPeeker, peeker);
    103     return peeker;
    104 }
    105 
    106 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
    107     SkRefCnt_SafeAssign(fChooser, chooser);
    108     return chooser;
    109 }
    110 
    111 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
    112     SkRefCnt_SafeAssign(fAllocator, alloc);
    113     return alloc;
    114 }
    115 
    116 void SkImageDecoder::setSampleSize(int size) {
    117     if (size < 1) {
    118         size = 1;
    119     }
    120     fSampleSize = size;
    121 }
    122 
    123 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
    124                                          int height) const {
    125     Chooser* chooser = fChooser;
    126 
    127     if (NULL == chooser) {    // no chooser, we just say YES to decoding :)
    128         return true;
    129     }
    130     chooser->begin(1);
    131     chooser->inspect(0, config, width, height);
    132     return chooser->choose() == 0;
    133 }
    134 
    135 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
    136                                    SkColorTable* ctable) const {
    137     return bitmap->allocPixels(fAllocator, ctable);
    138 }
    139 
    140 ///////////////////////////////////////////////////////////////////////////////
    141 
    142 void SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) {
    143     fUsePrefTable = true;
    144     fPrefTable = prefTable;
    145 }
    146 
    147 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
    148                                                bool srcHasAlpha) const {
    149     SkBitmap::Config config = SkBitmap::kNo_Config;
    150 
    151     if (fUsePrefTable) {
    152         switch (srcDepth) {
    153             case kIndex_SrcDepth:
    154                 config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src
    155                                      : fPrefTable.fPrefFor_8Index_NoAlpha_src;
    156                 break;
    157             case k8BitGray_SrcDepth:
    158                 config = fPrefTable.fPrefFor_8Gray_src;
    159                 break;
    160             case k32Bit_SrcDepth:
    161                 config = srcHasAlpha ? fPrefTable.fPrefFor_8bpc_YesAlpha_src
    162                                      : fPrefTable.fPrefFor_8bpc_NoAlpha_src;
    163                 break;
    164         }
    165     } else {
    166         config = fDefaultPref;
    167     }
    168 
    169     if (SkBitmap::kNo_Config == config) {
    170         config = SkImageDecoder::GetDeviceConfig();
    171     }
    172     return config;
    173 }
    174 
    175 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
    176                             SkBitmap::Config pref, Mode mode) {
    177     // we reset this to false before calling onDecode
    178     fShouldCancelDecode = false;
    179     // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
    180     fDefaultPref = pref;
    181 
    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     if (!this->onDecode(stream, &tmp, mode)) {
    186         return false;
    187     }
    188     bm->swap(tmp);
    189     return true;
    190 }
    191 
    192 bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect,
    193                                   SkBitmap::Config pref) {
    194     // we reset this to false before calling onDecodeSubset
    195     fShouldCancelDecode = false;
    196     // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
    197     fDefaultPref = pref;
    198 
    199     return this->onDecodeSubset(bm, rect);
    200 }
    201 
    202 bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream,
    203                                     int *width, int *height) {
    204     // we reset this to false before calling onBuildTileIndex
    205     fShouldCancelDecode = false;
    206 
    207     return this->onBuildTileIndex(stream, width, height);
    208 }
    209 
    210 bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
    211                                 int dstX, int dstY, int width, int height,
    212                                 int srcX, int srcY) {
    213     int w = width / sampleSize;
    214     int h = height / sampleSize;
    215     if (src->config() == SkBitmap::kIndex8_Config) {
    216         // kIndex8 does not allow drawing via an SkCanvas, as is done below.
    217         // Instead, use extractSubset. Note that this shares the SkPixelRef and
    218         // SkColorTable.
    219         // FIXME: Since src is discarded in practice, this holds on to more
    220         // pixels than is strictly necessary. Switch to a copy if memory
    221         // savings are more important than speed here. This also means
    222         // that the pixels in dst can not be reused (though there is no
    223         // allocation, which was already done on src).
    224         int x = (dstX - srcX) / sampleSize;
    225         int y = (dstY - srcY) / sampleSize;
    226         SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
    227         return src->extractSubset(dst, subset);
    228     }
    229     // if the destination has no pixels then we must allocate them.
    230     if (dst->isNull()) {
    231         dst->setConfig(src->config(), w, h, 0, src->alphaType());
    232 
    233         if (!this->allocPixelRef(dst, NULL)) {
    234             SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
    235             return false;
    236         }
    237     }
    238     // check to see if the destination is large enough to decode the desired
    239     // region. If this assert fails we will just draw as much of the source
    240     // into the destination that we can.
    241     if (dst->width() < w || dst->height() < h) {
    242         SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
    243     }
    244 
    245     // Set the Src_Mode for the paint to prevent transparency issue in the
    246     // dest in the event that the dest was being re-used.
    247     SkPaint paint;
    248     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    249 
    250     SkCanvas canvas(*dst);
    251     canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
    252                             (srcY - dstY) / sampleSize,
    253                             &paint);
    254     return true;
    255 }
    256 
    257 ///////////////////////////////////////////////////////////////////////////////
    258 
    259 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
    260                             SkBitmap::Config pref,  Mode mode, Format* format) {
    261     SkASSERT(file);
    262     SkASSERT(bm);
    263 
    264     SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file));
    265     if (stream.get()) {
    266         if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
    267             bm->pixelRef()->setURI(file);
    268             return true;
    269         }
    270     }
    271     return false;
    272 }
    273 
    274 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
    275                           SkBitmap::Config pref, Mode mode, Format* format) {
    276     if (0 == size) {
    277         return false;
    278     }
    279     SkASSERT(buffer);
    280 
    281     SkMemoryStream  stream(buffer, size);
    282     return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
    283 }
    284 
    285 bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm,
    286                                   SkBitmap::Config pref, Mode mode,
    287                                   Format* format) {
    288     SkASSERT(stream);
    289     SkASSERT(bm);
    290 
    291     bool success = false;
    292     SkImageDecoder* codec = SkImageDecoder::Factory(stream);
    293 
    294     if (NULL != codec) {
    295         success = codec->decode(stream, bm, pref, mode);
    296         if (success && format) {
    297             *format = codec->getFormat();
    298             if (kUnknown_Format == *format) {
    299                 if (stream->rewind()) {
    300                     *format = GetStreamFormat(stream);
    301                 }
    302             }
    303         }
    304         delete codec;
    305     }
    306     return success;
    307 }
    308