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