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 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, Mode mode) {
    184     // we reset this to false before calling onDecode
    185     fShouldCancelDecode = false;
    186     // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
    187     fDefaultPref = pref;
    188 
    189     // pass a temporary bitmap, so that if we return false, we are assured of
    190     // leaving the caller's bitmap untouched.
    191     SkBitmap    tmp;
    192     if (!this->onDecode(stream, &tmp, mode)) {
    193         return false;
    194     }
    195     bm->swap(tmp);
    196     return true;
    197 }
    198 
    199 bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) {
    200     // we reset this to false before calling onDecodeSubset
    201     fShouldCancelDecode = false;
    202     // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
    203     fDefaultPref = pref;
    204 
    205     return this->onDecodeSubset(bm, rect);
    206 }
    207 
    208 bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
    209     // we reset this to false before calling onBuildTileIndex
    210     fShouldCancelDecode = false;
    211 
    212     return this->onBuildTileIndex(stream, width, height);
    213 }
    214 
    215 bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
    216                                 int dstX, int dstY, int width, int height,
    217                                 int srcX, int srcY) {
    218     int w = width / sampleSize;
    219     int h = height / sampleSize;
    220     if (src->colorType() == kIndex_8_SkColorType) {
    221         // kIndex8 does not allow drawing via an SkCanvas, as is done below.
    222         // Instead, use extractSubset. Note that this shares the SkPixelRef and
    223         // SkColorTable.
    224         // FIXME: Since src is discarded in practice, this holds on to more
    225         // pixels than is strictly necessary. Switch to a copy if memory
    226         // savings are more important than speed here. This also means
    227         // that the pixels in dst can not be reused (though there is no
    228         // allocation, which was already done on src).
    229         int x = (dstX - srcX) / sampleSize;
    230         int y = (dstY - srcY) / sampleSize;
    231         SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
    232         return src->extractSubset(dst, subset);
    233     }
    234     // if the destination has no pixels then we must allocate them.
    235     if (dst->isNull()) {
    236         dst->setInfo(src->info().makeWH(w, h));
    237 
    238         if (!this->allocPixelRef(dst, NULL)) {
    239             SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
    240             return false;
    241         }
    242     }
    243     // check to see if the destination is large enough to decode the desired
    244     // region. If this assert fails we will just draw as much of the source
    245     // into the destination that we can.
    246     if (dst->width() < w || dst->height() < h) {
    247         SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
    248     }
    249 
    250     // Set the Src_Mode for the paint to prevent transparency issue in the
    251     // dest in the event that the dest was being re-used.
    252     SkPaint paint;
    253     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    254 
    255     SkCanvas canvas(*dst);
    256     canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
    257                             (srcY - dstY) / sampleSize,
    258                             &paint);
    259     return true;
    260 }
    261 
    262 ///////////////////////////////////////////////////////////////////////////////
    263 
    264 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref,  Mode mode,
    265                                 Format* format) {
    266     SkASSERT(file);
    267     SkASSERT(bm);
    268 
    269     SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file));
    270     if (stream.get()) {
    271         if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
    272             bm->pixelRef()->setURI(file);
    273             return true;
    274         }
    275     }
    276     return false;
    277 }
    278 
    279 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref,
    280                                   Mode mode, Format* format) {
    281     if (0 == size) {
    282         return false;
    283     }
    284     SkASSERT(buffer);
    285 
    286     SkMemoryStream  stream(buffer, size);
    287     return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
    288 }
    289 
    290 bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref,
    291                                   Mode mode, Format* format) {
    292     SkASSERT(stream);
    293     SkASSERT(bm);
    294 
    295     bool success = false;
    296     SkImageDecoder* codec = SkImageDecoder::Factory(stream);
    297 
    298     if (NULL != codec) {
    299         success = codec->decode(stream, bm, pref, mode);
    300         if (success && format) {
    301             *format = codec->getFormat();
    302             if (kUnknown_Format == *format) {
    303                 if (stream->rewind()) {
    304                     *format = GetStreamFormat(stream);
    305                 }
    306             }
    307         }
    308         delete codec;
    309     }
    310     return success;
    311 }
    312