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 "SkData.h"
      9 #include "SkDecodingImageGenerator.h"
     10 #include "SkImageDecoder.h"
     11 #include "SkImageInfo.h"
     12 #include "SkImageGenerator.h"
     13 #include "SkImagePriv.h"
     14 #include "SkStream.h"
     15 #include "SkUtils.h"
     16 
     17 namespace {
     18 bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
     19     return a.width() == b.width() && a.height() == b.height() &&
     20            a.colorType() == b.colorType();
     21 }
     22 
     23 class DecodingImageGenerator : public SkImageGenerator {
     24 public:
     25     virtual ~DecodingImageGenerator();
     26 
     27     SkData*                fData;
     28     SkStreamRewindable*    fStream;
     29     const SkImageInfo      fInfo;
     30     const int              fSampleSize;
     31     const bool             fDitherImage;
     32 
     33     DecodingImageGenerator(SkData* data,
     34                            SkStreamRewindable* stream,
     35                            const SkImageInfo& info,
     36                            int sampleSize,
     37                            bool ditherImage);
     38 
     39 protected:
     40     virtual SkData* onRefEncodedData() SK_OVERRIDE;
     41     virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
     42         *info = fInfo;
     43         return true;
     44     }
     45     virtual bool onGetPixels(const SkImageInfo& info,
     46                              void* pixels, size_t rowBytes,
     47                              SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
     48 
     49 private:
     50     typedef SkImageGenerator INHERITED;
     51 };
     52 
     53 /**
     54  *  Special allocator used by getPixels(). Uses preallocated memory
     55  *  provided if possible, else fall-back on the default allocator
     56  */
     57 class TargetAllocator : public SkBitmap::Allocator {
     58 public:
     59     TargetAllocator(const SkImageInfo& info,
     60                     void* target,
     61                     size_t rowBytes)
     62         : fInfo(info)
     63         , fTarget(target)
     64         , fRowBytes(rowBytes)
     65     {}
     66 
     67     bool isReady() { return (fTarget != NULL); }
     68 
     69     virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
     70         if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
     71             // Call default allocator.
     72             return bm->allocPixels(NULL, ct);
     73         }
     74 
     75         // TODO(halcanary): verify that all callers of this function
     76         // will respect new RowBytes.  Will be moot once rowbytes belongs
     77         // to PixelRef.
     78         bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
     79 
     80         fTarget = NULL;  // never alloc same pixels twice!
     81         return true;
     82     }
     83 
     84 private:
     85     const SkImageInfo fInfo;
     86     void* fTarget;  // Block of memory to be supplied as pixel memory
     87                     // in allocPixelRef.  Must be large enough to hold
     88                     // a bitmap described by fInfo and fRowBytes
     89     const size_t fRowBytes;  // rowbytes for the destination bitmap
     90 
     91     typedef SkBitmap::Allocator INHERITED;
     92 };
     93 
     94 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h
     95 #ifdef SK_DEBUG
     96     #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
     97 #else
     98     #define SkCheckResult(expr, value)  (void)(expr)
     99 #endif
    100 
    101 #ifdef SK_DEBUG
    102 inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
    103     return ((reported == actual)
    104             || ((reported == kPremul_SkAlphaType)
    105                 && (actual == kOpaque_SkAlphaType)));
    106 }
    107 #endif  // SK_DEBUG
    108 
    109 ////////////////////////////////////////////////////////////////////////////////
    110 
    111 DecodingImageGenerator::DecodingImageGenerator(
    112         SkData* data,
    113         SkStreamRewindable* stream,
    114         const SkImageInfo& info,
    115         int sampleSize,
    116         bool ditherImage)
    117     : fData(data)
    118     , fStream(stream)
    119     , fInfo(info)
    120     , fSampleSize(sampleSize)
    121     , fDitherImage(ditherImage)
    122 {
    123     SkASSERT(stream != NULL);
    124     SkSafeRef(fData);  // may be NULL.
    125 }
    126 
    127 DecodingImageGenerator::~DecodingImageGenerator() {
    128     SkSafeUnref(fData);
    129     fStream->unref();
    130 }
    131 
    132 SkData* DecodingImageGenerator::onRefEncodedData() {
    133     // This functionality is used in `gm --serialize`
    134     // Does not encode options.
    135     if (fData != NULL) {
    136         return SkSafeRef(fData);
    137     }
    138     // TODO(halcanary): SkStreamRewindable needs a refData() function
    139     // which returns a cheap copy of the underlying data.
    140     if (!fStream->rewind()) {
    141         return NULL;
    142     }
    143     size_t length = fStream->getLength();
    144     if (0 == length) {
    145         return NULL;
    146     }
    147     void* buffer = sk_malloc_flags(length, 0);
    148     SkCheckResult(fStream->read(buffer, length), length);
    149     fData = SkData::NewFromMalloc(buffer, length);
    150     return SkSafeRef(fData);
    151 }
    152 
    153 bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
    154                                          void* pixels, size_t rowBytes,
    155                                          SkPMColor ctableEntries[], int* ctableCount) {
    156     if (fInfo != info) {
    157         // The caller has specified a different info.  This is an
    158         // error for this kind of SkImageGenerator.  Use the Options
    159         // to change the settings.
    160         return false;
    161     }
    162 
    163     SkAssertResult(fStream->rewind());
    164     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
    165     if (NULL == decoder.get()) {
    166         return false;
    167     }
    168     decoder->setDitherImage(fDitherImage);
    169     decoder->setSampleSize(fSampleSize);
    170     decoder->setRequireUnpremultipliedColors(
    171             info.fAlphaType == kUnpremul_SkAlphaType);
    172 
    173     SkBitmap bitmap;
    174     TargetAllocator allocator(fInfo, pixels, rowBytes);
    175     decoder->setAllocator(&allocator);
    176     bool success = decoder->decode(fStream, &bitmap, info.colorType(),
    177                                    SkImageDecoder::kDecodePixels_Mode);
    178     decoder->setAllocator(NULL);
    179     if (!success) {
    180         return false;
    181     }
    182     if (allocator.isReady()) {  // Did not use pixels!
    183         SkBitmap bm;
    184         SkASSERT(bitmap.canCopyTo(info.colorType()));
    185         bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
    186         if (!copySuccess || allocator.isReady()) {
    187             SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
    188             // Earlier we checked canCopyto(); we expect consistency.
    189             return false;
    190         }
    191         SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
    192     } else {
    193         SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
    194     }
    195 
    196     if (kIndex_8_SkColorType == info.colorType()) {
    197         if (kIndex_8_SkColorType != bitmap.colorType()) {
    198             return false;   // they asked for Index8, but we didn't receive that from decoder
    199         }
    200         SkColorTable* ctable = bitmap.getColorTable();
    201         if (NULL == ctable) {
    202             return false;
    203         }
    204         const int count = ctable->count();
    205         memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
    206         ctable->unlockColors();
    207         *ctableCount = count;
    208     }
    209     return true;
    210 }
    211 
    212 // A contructor-type function that returns NULL on failure.  This
    213 // prevents the returned SkImageGenerator from ever being in a bad
    214 // state.  Called by both Create() functions
    215 SkImageGenerator* CreateDecodingImageGenerator(
    216         SkData* data,
    217         SkStreamRewindable* stream,
    218         const SkDecodingImageGenerator::Options& opts) {
    219     SkASSERT(stream);
    220     SkAutoTUnref<SkStreamRewindable> autoStream(stream);  // always unref this.
    221     SkAssertResult(autoStream->rewind());
    222     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
    223     if (NULL == decoder.get()) {
    224         return NULL;
    225     }
    226     SkBitmap bitmap;
    227     decoder->setSampleSize(opts.fSampleSize);
    228     decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
    229     if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
    230         return NULL;
    231     }
    232     if (kUnknown_SkColorType == bitmap.colorType()) {
    233         return NULL;
    234     }
    235 
    236     SkImageInfo info = bitmap.info();
    237 
    238     if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
    239         if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
    240             SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
    241             return NULL;  // Can not translate to needed config.
    242         }
    243         info.fColorType = opts.fRequestedColorType;
    244     }
    245 
    246     if (opts.fRequireUnpremul && info.fAlphaType != kOpaque_SkAlphaType) {
    247         info.fAlphaType = kUnpremul_SkAlphaType;
    248     }
    249     return SkNEW_ARGS(DecodingImageGenerator,
    250                       (data, autoStream.detach(), info,
    251                        opts.fSampleSize, opts.fDitherImage));
    252 }
    253 
    254 }  // namespace
    255 
    256 ////////////////////////////////////////////////////////////////////////////////
    257 
    258 SkImageGenerator* SkDecodingImageGenerator::Create(
    259         SkData* data,
    260         const SkDecodingImageGenerator::Options& opts) {
    261     SkASSERT(data != NULL);
    262     if (NULL == data) {
    263         return NULL;
    264     }
    265     SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
    266     SkASSERT(stream != NULL);
    267     SkASSERT(stream->unique());
    268     return CreateDecodingImageGenerator(data, stream, opts);
    269 }
    270 
    271 SkImageGenerator* SkDecodingImageGenerator::Create(
    272         SkStreamRewindable* stream,
    273         const SkDecodingImageGenerator::Options& opts) {
    274     SkASSERT(stream != NULL);
    275     SkASSERT(stream->unique());
    276     if ((stream == NULL) || !stream->unique()) {
    277         SkSafeUnref(stream);
    278         return NULL;
    279     }
    280     return CreateDecodingImageGenerator(NULL, stream, opts);
    281 }
    282