blob: 54bd6ff5d617ebba99b1e8717a7c01e9bba804cf [file] [log] [blame]
scroggof24f2242015-03-03 08:59:20 -08001/*
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 SkCodec_DEFINED
9#define SkCodec_DEFINED
10
scroggoeb602a52015-07-09 08:16:03 -070011#include "SkColor.h"
scroggo1dd3ea92015-03-20 11:55:55 -070012#include "SkEncodedFormat.h"
scroggof24f2242015-03-03 08:59:20 -080013#include "SkImageInfo.h"
14#include "SkSize.h"
scroggofffeede2015-03-18 10:50:37 -070015#include "SkStream.h"
scroggof24f2242015-03-03 08:59:20 -080016#include "SkTemplates.h"
17#include "SkTypes.h"
18
19class SkData;
scroggoeb602a52015-07-09 08:16:03 -070020class SkScanlineDecoder;
scroggof24f2242015-03-03 08:59:20 -080021
22/**
23 * Abstraction layer directly on top of an image codec.
24 */
scroggoeb602a52015-07-09 08:16:03 -070025class SkCodec : SkNoncopyable {
scroggof24f2242015-03-03 08:59:20 -080026public:
27 /**
28 * If this stream represents an encoded image that we know how to decode,
29 * return an SkCodec that can decode it. Otherwise return NULL.
30 *
31 * If NULL is returned, the stream is deleted immediately. Otherwise, the
32 * SkCodec takes ownership of it, and will delete it when done with it.
33 */
34 static SkCodec* NewFromStream(SkStream*);
35
36 /**
37 * If this data represents an encoded image that we know how to decode,
38 * return an SkCodec that can decode it. Otherwise return NULL.
39 *
40 * Will take a ref if it returns a codec, else will not affect the data.
41 */
42 static SkCodec* NewFromData(SkData*);
43
scroggoeb602a52015-07-09 08:16:03 -070044 virtual ~SkCodec();
45
46 /**
47 * Return the ImageInfo associated with this codec.
48 */
49 const SkImageInfo& getInfo() const { return fInfo; }
50
scroggof24f2242015-03-03 08:59:20 -080051 /**
52 * Return a size that approximately supports the desired scale factor.
53 * The codec may not be able to scale efficiently to the exact scale
54 * factor requested, so return a size that approximates that scale.
scroggof24f2242015-03-03 08:59:20 -080055 */
scroggofffeede2015-03-18 10:50:37 -070056 SkISize getScaledDimensions(float desiredScale) const {
57 return this->onGetScaledDimensions(desiredScale);
58 }
scroggof24f2242015-03-03 08:59:20 -080059
scroggo1dd3ea92015-03-20 11:55:55 -070060 /**
61 * Format of the encoded data.
62 */
63 SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
64
scroggo05245902015-03-25 11:11:52 -070065 /**
scroggoeb602a52015-07-09 08:16:03 -070066 * Used to describe the result of a call to getPixels().
67 *
68 * Result is the union of possible results from subclasses.
69 */
70 enum Result {
71 /**
72 * General return value for success.
73 */
74 kSuccess,
75 /**
76 * The input is incomplete. A partial image was generated.
77 */
78 kIncompleteInput,
79 /**
80 * The generator cannot convert to match the request, ignoring
81 * dimensions.
82 */
83 kInvalidConversion,
84 /**
85 * The generator cannot scale to requested size.
86 */
87 kInvalidScale,
88 /**
89 * Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
90 * too small, etc.
91 */
92 kInvalidParameters,
93 /**
94 * The input did not contain a valid image.
95 */
96 kInvalidInput,
97 /**
98 * Fulfilling this request requires rewinding the input, which is not
99 * supported for this input.
100 */
101 kCouldNotRewind,
102 /**
103 * This method is not implemented by this generator.
104 */
105 kUnimplemented,
106 };
107
108 /**
109 * Whether or not the memory passed to getPixels is zero initialized.
110 */
111 enum ZeroInitialized {
112 /**
113 * The memory passed to getPixels is zero initialized. The SkCodec
114 * may take advantage of this by skipping writing zeroes.
115 */
116 kYes_ZeroInitialized,
117 /**
118 * The memory passed to getPixels has not been initialized to zero,
119 * so the SkCodec must write all zeroes to memory.
120 *
121 * This is the default. It will be used if no Options struct is used.
122 */
123 kNo_ZeroInitialized,
124 };
125
126 /**
127 * Additional options to pass to getPixels.
128 */
129 struct Options {
130 Options()
131 : fZeroInitialized(kNo_ZeroInitialized) {}
132
133 ZeroInitialized fZeroInitialized;
134 };
135
136 /**
137 * Decode into the given pixels, a block of memory of size at
138 * least (info.fHeight - 1) * rowBytes + (info.fWidth *
139 * bytesPerPixel)
140 *
141 * Repeated calls to this function should give the same results,
142 * allowing the PixelRef to be immutable.
143 *
144 * @param info A description of the format (config, size)
145 * expected by the caller. This can simply be identical
146 * to the info returned by getInfo().
147 *
148 * This contract also allows the caller to specify
149 * different output-configs, which the implementation can
150 * decide to support or not.
151 *
152 * A size that does not match getInfo() implies a request
153 * to scale. If the generator cannot perform this scale,
154 * it will return kInvalidScale.
155 *
156 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
157 * SkPMColor values in ctable. On success the generator must copy N colors into that storage,
158 * (where N is the logical number of table entries) and set ctableCount to N.
159 *
160 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
161 * is not null, it will be set to 0.
162 *
163 * @return Result kSuccess, or another value explaining the type of failure.
164 */
165 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*,
166 SkPMColor ctable[], int* ctableCount);
167
168 /**
169 * Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
170 * uses the default Options.
171 */
172 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
173
174 /**
scroggo05245902015-03-25 11:11:52 -0700175 * Return an object which can be used to decode individual scanlines.
176 *
177 * This object is owned by the SkCodec, which will handle its lifetime. The
178 * returned object is only valid until the SkCodec is deleted or the next
179 * call to getScanlineDecoder, whichever comes first.
180 *
181 * Calling a second time will rewind and replace the existing one with a
182 * new one. If the stream cannot be rewound, this will delete the existing
183 * one and return NULL.
184 *
185 * @param dstInfo Info of the destination. If the dimensions do not match
186 * those of getInfo, this implies a scale.
msarett9e43cab2015-04-29 07:38:43 -0700187 * @param options Contains decoding options, including if memory is zero
188 * initialized.
189 * @param ctable A pointer to a color table. When dstInfo.colorType() is
190 * kIndex8, this should be non-NULL and have enough storage for 256
191 * colors. The color table will be populated after decoding the palette.
192 * @param ctableCount A pointer to the size of the color table. When
193 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
194 * be modified to the true size of the color table (<= 256) after
195 * decoding the palette.
scroggo05245902015-03-25 11:11:52 -0700196 * @return New SkScanlineDecoder, or NULL on failure.
197 *
198 * NOTE: If any rows were previously decoded, this requires rewinding the
199 * SkStream.
200 *
201 * NOTE: The scanline decoder is owned by the SkCodec and will delete it
202 * when the SkCodec is deleted.
203 */
msarett9e43cab2015-04-29 07:38:43 -0700204 SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
205 SkPMColor ctable[], int* ctableCount);
206
207 /**
208 * Simplified version of getScanlineDecoder() that asserts that info is NOT
209 * kIndex8_SkColorType and uses the default Options.
210 */
scroggo05245902015-03-25 11:11:52 -0700211 SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo);
212
213 /**
214 * Some images may initially report that they have alpha due to the format
215 * of the encoded data, but then never use any colors which have alpha
216 * less than 100%. This function can be called *after* decoding to
217 * determine if such an image truly had alpha. Calling it before decoding
218 * is undefined.
219 * FIXME: see skbug.com/3582.
220 */
221 bool reallyHasAlpha() const {
222 return this->onReallyHasAlpha();
223 }
224
scroggof24f2242015-03-03 08:59:20 -0800225protected:
226 SkCodec(const SkImageInfo&, SkStream*);
227
scroggof24f2242015-03-03 08:59:20 -0800228 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const {
229 // By default, scaling is not supported.
halcanaryb880d7f2015-03-26 06:29:03 -0700230 return this->getInfo().dimensions();
scroggof24f2242015-03-03 08:59:20 -0800231 }
232
scroggo1dd3ea92015-03-20 11:55:55 -0700233 virtual SkEncodedFormat onGetEncodedFormat() const = 0;
234
scroggoeb602a52015-07-09 08:16:03 -0700235 virtual Result onGetPixels(const SkImageInfo& info,
236 void* pixels, size_t rowBytes, const Options&,
237 SkPMColor ctable[], int* ctableCount) = 0;
238
scroggof24f2242015-03-03 08:59:20 -0800239 /**
scroggo05245902015-03-25 11:11:52 -0700240 * Override if your codec supports scanline decoding.
241 *
scroggo58421542015-04-01 11:25:20 -0700242 * As in onGetPixels(), the implementation must call rewindIfNeeded() and
243 * handle as appropriate.
scroggo05245902015-03-25 11:11:52 -0700244 *
245 * @param dstInfo Info of the destination. If the dimensions do not match
246 * those of getInfo, this implies a scale.
msarett9e43cab2015-04-29 07:38:43 -0700247 * @param options Contains decoding options, including if memory is zero
248 * initialized.
249 * @param ctable A pointer to a color table. When dstInfo.colorType() is
250 * kIndex8, this should be non-NULL and have enough storage for 256
251 * colors. The color table will be populated after decoding the palette.
252 * @param ctableCount A pointer to the size of the color table. When
253 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
254 * be modified to the true size of the color table (<= 256) after
255 * decoding the palette.
scroggo05245902015-03-25 11:11:52 -0700256 * @return New SkScanlineDecoder on success, NULL otherwise. The SkCodec
257 * will take ownership of the returned scanline decoder.
258 */
msarett9e43cab2015-04-29 07:38:43 -0700259 virtual SkScanlineDecoder* onGetScanlineDecoder(const SkImageInfo& dstInfo,
260 const Options& options,
261 SkPMColor ctable[],
262 int* ctableCount) {
scroggo05245902015-03-25 11:11:52 -0700263 return NULL;
264 }
265
266 virtual bool onReallyHasAlpha() const { return false; }
267
halcanarya096d7a2015-03-27 12:16:53 -0700268 enum RewindState {
269 kRewound_RewindState,
270 kNoRewindNecessary_RewindState,
271 kCouldNotRewind_RewindState
272 };
scroggo05245902015-03-25 11:11:52 -0700273 /**
scroggof24f2242015-03-03 08:59:20 -0800274 * If the stream was previously read, attempt to rewind.
275 * @returns:
halcanarya096d7a2015-03-27 12:16:53 -0700276 * kRewound if the stream needed to be rewound, and the
277 * rewind succeeded.
278 * kNoRewindNecessary if the stream did not need to be
279 * rewound.
280 * kCouldNotRewind if the stream needed to be rewound, and
281 * rewind failed.
282 *
scroggof24f2242015-03-03 08:59:20 -0800283 * Subclasses MUST call this function before reading the stream (e.g. in
284 * onGetPixels). If it returns false, onGetPixels should return
285 * kCouldNotRewind.
286 */
halcanarya096d7a2015-03-27 12:16:53 -0700287 RewindState SK_WARN_UNUSED_RESULT rewindIfNeeded();
scroggof24f2242015-03-03 08:59:20 -0800288
msarettc0e80c12015-07-01 06:50:35 -0700289 /**
msarett74114382015-03-16 11:55:18 -0700290 * Get method for the input stream
msarett74114382015-03-16 11:55:18 -0700291 */
292 SkStream* stream() {
293 return fStream.get();
294 }
295
msarettc0e80c12015-07-01 06:50:35 -0700296 /**
297 * If the codec has a scanline decoder, return it (no ownership change occurs)
298 * else return NULL.
299 * The returned decoder is valid while the codec exists and the client has not
300 * created a new scanline decoder.
301 */
302 SkScanlineDecoder* scanlineDecoder() {
scroggoeb602a52015-07-09 08:16:03 -0700303 return fScanlineDecoder;
msarettc0e80c12015-07-01 06:50:35 -0700304 }
305
306 /**
307 * Allow the codec subclass to detach and take ownership of the scanline decoder.
308 * This will likely be used when the scanline decoder needs to be destroyed
309 * in the destructor of the subclass.
310 */
311 SkScanlineDecoder* detachScanlineDecoder() {
scroggoeb602a52015-07-09 08:16:03 -0700312 SkScanlineDecoder* scanlineDecoder = fScanlineDecoder;
313 fScanlineDecoder = NULL;
314 return scanlineDecoder;
msarettc0e80c12015-07-01 06:50:35 -0700315 }
316
scroggof24f2242015-03-03 08:59:20 -0800317private:
scroggoeb602a52015-07-09 08:16:03 -0700318 const SkImageInfo fInfo;
319 SkAutoTDelete<SkStream> fStream;
320 bool fNeedsRewind;
321 SkScanlineDecoder* fScanlineDecoder;
scroggof24f2242015-03-03 08:59:20 -0800322};
323#endif // SkCodec_DEFINED