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
17class JpegDecoderMgr;
18
19/*
20 *
21 * This class implements the decoding for jpeg images
22 *
23 */
24class SkJpegCodec : public SkCodec {
25public:
26    static bool IsJpeg(const void*, size_t);
27
28    /*
29     * Assumes IsJpeg was called and returned true
30     * Creates a jpeg decoder
31     * Takes ownership of the stream
32     */
33    static SkCodec* NewFromStream(SkStream*);
34
35protected:
36
37    /*
38     * Recommend a set of destination dimensions given a requested scale
39     */
40    SkISize onGetScaledDimensions(float desiredScale) const override;
41
42    /*
43     * Initiates the jpeg decode
44     */
45    Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
46            SkPMColor*, int*, int*) override;
47
48    bool onQueryYUV8(YUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override;
49
50    Result onGetYUV8Planes(const YUVSizeInfo& sizeInfo, void* pixels[3]) override;
51
52    SkEncodedFormat onGetEncodedFormat() const override {
53        return kJPEG_SkEncodedFormat;
54    }
55
56    bool onRewind() override;
57
58    bool onDimensionsSupported(const SkISize&) override;
59
60private:
61
62    /*
63     * Read enough of the stream to initialize the SkJpegCodec.
64     * Returns a bool representing success or failure.
65     *
66     * @param codecOut
67     * If this returns true, and codecOut was not nullptr,
68     * codecOut will be set to a new SkJpegCodec.
69     *
70     * @param decoderMgrOut
71     * If this returns true, and codecOut was nullptr,
72     * decoderMgrOut must be non-nullptr and decoderMgrOut will be set to a new
73     * JpegDecoderMgr pointer.
74     *
75     * @param stream
76     * Deleted on failure.
77     * codecOut will take ownership of it in the case where we created a codec.
78     * Ownership is unchanged when we set decoderMgrOut.
79     *
80     */
81    static bool ReadHeader(SkStream* stream, SkCodec** codecOut,
82            JpegDecoderMgr** decoderMgrOut);
83
84    /*
85     * Creates an instance of the decoder
86     * Called only by NewFromStream
87     *
88     * @param srcInfo contains the source width and height
89     * @param stream the encoded image data
90     * @param decoderMgr holds decompress struct, src manager, and error manager
91     *                   takes ownership
92     */
93    SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, JpegDecoderMgr* decoderMgr);
94
95    /*
96     * Checks if the conversion between the input image and the requested output
97     * image has been implemented
98     * Sets the output color space
99     */
100    bool setOutputColorSpace(const SkImageInfo& dst);
101
102    // scanline decoding
103    void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options);
104    SkSampler* getSampler(bool createIfNecessary) override;
105    Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options,
106            SkPMColor ctable[], int* ctableCount) override;
107    int onGetScanlines(void* dst, int count, size_t rowBytes) override;
108    bool onSkipScanlines(int count) override;
109
110    SkAutoTDelete<JpegDecoderMgr> fDecoderMgr;
111    // We will save the state of the decompress struct after reading the header.
112    // This allows us to safely call onGetScaledDimensions() at any time.
113    const int                     fReadyState;
114
115    // scanline decoding
116    SkAutoTMalloc<uint8_t>     fStorage;    // Only used if sampling is needed
117    uint8_t*                   fSrcRow;     // Only used if sampling is needed
118    // libjpeg-turbo provides some subsetting.  In the case that libjpeg-turbo
119    // cannot take the exact the subset that we need, we will use the swizzler
120    // to further subset the output from libjpeg-turbo.
121    SkIRect                    fSwizzlerSubset;
122    SkAutoTDelete<SkSwizzler>  fSwizzler;
123
124    typedef SkCodec INHERITED;
125};
126
127#endif
128