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