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
19class JpegDecoderMgr;
20
21/*
22 *
23 * This class implements the decoding for jpeg images
24 *
25 */
26class SkJpegCodec : public SkCodec {
27public:
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
36protected:
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
67private:
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