Home | History | Annotate | Download | only in images
      1 /* libs/graphics/images/SkImageDecoder.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkImageDecoder.h"
     19 #include "SkBitmap.h"
     20 #include "SkPixelRef.h"
     21 #include "SkStream.h"
     22 #include "SkTemplates.h"
     23 #include "SkCanvas.h"
     24 
     25 SkVMMemoryReporter::~SkVMMemoryReporter() {
     26 }
     27 
     28 const char *SkImageDecoder::kFormatName[] = {
     29     "Unknown Format",
     30     "BMP",
     31     "GIF",
     32     "ICO",
     33     "JPEG",
     34     "PNG",
     35     "WBMP",
     36 };
     37 
     38 static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config;
     39 
     40 SkBitmap::Config SkImageDecoder::GetDeviceConfig()
     41 {
     42     return gDeviceConfig;
     43 }
     44 
     45 void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
     46 {
     47     gDeviceConfig = config;
     48 }
     49 
     50 ///////////////////////////////////////////////////////////////////////////////
     51 
     52 SkImageDecoder::SkImageDecoder()
     53     : fReporter(NULL), fPeeker(NULL), fChooser(NULL), fAllocator(NULL),
     54       fSampleSize(1), fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
     55       fUsePrefTable(false) {
     56 }
     57 
     58 SkImageDecoder::~SkImageDecoder() {
     59     fPeeker->safeUnref();
     60     fChooser->safeUnref();
     61     fAllocator->safeUnref();
     62     fReporter->safeUnref();
     63 }
     64 
     65 SkImageDecoder::Format SkImageDecoder::getFormat() const {
     66     return kUnknown_Format;
     67 }
     68 
     69 SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
     70     SkRefCnt_SafeAssign(fPeeker, peeker);
     71     return peeker;
     72 }
     73 
     74 SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) {
     75     SkRefCnt_SafeAssign(fChooser, chooser);
     76     return chooser;
     77 }
     78 
     79 SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) {
     80     SkRefCnt_SafeAssign(fAllocator, alloc);
     81     return alloc;
     82 }
     83 
     84 SkVMMemoryReporter* SkImageDecoder::setReporter(SkVMMemoryReporter* reporter) {
     85     SkRefCnt_SafeAssign(fReporter, reporter);
     86     return reporter;
     87 }
     88 
     89 void SkImageDecoder::setSampleSize(int size) {
     90     if (size < 1) {
     91         size = 1;
     92     }
     93     fSampleSize = size;
     94 }
     95 
     96 bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width,
     97                                          int height) const {
     98     Chooser* chooser = fChooser;
     99 
    100     if (NULL == chooser) {    // no chooser, we just say YES to decoding :)
    101         return true;
    102     }
    103     chooser->begin(1);
    104     chooser->inspect(0, config, width, height);
    105     return chooser->choose() == 0;
    106 }
    107 
    108 bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
    109                                    SkColorTable* ctable) const {
    110     return bitmap->allocPixels(fAllocator, ctable);
    111 }
    112 
    113 ///////////////////////////////////////////////////////////////////////////////
    114 
    115 void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
    116     if (NULL == pref) {
    117         fUsePrefTable = false;
    118     } else {
    119         fUsePrefTable = true;
    120         memcpy(fPrefTable, pref, sizeof(fPrefTable));
    121     }
    122 }
    123 
    124 SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
    125                                                bool srcHasAlpha) const {
    126     SkBitmap::Config config;
    127 
    128     if (fUsePrefTable) {
    129         int index = 0;
    130         switch (srcDepth) {
    131             case kIndex_SrcDepth:
    132                 index = 0;
    133                 break;
    134             case k16Bit_SrcDepth:
    135                 index = 2;
    136                 break;
    137             case k32Bit_SrcDepth:
    138                 index = 4;
    139                 break;
    140         }
    141         if (srcHasAlpha) {
    142             index += 1;
    143         }
    144         config = fPrefTable[index];
    145     } else {
    146         config = fDefaultPref;
    147     }
    148 
    149     if (SkBitmap::kNo_Config == config) {
    150         config = SkImageDecoder::GetDeviceConfig();
    151     }
    152     return config;
    153 }
    154 
    155 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
    156                             SkBitmap::Config pref, Mode mode) {
    157     // pass a temporary bitmap, so that if we return false, we are assured of
    158     // leaving the caller's bitmap untouched.
    159     SkBitmap    tmp;
    160 
    161     // we reset this to false before calling onDecode
    162     fShouldCancelDecode = false;
    163     // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
    164     fDefaultPref = pref;
    165 
    166     if (!this->onDecode(stream, &tmp, mode)) {
    167         return false;
    168     }
    169     bm->swap(tmp);
    170     return true;
    171 }
    172 
    173 bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect,
    174                                   SkBitmap::Config pref) {
    175     // pass a temporary bitmap, so that if we return false, we are assured of
    176     // leaving the caller's bitmap untouched.
    177     SkBitmap    tmp;
    178 
    179     // we reset this to false before calling onDecodeRegion
    180     fShouldCancelDecode = false;
    181     // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
    182     fDefaultPref = pref;
    183 
    184     if (!this->onDecodeRegion(&tmp, rect)) {
    185         return false;
    186     }
    187     bm->swap(tmp);
    188     return true;
    189 }
    190 
    191 bool SkImageDecoder::buildTileIndex(SkStream* stream,
    192                                 int *width, int *height) {
    193     // we reset this to false before calling onBuildTileIndex
    194     fShouldCancelDecode = false;
    195 
    196     return this->onBuildTileIndex(stream, width, height);
    197 }
    198 
    199 void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src,
    200                                     int sampleSize, int destX, int destY,
    201                                     int width, int height, int srcX, int srcY) {
    202     int w = width / sampleSize;
    203     int h = height / sampleSize;
    204     if (w == src->width() && h == src->height() &&
    205           (srcX - destX) / sampleSize == 0 && (srcY - destY) / sampleSize == 0) {
    206         // The output rect is the same as the decode result
    207         dest->swap(*src);
    208         return;
    209     }
    210     dest->setConfig(src->getConfig(), w, h);
    211     dest->setIsOpaque(src->isOpaque());
    212     this->allocPixelRef(dest, NULL);
    213 
    214     SkCanvas canvas(*dest);
    215     canvas.drawBitmap(*src, (srcX - destX) / sampleSize,
    216                              (srcY - destY) / sampleSize);
    217 }
    218 
    219 ///////////////////////////////////////////////////////////////////////////////
    220 
    221 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
    222                             SkBitmap::Config pref,  Mode mode, Format* format) {
    223     SkASSERT(file);
    224     SkASSERT(bm);
    225 
    226     SkFILEStream    stream(file);
    227     if (stream.isValid()) {
    228         if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) {
    229             bm->pixelRef()->setURI(file);
    230         }
    231         return true;
    232     }
    233     return false;
    234 }
    235 
    236 bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm,
    237                           SkBitmap::Config pref, Mode mode, Format* format) {
    238     if (0 == size) {
    239         return false;
    240     }
    241     SkASSERT(buffer);
    242 
    243     SkMemoryStream  stream(buffer, size);
    244     return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format);
    245 }
    246 
    247 bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
    248                           SkBitmap::Config pref, Mode mode, Format* format) {
    249     SkASSERT(stream);
    250     SkASSERT(bm);
    251 
    252     bool success = false;
    253     SkImageDecoder* codec = SkImageDecoder::Factory(stream);
    254 
    255     if (NULL != codec) {
    256         success = codec->decode(stream, bm, pref, mode);
    257         if (success && format) {
    258             *format = codec->getFormat();
    259         }
    260         delete codec;
    261     }
    262     return success;
    263 }
    264