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      * Creates a jpeg decoder
33      * Takes ownership of the stream
34      */
35     static SkCodec* NewFromStream(SkStream*);
36 
37 protected:
38 
39     /*
40      * Recommend a set of destination dimensions given a requested scale
41      */
42     SkISize onGetScaledDimensions(float desiredScale) const override;
43 
44     /*
45      * Initiates the jpeg decode
46      */
47     Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
48             SkPMColor*, int*, int*) override;
49 
50     bool onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const override;
51 
52     Result onGetYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) override;
53 
onGetEncodedFormat()54     SkEncodedImageFormat onGetEncodedFormat() const override {
55         return SkEncodedImageFormat::kJPEG;
56     }
57 
58     bool onRewind() override;
59 
60     bool onDimensionsSupported(const SkISize&) override;
61 
62 private:
63 
64     /*
65      * Allows SkRawCodec to communicate the color space from the exif data.
66      */
67     static SkCodec* NewFromStream(SkStream*, sk_sp<SkColorSpace> defaultColorSpace);
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 defaultColorSpace
88      * If the jpeg does not have an embedded color space, the image data should
89      * be tagged with this color space.
90      */
91     static bool ReadHeader(SkStream* stream, SkCodec** codecOut,
92             JpegDecoderMgr** decoderMgrOut, sk_sp<SkColorSpace> defaultColorSpace);
93 
94     /*
95      * Creates an instance of the decoder
96      * Called only by NewFromStream
97      *
98      * @param info contains properties of the encoded data
99      * @param stream the encoded image data
100      * @param decoderMgr holds decompress struct, src manager, and error manager
101      *                   takes ownership
102      */
103     SkJpegCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
104             JpegDecoderMgr* decoderMgr, sk_sp<SkColorSpace> colorSpace, Origin origin);
105 
106     /*
107      * Checks if the conversion between the input image and the requested output
108      * image has been implemented.
109      *
110      * Sets the output color space.
111      */
112     bool setOutputColorSpace(const SkImageInfo& dst);
113 
114     void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options,
115                             bool needsCMYKToRGB);
116     void allocateStorage(const SkImageInfo& dstInfo);
117     int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count, const Options&);
118 
119     /*
120      * Scanline decoding.
121      */
122     SkSampler* getSampler(bool createIfNecessary) override;
123     Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options,
124             SkPMColor ctable[], int* ctableCount) override;
125     int onGetScanlines(void* dst, int count, size_t rowBytes) override;
126     bool onSkipScanlines(int count) override;
127 
128     std::unique_ptr<JpegDecoderMgr>    fDecoderMgr;
129 
130     // We will save the state of the decompress struct after reading the header.
131     // This allows us to safely call onGetScaledDimensions() at any time.
132     const int                          fReadyState;
133 
134 
135     SkAutoTMalloc<uint8_t>             fStorage;
136     uint8_t*                           fSwizzleSrcRow;
137     uint32_t*                          fColorXformSrcRow;
138 
139     // libjpeg-turbo provides some subsetting.  In the case that libjpeg-turbo
140     // cannot take the exact the subset that we need, we will use the swizzler
141     // to further subset the output from libjpeg-turbo.
142     SkIRect                            fSwizzlerSubset;
143 
144     std::unique_ptr<SkSwizzler>        fSwizzler;
145 
146     friend class SkRawCodec;
147 
148     typedef SkCodec INHERITED;
149 };
150 
151 #endif
152