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