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     , fAllocator(NULL)
     20     , fSampleSize(1)
     21     , fDefaultPref(kUnknown_SkColorType)
     22     , fPreserveSrcDepth(false)
     23     , fDitherImage(true)
     24     , fSkipWritingZeroes(false)
     25     , fPreferQualityOverSpeed(false)
     26     , fRequireUnpremultipliedColors(false) {
     27 }
     28 
     29 SkImageDecoder::~SkImageDecoder() {
     30     SkSafeUnref(fPeeker);
     31     SkSafeUnref(fAllocator);
     32 }
     33 
     34 void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) {
     35     if (NULL == other) {
     36         return;
     37     }
     38     other->setPeeker(fPeeker);
     39     other->setAllocator(fAllocator);
     40     other->setSampleSize(fSampleSize);
     41     other->setPreserveSrcDepth(fPreserveSrcDepth);
     42     other->setDitherImage(fDitherImage);
     43     other->setSkipWritingZeroes(fSkipWritingZeroes);
     44     other->setPreferQualityOverSpeed(fPreferQualityOverSpeed);
     45     other->setRequireUnpremultipliedColors(fRequireUnpremultipliedColors);
     46 }
     47 
     48 SkImageDecoder::Format SkImageDecoder::getFormat() const {
     49     return kUnknown_Format;
     50 }
     51 
     52 const char* SkImageDecoder::getFormatName() const {
     53     return GetFormatName(this->getFormat());
     54 }
     55 
     56 const char* SkImageDecoder::GetFormatName(Format format) {
     57     switch (format) {
     58         case kUnknown_Format:
     59             return "Unknown Format";
     60         case kBMP_Format:
     61             return "BMP";
     62         case kGIF_Format:
     63             return "GIF";
     64         case kICO_Format:
     65             return "ICO";
     66         case kPKM_Format:
     67             return "PKM";
     68         case kKTX_Format:
     69             return "KTX";
     70         case kASTC_Format:
     71             return "ASTC";
     72         case kJPEG_Format:
     73             return "JPEG";
     74         case kPNG_Format:
     75             return "PNG";
     76         case kWBMP_Format:
     77             return "WBMP";
     78         case kWEBP_Format:
     79             return "WEBP";
     80         default:
     81             SkDEBUGFAIL("Invalid format type!");
     82     }
     83     return "Unknown Format";
     84 }
     85 
     86 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
     87     SkRefCnt_SafeAssign(fPeeker, peeker);
     88     return peeker;
     89 }
     90 
     91 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
     92     SkRefCnt_SafeAssign(fAllocator, alloc);
     93     return alloc;
     94 }
     95 
     96 void SkImageDecoder::setSampleSize(int size) {
     97     if (size < 1) {
     98         size = 1;
     99     }
    100     fSampleSize = size;
    101 }
    102 
    103 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
    104                                    SkColorTable* ctable) const {
    105     return bitmap->tryAllocPixels(fAllocator, ctable);
    106 }
    107 
    108 ///////////////////////////////////////////////////////////////////////////////
    109 
    110 SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const {
    111     SkColorType ct = fDefaultPref;
    112     if (fPreserveSrcDepth) {
    113         switch (srcDepth) {
    114             case kIndex_SrcDepth:
    115                 ct = kIndex_8_SkColorType;
    116                 break;
    117             case k8BitGray_SrcDepth:
    118                 ct = kN32_SkColorType;
    119                 break;
    120             case k32Bit_SrcDepth:
    121                 ct = kN32_SkColorType;
    122                 break;
    123         }
    124     }
    125     return ct;
    126 }
    127 
    128 SkImageDecoder::Result SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref,
    129                                               Mode mode) {
    130     // we reset this to false before calling onDecode
    131     fShouldCancelDecode = false;
    132     // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
    133     fDefaultPref = pref;
    134 
    135     // pass a temporary bitmap, so that if we return false, we are assured of
    136     // leaving the caller's bitmap untouched.
    137     SkBitmap tmp;
    138     const Result result = this->onDecode(stream, &tmp, mode);
    139     if (kFailure != result) {
    140         bm->swap(tmp);
    141     }
    142     return result;
    143 }
    144 
    145 bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) {
    146     // we reset this to false before calling onDecodeSubset
    147     fShouldCancelDecode = false;
    148     // assign this, for use by getPrefColorType(), in case fUsePrefTable is false
    149     fDefaultPref = pref;
    150 
    151     return this->onDecodeSubset(bm, rect);
    152 }
    153 
    154 bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
    155     // we reset this to false before calling onBuildTileIndex
    156     fShouldCancelDecode = false;
    157 
    158     return this->onBuildTileIndex(stream, width, height);
    159 }
    160 
    161 bool SkImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int* /*width*/,
    162                                       int* /*height*/) {
    163     SkDELETE(stream);
    164     return false;
    165 }
    166 
    167 
    168 bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize,
    169                                 int dstX, int dstY, int width, int height,
    170                                 int srcX, int srcY) {
    171     int w = width / sampleSize;
    172     int h = height / sampleSize;
    173     if (src->colorType() == kIndex_8_SkColorType) {
    174         // kIndex8 does not allow drawing via an SkCanvas, as is done below.
    175         // Instead, use extractSubset. Note that this shares the SkPixelRef and
    176         // SkColorTable.
    177         // FIXME: Since src is discarded in practice, this holds on to more
    178         // pixels than is strictly necessary. Switch to a copy if memory
    179         // savings are more important than speed here. This also means
    180         // that the pixels in dst can not be reused (though there is no
    181         // allocation, which was already done on src).
    182         int x = (dstX - srcX) / sampleSize;
    183         int y = (dstY - srcY) / sampleSize;
    184         SkIRect subset = SkIRect::MakeXYWH(x, y, w, h);
    185         return src->extractSubset(dst, subset);
    186     }
    187     // if the destination has no pixels then we must allocate them.
    188     if (dst->isNull()) {
    189         dst->setInfo(src->info().makeWH(w, h));
    190 
    191         if (!this->allocPixelRef(dst, NULL)) {
    192             SkDEBUGF(("failed to allocate pixels needed to crop the bitmap"));
    193             return false;
    194         }
    195     }
    196     // check to see if the destination is large enough to decode the desired
    197     // region. If this assert fails we will just draw as much of the source
    198     // into the destination that we can.
    199     if (dst->width() < w || dst->height() < h) {
    200         SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n"));
    201     }
    202 
    203     // Set the Src_Mode for the paint to prevent transparency issue in the
    204     // dest in the event that the dest was being re-used.
    205     SkPaint paint;
    206     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    207 
    208     SkCanvas canvas(*dst);
    209     canvas.drawSprite(*src, (srcX - dstX) / sampleSize,
    210                             (srcY - dstY) / sampleSize,
    211                             &paint);
    212     return true;
    213 }
    214 
    215 ///////////////////////////////////////////////////////////////////////////////
    216 
    217 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref,  Mode mode,
    218                                 Format* format) {
    219     SkASSERT(file);
    220     SkASSERT(bm);
    221 
    222     SkAutoTDelete<SkStreamRewindable> stream(SkStream::NewFromFile(file));
    223     if (stream.get()) {
    224         if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
    225             if (SkPixelRef* pr = bm->pixelRef()) {
    226                 pr->setURI(file);
    227             }
    228             return true;
    229         }
    230     }
    231     return false;
    232 }
    233 
    234 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref,
    235                                   Mode mode, Format* format) {
    236     if (0 == size) {
    237         return false;
    238     }
    239     SkASSERT(buffer);
    240 
    241     SkMemoryStream  stream(buffer, size);
    242     return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
    243 }
    244 
    245 bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref,
    246                                   Mode mode, Format* format) {
    247     SkASSERT(stream);
    248     SkASSERT(bm);
    249 
    250     bool success = false;
    251     SkImageDecoder* codec = SkImageDecoder::Factory(stream);
    252 
    253     if (codec) {
    254         success = codec->decode(stream, bm, pref, mode) != kFailure;
    255         if (success && format) {
    256             *format = codec->getFormat();
    257             if (kUnknown_Format == *format) {
    258                 if (stream->rewind()) {
    259                     *format = GetStreamFormat(stream);
    260                 }
    261             }
    262         }
    263         delete codec;
    264     }
    265     return success;
    266 }
    267 
    268 bool SkImageDecoder::decodeYUV8Planes(SkStream* stream, SkISize componentSizes[3], void* planes[3],
    269                                       size_t rowBytes[3], SkYUVColorSpace* colorSpace) {
    270     // we reset this to false before calling onDecodeYUV8Planes
    271     fShouldCancelDecode = false;
    272 
    273     return this->onDecodeYUV8Planes(stream, componentSizes, planes, rowBytes, colorSpace);
    274 }
    275