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 SkJpegCodec_DEFINED
      9 #define SkJpegCodec_DEFINED
     10 
     11 #include "SkCodec.h"
     12 #include "SkImageInfo.h"
     13 #include "SkSwizzler.h"
     14 #include "SkStream.h"
     15 #include "SkTemplates.h"
     16 
     17 class JpegDecoderMgr;
     18 
     19 /*
     20  *
     21  * This class implements the decoding for jpeg images
     22  *
     23  */
     24 class SkJpegCodec : public SkCodec {
     25 public:
     26     static bool IsJpeg(const void*, size_t);
     27 
     28     /*
     29      * Assumes IsJpeg was called and returned true
     30      * Takes ownership of the stream
     31      */
     32     static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
     33 
     34 protected:
     35 
     36     /*
     37      * Recommend a set of destination dimensions given a requested scale
     38      */
     39     SkISize onGetScaledDimensions(float desiredScale) const override;
     40 
     41     /*
     42      * Initiates the jpeg decode
     43      */
     44     Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
     45             int*) override;
     46 
     47     bool onQueryYUV8(SkYUVASizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override;
     48 
     49     Result onGetYUV8Planes(const SkYUVASizeInfo& sizeInfo,
     50                            void* planes[SkYUVASizeInfo::kMaxCount]) override;
     51 
     52     SkEncodedImageFormat onGetEncodedFormat() const override {
     53         return SkEncodedImageFormat::kJPEG;
     54     }
     55 
     56     bool onRewind() override;
     57 
     58     bool onDimensionsSupported(const SkISize&) override;
     59 
     60     bool conversionSupported(const SkImageInfo&, bool, bool) override;
     61 
     62 private:
     63     /*
     64      * Allows SkRawCodec to communicate the color profile from the exif data.
     65      */
     66     static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*,
     67             std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile);
     68 
     69     /*
     70      * Read enough of the stream to initialize the SkJpegCodec.
     71      * Returns a bool representing success or failure.
     72      *
     73      * @param codecOut
     74      * If this returns true, and codecOut was not nullptr,
     75      * codecOut will be set to a new SkJpegCodec.
     76      *
     77      * @param decoderMgrOut
     78      * If this returns true, and codecOut was nullptr,
     79      * decoderMgrOut must be non-nullptr and decoderMgrOut will be set to a new
     80      * JpegDecoderMgr pointer.
     81      *
     82      * @param stream
     83      * Deleted on failure.
     84      * codecOut will take ownership of it in the case where we created a codec.
     85      * Ownership is unchanged when we set decoderMgrOut.
     86      *
     87      * @param defaultColorProfile
     88      * If the jpeg does not have an embedded color profile, the image data should
     89      * be tagged with this color profile.
     90      */
     91     static Result ReadHeader(SkStream* stream, SkCodec** codecOut,
     92             JpegDecoderMgr** decoderMgrOut,
     93             std::unique_ptr<SkEncodedInfo::ICCProfile> defaultColorProfile);
     94 
     95     /*
     96      * Creates an instance of the decoder
     97      * Called only by NewFromStream
     98      *
     99      * @param info contains properties of the encoded data
    100      * @param stream the encoded image data
    101      * @param decoderMgr holds decompress struct, src manager, and error manager
    102      *                   takes ownership
    103      */
    104     SkJpegCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream> stream,
    105             JpegDecoderMgr* decoderMgr, SkEncodedOrigin origin);
    106 
    107     void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
    108                             bool needsCMYKToRGB);
    109     void allocateStorage(const SkImageInfo& dstInfo);
    110     int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count, const Options&);
    111 
    112     /*
    113      * Scanline decoding.
    114      */
    115     SkSampler* getSampler(bool createIfNecessary) override;
    116     Result onStartScanlineDecode(const SkImageInfo& dstInfo,
    117             const Options& options) override;
    118     int onGetScanlines(void* dst, int count, size_t rowBytes) override;
    119     bool onSkipScanlines(int count) override;
    120 
    121     std::unique_ptr<JpegDecoderMgr>    fDecoderMgr;
    122 
    123     // We will save the state of the decompress struct after reading the header.
    124     // This allows us to safely call onGetScaledDimensions() at any time.
    125     const int                          fReadyState;
    126 
    127 
    128     SkAutoTMalloc<uint8_t>             fStorage;
    129     uint8_t*                           fSwizzleSrcRow;
    130     uint32_t*                          fColorXformSrcRow;
    131 
    132     // libjpeg-turbo provides some subsetting.  In the case that libjpeg-turbo
    133     // cannot take the exact the subset that we need, we will use the swizzler
    134     // to further subset the output from libjpeg-turbo.
    135     SkIRect                            fSwizzlerSubset;
    136 
    137     std::unique_ptr<SkSwizzler>        fSwizzler;
    138 
    139     friend class SkRawCodec;
    140 
    141     typedef SkCodec INHERITED;
    142 };
    143 
    144 #endif
    145