Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2015 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 #ifndef SkCodec_DEFINED
      9 #define SkCodec_DEFINED
     10 
     11 #include "SkEncodedFormat.h"
     12 #include "SkImageGenerator.h"
     13 #include "SkImageInfo.h"
     14 #include "SkScanlineDecoder.h"
     15 #include "SkSize.h"
     16 #include "SkStream.h"
     17 #include "SkTemplates.h"
     18 #include "SkTypes.h"
     19 
     20 class SkData;
     21 
     22 /**
     23  *  Abstraction layer directly on top of an image codec.
     24  */
     25 class SkCodec : public SkImageGenerator {
     26 public:
     27     /**
     28      *  If this stream represents an encoded image that we know how to decode,
     29      *  return an SkCodec that can decode it. Otherwise return NULL.
     30      *
     31      *  If NULL is returned, the stream is deleted immediately. Otherwise, the
     32      *  SkCodec takes ownership of it, and will delete it when done with it.
     33      */
     34     static SkCodec* NewFromStream(SkStream*);
     35 
     36     /**
     37      *  If this data represents an encoded image that we know how to decode,
     38      *  return an SkCodec that can decode it. Otherwise return NULL.
     39      *
     40      *  Will take a ref if it returns a codec, else will not affect the data.
     41      */
     42     static SkCodec* NewFromData(SkData*);
     43 
     44     /**
     45      *  Return a size that approximately supports the desired scale factor.
     46      *  The codec may not be able to scale efficiently to the exact scale
     47      *  factor requested, so return a size that approximates that scale.
     48      *
     49      *  FIXME: Move to SkImageGenerator?
     50      */
     51     SkISize getScaledDimensions(float desiredScale) const {
     52         return this->onGetScaledDimensions(desiredScale);
     53     }
     54 
     55     /**
     56      *  Format of the encoded data.
     57      */
     58     SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
     59 
     60     /**
     61      *  Return an object which can be used to decode individual scanlines.
     62      *
     63      *  This object is owned by the SkCodec, which will handle its lifetime. The
     64      *  returned object is only valid until the SkCodec is deleted or the next
     65      *  call to getScanlineDecoder, whichever comes first.
     66      *
     67      *  Calling a second time will rewind and replace the existing one with a
     68      *  new one. If the stream cannot be rewound, this will delete the existing
     69      *  one and return NULL.
     70      *
     71      *  @param dstInfo Info of the destination. If the dimensions do not match
     72      *      those of getInfo, this implies a scale.
     73      *  @param options Contains decoding options, including if memory is zero
     74      *      initialized.
     75      *  @param ctable A pointer to a color table.  When dstInfo.colorType() is
     76      *      kIndex8, this should be non-NULL and have enough storage for 256
     77      *      colors.  The color table will be populated after decoding the palette.
     78      *  @param ctableCount A pointer to the size of the color table.  When
     79      *      dstInfo.colorType() is kIndex8, this should be non-NULL.  It will
     80      *      be modified to the true size of the color table (<= 256) after
     81      *      decoding the palette.
     82      *  @return New SkScanlineDecoder, or NULL on failure.
     83      *
     84      *  NOTE: If any rows were previously decoded, this requires rewinding the
     85      *  SkStream.
     86      *
     87      *  NOTE: The scanline decoder is owned by the SkCodec and will delete it
     88      *  when the SkCodec is deleted.
     89      */
     90     SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
     91                                           SkPMColor ctable[], int* ctableCount);
     92 
     93     /**
     94      *  Simplified version of getScanlineDecoder() that asserts that info is NOT
     95      *  kIndex8_SkColorType and uses the default Options.
     96      */
     97     SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo);
     98 
     99     /**
    100      *  Some images may initially report that they have alpha due to the format
    101      *  of the encoded data, but then never use any colors which have alpha
    102      *  less than 100%. This function can be called *after* decoding to
    103      *  determine if such an image truly had alpha. Calling it before decoding
    104      *  is undefined.
    105      *  FIXME: see skbug.com/3582.
    106      */
    107     bool reallyHasAlpha() const {
    108         return this->onReallyHasAlpha();
    109     }
    110 
    111 protected:
    112     SkCodec(const SkImageInfo&, SkStream*);
    113 
    114     virtual SkISize onGetScaledDimensions(float /* desiredScale */) const {
    115         // By default, scaling is not supported.
    116         return this->getInfo().dimensions();
    117     }
    118 
    119     virtual SkEncodedFormat onGetEncodedFormat() const = 0;
    120 
    121     /**
    122      *  Override if your codec supports scanline decoding.
    123      *
    124      *  As in onGetPixels(), the implementation must call rewindIfNeeded() and
    125      *  handle as appropriate.
    126      *
    127      *  @param dstInfo Info of the destination. If the dimensions do not match
    128      *      those of getInfo, this implies a scale.
    129      *  @param options Contains decoding options, including if memory is zero
    130      *      initialized.
    131      *  @param ctable A pointer to a color table.  When dstInfo.colorType() is
    132      *      kIndex8, this should be non-NULL and have enough storage for 256
    133      *      colors.  The color table will be populated after decoding the palette.
    134      *  @param ctableCount A pointer to the size of the color table.  When
    135      *      dstInfo.colorType() is kIndex8, this should be non-NULL.  It will
    136      *      be modified to the true size of the color table (<= 256) after
    137      *      decoding the palette.
    138      *  @return New SkScanlineDecoder on success, NULL otherwise. The SkCodec
    139      *      will take ownership of the returned scanline decoder.
    140      */
    141     virtual SkScanlineDecoder* onGetScanlineDecoder(const SkImageInfo& dstInfo,
    142                                                     const Options& options,
    143                                                     SkPMColor ctable[],
    144                                                     int* ctableCount) {
    145         return NULL;
    146     }
    147 
    148     virtual bool onReallyHasAlpha() const { return false; }
    149 
    150     enum RewindState {
    151         kRewound_RewindState,
    152         kNoRewindNecessary_RewindState,
    153         kCouldNotRewind_RewindState
    154     };
    155     /**
    156      *  If the stream was previously read, attempt to rewind.
    157      *  @returns:
    158      *      kRewound if the stream needed to be rewound, and the
    159      *               rewind succeeded.
    160      *      kNoRewindNecessary if the stream did not need to be
    161      *                         rewound.
    162      *      kCouldNotRewind if the stream needed to be rewound, and
    163      *                      rewind failed.
    164      *
    165      *  Subclasses MUST call this function before reading the stream (e.g. in
    166      *  onGetPixels). If it returns false, onGetPixels should return
    167      *  kCouldNotRewind.
    168      */
    169     RewindState SK_WARN_UNUSED_RESULT rewindIfNeeded();
    170 
    171     /*
    172      *
    173      * Get method for the input stream
    174      *
    175      */
    176     SkStream* stream() {
    177         return fStream.get();
    178     }
    179 
    180 private:
    181     SkAutoTDelete<SkStream>             fStream;
    182     bool                                fNeedsRewind;
    183     SkAutoTDelete<SkScanlineDecoder>    fScanlineDecoder;
    184 
    185     typedef SkImageGenerator INHERITED;
    186 };
    187 #endif // SkCodec_DEFINED
    188