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 "SkJpegDecoderMgr.h"
14 #include "SkJpegUtility.h"
15 #include "SkStream.h"
16 
17 extern "C" {
18     #include "jpeglib.h"
19 }
20 
21 /*
22  *
23  * This class implements the decoding for jpeg images
24  *
25  */
26 class SkJpegCodec : public SkCodec {
27 public:
28 
29     /*
30      * Checks the start of the stream to see if the image is a jpeg
31      * Does not take ownership of the stream
32      */
33     static bool IsJpeg(SkStream*);
34 
35     /*
36      * Assumes IsJpeg was called and returned true
37      * Creates a jpeg decoder
38      * Takes ownership of the stream
39      */
40     static SkCodec* NewFromStream(SkStream*);
41 
42 protected:
43 
44     /*
45      * Recommend a set of destination dimensions given a requested scale
46      */
47     SkISize onGetScaledDimensions(float desiredScale) const override;
48 
49     /*
50      * Initiates the jpeg decode
51      */
52     Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
53             SkPMColor*, int*) override;
54 
onGetEncodedFormat()55     SkEncodedFormat onGetEncodedFormat() const override {
56         return kJPEG_SkEncodedFormat;
57     }
58 
59     SkScanlineDecoder* onGetScanlineDecoder(const SkImageInfo& dstInfo, const Options& options,
60             SkPMColor ctable[], int* ctableCount) override;
61 
62 private:
63 
64     /*
65      * Read enough of the stream to initialize the SkJpegCodec.
66      * Returns a bool representing success or failure.
67      *
68      * @param codecOut
69      * If this returns true, and codecOut was not NULL,
70      * codecOut will be set to a new SkJpegCodec.
71      *
72      * @param decoderMgrOut
73      * If this returns true, and codecOut was NULL,
74      * decoderMgrOut must be non-NULL and decoderMgrOut will be set to a new
75      * JpegDecoderMgr pointer.
76      *
77      * @param stream
78      * Deleted on failure.
79      * codecOut will take ownership of it in the case where we created a codec.
80      * Ownership is unchanged when we set decoderMgrOut.
81      *
82      */
83     static bool ReadHeader(SkStream* stream, SkCodec** codecOut,
84             JpegDecoderMgr** decoderMgrOut);
85 
86     /*
87      * Creates an instance of the decoder
88      * Called only by NewFromStream
89      *
90      * @param srcInfo contains the source width and height
91      * @param stream the encoded image data
92      * @param decoderMgr holds decompress struct, src manager, and error manager
93      *                   takes ownership
94      */
95     SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream, JpegDecoderMgr* decoderMgr);
96 
97     /*
98      * Handles rewinding the input stream if it is necessary
99      */
100     bool handleRewind();
101 
102     /*
103      * Checks if we can scale to the requested dimensions and scales the dimensions
104      * if possible
105      */
106     bool scaleToDimensions(uint32_t width, uint32_t height);
107 
108     /*
109      * Create the swizzler based on the encoded format
110      */
111     void initializeSwizzler(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
112             const Options& options);
113 
114     SkAutoTDelete<JpegDecoderMgr> fDecoderMgr;
115     SkAutoTDelete<SkSwizzler>     fSwizzler;
116     size_t                        fSrcRowBytes;
117 
118     friend class SkJpegScanlineDecoder;
119 
120     typedef SkCodec INHERITED;
121 };
122 
123 #endif
124