Home | History | Annotate | Download | only in images
      1 /*
      2  * Copyright 2013 Google Inc.
      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 #include "SkDecodingImageGenerator.h"
      9 #include "SkData.h"
     10 #include "SkImageDecoder.h"
     11 #include "SkImageGenerator.h"
     12 #include "SkImagePriv.h"
     13 #include "SkStream.h"
     14 
     15 
     16 namespace {
     17 /**
     18  *  Special allocator used by getPixels(). Uses preallocated memory
     19  *  provided.
     20  */
     21 class TargetAllocator : public SkBitmap::Allocator {
     22 public:
     23     TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
     24         : fTarget(target)
     25         , fRowBytes(rowBytes)
     26         , fInfo(info) { }
     27 
     28     virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
     29         if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
     30             || (bm->width() != fInfo.fWidth)
     31             || (bm->height() != fInfo.fHeight)) {
     32             return false;
     33         }
     34         bm->setConfig(bm->config(), bm->width(), bm->height(),
     35                       fRowBytes, bm->alphaType());
     36         bm->setPixels(fTarget, ct);
     37         return true;
     38     }
     39 
     40 private:
     41     void* fTarget;
     42     size_t fRowBytes;
     43     SkImageInfo fInfo;
     44     typedef SkBitmap::Allocator INHERITED;
     45 };
     46 }  // namespace
     47 ////////////////////////////////////////////////////////////////////////////////
     48 
     49 SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
     50     : fData(data)
     51     , fHasInfo(false)
     52     , fDoCopyTo(false) {
     53     SkASSERT(fData != NULL);
     54     fStream = SkNEW_ARGS(SkMemoryStream, (fData));
     55     SkASSERT(fStream != NULL);
     56     SkASSERT(fStream->unique());
     57     fData->ref();
     58 }
     59 
     60 SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream)
     61     : fData(NULL)
     62     , fStream(stream)
     63     , fHasInfo(false)
     64     , fDoCopyTo(false) {
     65     SkASSERT(fStream != NULL);
     66     SkASSERT(fStream->unique());
     67 }
     68 
     69 SkDecodingImageGenerator::~SkDecodingImageGenerator() {
     70     SkSafeUnref(fData);
     71     fStream->unref();
     72 }
     73 
     74 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h
     75 #ifdef SK_DEBUG
     76     #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
     77 #else
     78     #define SkCheckResult(expr, value)  (void)(expr)
     79 #endif
     80 
     81 SkData* SkDecodingImageGenerator::refEncodedData() {
     82     // This functionality is used in `gm --serialize`
     83     if (fData != NULL) {
     84         return SkSafeRef(fData);
     85     }
     86     // TODO(halcanary): SkStreamRewindable needs a refData() function
     87     // which returns a cheap copy of the underlying data.
     88     if (!fStream->rewind()) {
     89         return NULL;
     90     }
     91     size_t length = fStream->getLength();
     92     if (0 == length) {
     93         return NULL;
     94     }
     95     void* buffer = sk_malloc_flags(length, 0);
     96     SkCheckResult(fStream->read(buffer, length), length);
     97     fData = SkData::NewFromMalloc(buffer, length);
     98     return SkSafeRef(fData);
     99 }
    100 
    101 bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
    102     // info can be NULL.  If so, will update fInfo, fDoCopyTo, and fHasInfo.
    103     if (fHasInfo) {
    104         if (info != NULL) {
    105             *info = fInfo;
    106         }
    107         return true;
    108     }
    109     SkAssertResult(fStream->rewind());
    110     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
    111     if (NULL == decoder.get()) {
    112         return false;
    113     }
    114     SkBitmap bitmap;
    115     if (!decoder->decode(fStream, &bitmap,
    116                          SkImageDecoder::kDecodeBounds_Mode)) {
    117         return false;
    118     }
    119     if (bitmap.config() == SkBitmap::kNo_Config) {
    120         return false;
    121     }
    122     if (!bitmap.asImageInfo(&fInfo)) {
    123         // We can't use bitmap.config() as is.
    124         if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
    125             SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)");
    126             return false;
    127         }
    128         fDoCopyTo = true;
    129         fInfo.fWidth = bitmap.width();
    130         fInfo.fHeight = bitmap.height();
    131         fInfo.fColorType = kPMColor_SkColorType;
    132         fInfo.fAlphaType = bitmap.alphaType();
    133     }
    134     if (info != NULL) {
    135         *info = fInfo;
    136     }
    137     fHasInfo = true;
    138     return true;
    139 }
    140 
    141 bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
    142                                          void* pixels,
    143                                          size_t rowBytes) {
    144     if (NULL == pixels) {
    145         return false;
    146     }
    147     if (!this->getInfo(NULL)) {
    148         return false;
    149     }
    150     if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
    151         return false;  // Unsupported SkColorType.
    152     }
    153     SkAssertResult(fStream->rewind());
    154     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
    155     if (NULL == decoder.get()) {
    156         return false;
    157     }
    158     if (fInfo != info) {
    159         // The caller has specified a different info.  For now, this
    160         // is an error.  In the future, we will check to see if we can
    161         // convert.
    162         return false;
    163     }
    164     int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
    165     if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
    166         return false;
    167     }
    168     SkBitmap bitmap;
    169     if (!bitmap.setConfig(info, rowBytes)) {
    170         return false;
    171     }
    172 
    173     TargetAllocator allocator(pixels, rowBytes, info);
    174     if (!fDoCopyTo) {
    175         decoder->setAllocator(&allocator);
    176     }
    177     bool success = decoder->decode(fStream, &bitmap,
    178                                    SkImageDecoder::kDecodePixels_Mode);
    179     decoder->setAllocator(NULL);
    180     if (!success) {
    181         return false;
    182     }
    183     if (fDoCopyTo) {
    184         SkBitmap bm8888;
    185         bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
    186     }
    187     return true;
    188 }
    189 bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
    190                                        SkDiscardableMemory::Factory* factory) {
    191     SkASSERT(data != NULL);
    192     SkASSERT(dst != NULL);
    193     SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
    194     return SkInstallDiscardablePixelRef(gen, dst, factory);
    195 }
    196 
    197 bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
    198                                        SkBitmap* dst,
    199                                        SkDiscardableMemory::Factory* factory) {
    200     SkASSERT(stream != NULL);
    201     SkASSERT(dst != NULL);
    202     if ((stream == NULL) || !stream->unique()) {
    203         SkSafeUnref(stream);
    204         return false;
    205     }
    206     SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
    207     return SkInstallDiscardablePixelRef(gen, dst, factory);
    208 }
    209