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      * Creates a jpeg decoder
31      * Takes ownership of the stream
32      */
33     static SkCodec* NewFromStream(SkStream*);
34 
35 protected:
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 
onGetEncodedFormat()52     SkEncodedFormat onGetEncodedFormat() const override {
53         return kJPEG_SkEncodedFormat;
54     }
55 
56     bool onRewind() override;
57 
58     bool onDimensionsSupported(const SkISize&) override;
59 
60 private:
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