blob: 6d4352214cf4f2ba5a6d655f9e8bc73bbed52409 [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
bungemanf3c15b72015-08-19 11:56:48 -070011#include "../private/SkTemplates.h"
scroggoeb602a52015-07-09 08:16:03 -070012#include "SkColor.h"
Hal Canarydb683012016-11-23 08:55:18 -070013#include "SkEncodedImageFormat.h"
msarettc30c4182016-04-20 11:53:35 -070014#include "SkEncodedInfo.h"
scroggof24f2242015-03-03 08:59:20 -080015#include "SkImageInfo.h"
16#include "SkSize.h"
scroggofffeede2015-03-18 10:50:37 -070017#include "SkStream.h"
scroggof24f2242015-03-03 08:59:20 -080018#include "SkTypes.h"
msarett4984c3c2016-03-10 05:44:43 -080019#include "SkYUVSizeInfo.h"
scroggof24f2242015-03-03 08:59:20 -080020
scroggo19b91532016-10-24 09:03:26 -070021#include <vector>
22
msarettad8bcfe2016-03-07 07:09:03 -080023class SkColorSpace;
Matt Sarett313c4632016-10-20 12:35:23 -040024class SkColorSpaceXform;
scroggof24f2242015-03-03 08:59:20 -080025class SkData;
scroggocf98fa92015-11-23 08:14:40 -080026class SkPngChunkReader;
scroggoe7fc14b2015-10-02 13:14:46 -070027class SkSampler;
scroggof24f2242015-03-03 08:59:20 -080028
msarett9876ac52016-06-01 14:47:18 -070029namespace DM {
scroggo8e6c7ad2016-09-16 08:20:38 -070030class CodecSrc;
msarett9876ac52016-06-01 14:47:18 -070031class ColorCodecSrc;
32}
msarett2cee9022016-06-03 08:25:21 -070033class ColorCodecBench;
msarett9876ac52016-06-01 14:47:18 -070034
scroggof24f2242015-03-03 08:59:20 -080035/**
36 * Abstraction layer directly on top of an image codec.
37 */
Florin Malita78c212a2016-12-14 13:17:01 -050038class SK_API SkCodec : SkNoncopyable {
scroggof24f2242015-03-03 08:59:20 -080039public:
40 /**
scroggodb30be22015-12-08 18:54:13 -080041 * Minimum number of bytes that must be buffered in SkStream input.
42 *
43 * An SkStream passed to NewFromStream must be able to use this many
44 * bytes to determine the image type. Then the same SkStream must be
45 * passed to the correct decoder to read from the beginning.
46 *
47 * This can be accomplished by implementing peek() to support peeking
48 * this many bytes, or by implementing rewind() to be able to rewind()
49 * after reading this many bytes.
50 */
51 static size_t MinBufferedBytesNeeded();
52
53 /**
scroggof24f2242015-03-03 08:59:20 -080054 * If this stream represents an encoded image that we know how to decode,
55 * return an SkCodec that can decode it. Otherwise return NULL.
56 *
scroggodb30be22015-12-08 18:54:13 -080057 * As stated above, this call must be able to peek or read
58 * MinBufferedBytesNeeded to determine the correct format, and then start
59 * reading from the beginning. First it will attempt to peek, and it
60 * assumes that if less than MinBufferedBytesNeeded bytes (but more than
61 * zero) are returned, this is because the stream is shorter than this,
62 * so falling back to reading would not provide more data. If peek()
63 * returns zero bytes, this call will instead attempt to read(). This
64 * will require that the stream can be rewind()ed.
65 *
66 * If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
67 * the image is a png.
68 *
msarett7d5105c2015-12-02 07:02:41 -080069 * If the SkPngChunkReader is not NULL then:
70 * If the image is not a PNG, the SkPngChunkReader will be ignored.
71 * If the image is a PNG, the SkPngChunkReader will be reffed.
72 * If the PNG has unknown chunks, the SkPngChunkReader will be used
73 * to handle these chunks. SkPngChunkReader will be called to read
74 * any unknown chunk at any point during the creation of the codec
75 * or the decode. Note that if SkPngChunkReader fails to read a
76 * chunk, this could result in a failure to create the codec or a
77 * failure to decode the image.
78 * If the PNG does not contain unknown chunks, the SkPngChunkReader
79 * will not be used or modified.
scroggocf98fa92015-11-23 08:14:40 -080080 *
scroggof24f2242015-03-03 08:59:20 -080081 * If NULL is returned, the stream is deleted immediately. Otherwise, the
82 * SkCodec takes ownership of it, and will delete it when done with it.
83 */
scroggocf98fa92015-11-23 08:14:40 -080084 static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
scroggof24f2242015-03-03 08:59:20 -080085
86 /**
87 * If this data represents an encoded image that we know how to decode,
88 * return an SkCodec that can decode it. Otherwise return NULL.
89 *
msarett7d5105c2015-12-02 07:02:41 -080090 * If the SkPngChunkReader is not NULL then:
91 * If the image is not a PNG, the SkPngChunkReader will be ignored.
92 * If the image is a PNG, the SkPngChunkReader will be reffed.
93 * If the PNG has unknown chunks, the SkPngChunkReader will be used
94 * to handle these chunks. SkPngChunkReader will be called to read
95 * any unknown chunk at any point during the creation of the codec
96 * or the decode. Note that if SkPngChunkReader fails to read a
97 * chunk, this could result in a failure to create the codec or a
98 * failure to decode the image.
99 * If the PNG does not contain unknown chunks, the SkPngChunkReader
100 * will not be used or modified.
scroggof24f2242015-03-03 08:59:20 -0800101 */
reed42943c82016-09-12 12:01:44 -0700102 static SkCodec* NewFromData(sk_sp<SkData>, SkPngChunkReader* = NULL);
103 static SkCodec* NewFromData(SkData* data, SkPngChunkReader* reader) {
104 return NewFromData(sk_ref_sp(data), reader);
105 }
scroggof24f2242015-03-03 08:59:20 -0800106
scroggoeb602a52015-07-09 08:16:03 -0700107 virtual ~SkCodec();
108
109 /**
110 * Return the ImageInfo associated with this codec.
111 */
scroggo46c57472015-09-30 08:57:13 -0700112 const SkImageInfo& getInfo() const { return fSrcInfo; }
scroggoeb602a52015-07-09 08:16:03 -0700113
msarettc30c4182016-04-20 11:53:35 -0700114 const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
115
msarett0e6274f2016-03-21 08:04:40 -0700116 enum Origin {
117 kTopLeft_Origin = 1, // Default
118 kTopRight_Origin = 2, // Reflected across y-axis
119 kBottomRight_Origin = 3, // Rotated 180
120 kBottomLeft_Origin = 4, // Reflected across x-axis
121 kLeftTop_Origin = 5, // Reflected across x-axis, Rotated 90 CCW
122 kRightTop_Origin = 6, // Rotated 90 CW
123 kRightBottom_Origin = 7, // Reflected across x-axis, Rotated 90 CW
124 kLeftBottom_Origin = 8, // Rotated 90 CCW
125 kDefault_Origin = kTopLeft_Origin,
126 kLast_Origin = kLeftBottom_Origin,
127 };
128
129 /**
130 * Returns the image orientation stored in the EXIF data.
131 * If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
132 */
133 Origin getOrigin() const { return fOrigin; }
134
msarett6a738212016-03-04 13:27:35 -0800135 /**
scroggof24f2242015-03-03 08:59:20 -0800136 * Return a size that approximately supports the desired scale factor.
137 * The codec may not be able to scale efficiently to the exact scale
138 * factor requested, so return a size that approximates that scale.
emmaleer8f4ba762015-08-14 07:44:46 -0700139 * The returned value is the codec's suggestion for the closest valid
140 * scale that it can natively support
scroggof24f2242015-03-03 08:59:20 -0800141 */
scroggofffeede2015-03-18 10:50:37 -0700142 SkISize getScaledDimensions(float desiredScale) const {
msarettb32758a2015-08-18 13:22:46 -0700143 // Negative and zero scales are errors.
144 SkASSERT(desiredScale > 0.0f);
145 if (desiredScale <= 0.0f) {
146 return SkISize::Make(0, 0);
147 }
148
149 // Upscaling is not supported. Return the original size if the client
150 // requests an upscale.
151 if (desiredScale >= 1.0f) {
152 return this->getInfo().dimensions();
153 }
scroggofffeede2015-03-18 10:50:37 -0700154 return this->onGetScaledDimensions(desiredScale);
155 }
scroggof24f2242015-03-03 08:59:20 -0800156
scroggo1dd3ea92015-03-20 11:55:55 -0700157 /**
scroggob636b452015-07-22 07:16:20 -0700158 * Return (via desiredSubset) a subset which can decoded from this codec,
159 * or false if this codec cannot decode subsets or anything similar to
160 * desiredSubset.
161 *
162 * @param desiredSubset In/out parameter. As input, a desired subset of
163 * the original bounds (as specified by getInfo). If true is returned,
164 * desiredSubset may have been modified to a subset which is
165 * supported. Although a particular change may have been made to
166 * desiredSubset to create something supported, it is possible other
167 * changes could result in a valid subset.
168 * If false is returned, desiredSubset's value is undefined.
169 * @return true if this codec supports decoding desiredSubset (as
170 * returned, potentially modified)
171 */
172 bool getValidSubset(SkIRect* desiredSubset) const {
173 return this->onGetValidSubset(desiredSubset);
174 }
175
176 /**
scroggo1dd3ea92015-03-20 11:55:55 -0700177 * Format of the encoded data.
178 */
Hal Canarydb683012016-11-23 08:55:18 -0700179 SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
scroggo1dd3ea92015-03-20 11:55:55 -0700180
scroggo05245902015-03-25 11:11:52 -0700181 /**
scroggoeb602a52015-07-09 08:16:03 -0700182 * Used to describe the result of a call to getPixels().
183 *
184 * Result is the union of possible results from subclasses.
185 */
186 enum Result {
187 /**
188 * General return value for success.
189 */
190 kSuccess,
191 /**
192 * The input is incomplete. A partial image was generated.
193 */
194 kIncompleteInput,
195 /**
196 * The generator cannot convert to match the request, ignoring
197 * dimensions.
198 */
199 kInvalidConversion,
200 /**
201 * The generator cannot scale to requested size.
202 */
203 kInvalidScale,
204 /**
205 * Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
206 * too small, etc.
207 */
208 kInvalidParameters,
209 /**
210 * The input did not contain a valid image.
211 */
212 kInvalidInput,
213 /**
214 * Fulfilling this request requires rewinding the input, which is not
215 * supported for this input.
216 */
217 kCouldNotRewind,
218 /**
scroggo46c57472015-09-30 08:57:13 -0700219 * This method is not implemented by this codec.
220 * FIXME: Perhaps this should be kUnsupported?
scroggoeb602a52015-07-09 08:16:03 -0700221 */
222 kUnimplemented,
223 };
224
225 /**
226 * Whether or not the memory passed to getPixels is zero initialized.
227 */
228 enum ZeroInitialized {
229 /**
230 * The memory passed to getPixels is zero initialized. The SkCodec
231 * may take advantage of this by skipping writing zeroes.
232 */
233 kYes_ZeroInitialized,
234 /**
235 * The memory passed to getPixels has not been initialized to zero,
236 * so the SkCodec must write all zeroes to memory.
237 *
238 * This is the default. It will be used if no Options struct is used.
239 */
240 kNo_ZeroInitialized,
241 };
242
243 /**
244 * Additional options to pass to getPixels.
245 */
246 struct Options {
247 Options()
scroggob636b452015-07-22 07:16:20 -0700248 : fZeroInitialized(kNo_ZeroInitialized)
scroggo19b91532016-10-24 09:03:26 -0700249 , fSubset(nullptr)
250 , fFrameIndex(0)
251 , fHasPriorFrame(false)
Matt Sarettcf3f2342017-03-23 15:32:25 -0400252 , fPremulBehavior(SkTransferFunctionBehavior::kRespect)
scroggob636b452015-07-22 07:16:20 -0700253 {}
scroggoeb602a52015-07-09 08:16:03 -0700254
Matt Sarettcf3f2342017-03-23 15:32:25 -0400255 ZeroInitialized fZeroInitialized;
scroggob636b452015-07-22 07:16:20 -0700256 /**
257 * If not NULL, represents a subset of the original image to decode.
scroggob636b452015-07-22 07:16:20 -0700258 * Must be within the bounds returned by getInfo().
Hal Canarydb683012016-11-23 08:55:18 -0700259 * If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
scroggob636b452015-07-22 07:16:20 -0700260 * currently supports subsets), the top and left values must be even.
msarettfdb47572015-10-13 12:50:14 -0700261 *
scroggo8e6c7ad2016-09-16 08:20:38 -0700262 * In getPixels and incremental decode, we will attempt to decode the
263 * exact rectangular subset specified by fSubset.
msarettfdb47572015-10-13 12:50:14 -0700264 *
265 * In a scanline decode, it does not make sense to specify a subset
266 * top or subset height, since the client already controls which rows
267 * to get and which rows to skip. During scanline decodes, we will
268 * require that the subset top be zero and the subset height be equal
269 * to the full height. We will, however, use the values of
270 * subset left and subset width to decode partial scanlines on calls
271 * to getScanlines().
scroggob636b452015-07-22 07:16:20 -0700272 */
Matt Sarettcf3f2342017-03-23 15:32:25 -0400273 const SkIRect* fSubset;
scroggo19b91532016-10-24 09:03:26 -0700274
275 /**
276 * The frame to decode.
277 *
278 * Only meaningful for multi-frame images.
279 */
Matt Sarettcf3f2342017-03-23 15:32:25 -0400280 size_t fFrameIndex;
scroggo19b91532016-10-24 09:03:26 -0700281
282 /**
283 * If true, the dst already contains the prior frame.
284 *
285 * Only meaningful for multi-frame images.
286 *
287 * If fFrameIndex needs to be blended with a prior frame (as reported by
288 * getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to
289 * either true or false:
290 *
291 * true means that the prior frame is already in the dst, and this
292 * codec only needs to decode fFrameIndex and blend it with the dst.
293 * Options.fZeroInitialized is ignored in this case.
294 *
295 * false means that the dst does not contain the prior frame, so this
296 * codec needs to first decode the prior frame (which in turn may need
297 * to decode its prior frame).
298 */
Matt Sarettcf3f2342017-03-23 15:32:25 -0400299 bool fHasPriorFrame;
300
301 /**
302 * Indicates whether we should do a linear premultiply or a legacy premultiply.
303 *
304 * In the case where the dst SkColorSpace is nullptr, this flag is ignored and
305 * we will always do a legacy premultiply.
306 */
307 SkTransferFunctionBehavior fPremulBehavior;
scroggoeb602a52015-07-09 08:16:03 -0700308 };
309
310 /**
311 * Decode into the given pixels, a block of memory of size at
312 * least (info.fHeight - 1) * rowBytes + (info.fWidth *
313 * bytesPerPixel)
314 *
315 * Repeated calls to this function should give the same results,
316 * allowing the PixelRef to be immutable.
317 *
318 * @param info A description of the format (config, size)
319 * expected by the caller. This can simply be identical
320 * to the info returned by getInfo().
321 *
322 * This contract also allows the caller to specify
323 * different output-configs, which the implementation can
324 * decide to support or not.
325 *
326 * A size that does not match getInfo() implies a request
327 * to scale. If the generator cannot perform this scale,
328 * it will return kInvalidScale.
329 *
msarett50ce1f22016-07-29 06:23:33 -0700330 * If the info contains a non-null SkColorSpace, the codec
331 * will perform the appropriate color space transformation.
332 * If the caller passes in the same color space that was
333 * reported by the codec, the color space transformation is
334 * a no-op.
335 *
scroggoeb602a52015-07-09 08:16:03 -0700336 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
337 * SkPMColor values in ctable. On success the generator must copy N colors into that storage,
338 * (where N is the logical number of table entries) and set ctableCount to N.
339 *
340 * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
341 * is not null, it will be set to 0.
342 *
scroggo46c57472015-09-30 08:57:13 -0700343 * If a scanline decode is in progress, scanline mode will end, requiring the client to call
344 * startScanlineDecode() in order to return to decoding scanlines.
345 *
scroggoeb602a52015-07-09 08:16:03 -0700346 * @return Result kSuccess, or another value explaining the type of failure.
347 */
348 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*,
349 SkPMColor ctable[], int* ctableCount);
350
351 /**
352 * Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
353 * uses the default Options.
354 */
355 Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
356
msarettb714fb02016-01-22 14:46:42 -0800357 /**
358 * If decoding to YUV is supported, this returns true. Otherwise, this
359 * returns false and does not modify any of the parameters.
360 *
361 * @param sizeInfo Output parameter indicating the sizes and required
362 * allocation widths of the Y, U, and V planes.
363 * @param colorSpace Output parameter. If non-NULL this is set to kJPEG,
364 * otherwise this is ignored.
365 */
msarett4984c3c2016-03-10 05:44:43 -0800366 bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
msarettb714fb02016-01-22 14:46:42 -0800367 if (nullptr == sizeInfo) {
368 return false;
369 }
370
371 return this->onQueryYUV8(sizeInfo, colorSpace);
372 }
373
374 /**
375 * Returns kSuccess, or another value explaining the type of failure.
376 * This always attempts to perform a full decode. If the client only
377 * wants size, it should call queryYUV8().
378 *
379 * @param sizeInfo Needs to exactly match the values returned by the
380 * query, except the WidthBytes may be larger than the
381 * recommendation (but not smaller).
382 * @param planes Memory for each of the Y, U, and V planes.
383 */
msarett4984c3c2016-03-10 05:44:43 -0800384 Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
msarettb714fb02016-01-22 14:46:42 -0800385 if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||
386 nullptr == planes[2]) {
387 return kInvalidInput;
388 }
389
390 if (!this->rewindIfNeeded()) {
391 return kCouldNotRewind;
392 }
393
394 return this->onGetYUV8Planes(sizeInfo, planes);
395 }
396
scroggoeb602a52015-07-09 08:16:03 -0700397 /**
scroggo8e6c7ad2016-09-16 08:20:38 -0700398 * Prepare for an incremental decode with the specified options.
399 *
400 * This may require a rewind.
401 *
402 * @param dstInfo Info of the destination. If the dimensions do not match
403 * those of getInfo, this implies a scale.
404 * @param dst Memory to write to. Needs to be large enough to hold the subset,
405 * if present, or the full image as described in dstInfo.
406 * @param options Contains decoding options, including if memory is zero
407 * initialized and whether to decode a subset.
408 * @param ctable A pointer to a color table. When dstInfo.colorType() is
409 * kIndex8, this should be non-NULL and have enough storage for 256
410 * colors. The color table will be populated after decoding the palette.
411 * @param ctableCount A pointer to the size of the color table. When
412 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
413 * be modified to the true size of the color table (<= 256) after
414 * decoding the palette.
415 * @return Enum representing success or reason for failure.
416 */
417 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
418 const SkCodec::Options*, SkPMColor* ctable, int* ctableCount);
419
420 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
421 const SkCodec::Options* options) {
422 return this->startIncrementalDecode(dstInfo, dst, rowBytes, options, nullptr, nullptr);
423 }
424
425 Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
426 return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr, nullptr, nullptr);
427 }
428
429 /**
430 * Start/continue the incremental decode.
431 *
432 * Not valid to call before calling startIncrementalDecode().
433 *
434 * After the first call, should only be called again if more data has been
435 * provided to the source SkStream.
436 *
437 * Unlike getPixels and getScanlines, this does not do any filling. This is
438 * left up to the caller, since they may be skipping lines or continuing the
439 * decode later. In the latter case, they may choose to initialize all lines
440 * first, or only initialize the remaining lines after the first call.
441 *
442 * @param rowsDecoded Optional output variable returning the total number of
443 * lines initialized. Only meaningful if this method returns kIncompleteInput.
444 * Otherwise the implementation may not set it.
445 * Note that some implementations may have initialized this many rows, but
446 * not necessarily finished those rows (e.g. interlaced PNG). This may be
447 * useful for determining what rows the client needs to initialize.
448 * @return kSuccess if all lines requested in startIncrementalDecode have
449 * been completely decoded. kIncompleteInput otherwise.
450 */
451 Result incrementalDecode(int* rowsDecoded = nullptr) {
452 if (!fStartedIncrementalDecode) {
453 return kInvalidParameters;
454 }
455 return this->onIncrementalDecode(rowsDecoded);
456 }
457
458 /**
scroggo46c57472015-09-30 08:57:13 -0700459 * The remaining functions revolve around decoding scanlines.
460 */
461
462 /**
463 * Prepare for a scanline decode with the specified options.
464 *
465 * After this call, this class will be ready to decode the first scanline.
466 *
467 * This must be called in order to call getScanlines or skipScanlines.
468 *
469 * This may require rewinding the stream.
470 *
471 * Not all SkCodecs support this.
472 *
473 * @param dstInfo Info of the destination. If the dimensions do not match
474 * those of getInfo, this implies a scale.
475 * @param options Contains decoding options, including if memory is zero
476 * initialized.
477 * @param ctable A pointer to a color table. When dstInfo.colorType() is
478 * kIndex8, this should be non-NULL and have enough storage for 256
479 * colors. The color table will be populated after decoding the palette.
480 * @param ctableCount A pointer to the size of the color table. When
481 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
482 * be modified to the true size of the color table (<= 256) after
483 * decoding the palette.
484 * @return Enum representing success or reason for failure.
485 */
486 Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options,
msarettfdb47572015-10-13 12:50:14 -0700487 SkPMColor ctable[], int* ctableCount);
scroggo46c57472015-09-30 08:57:13 -0700488
489 /**
490 * Simplified version of startScanlineDecode() that asserts that info is NOT
491 * kIndex8_SkColorType and uses the default Options.
492 */
493 Result startScanlineDecode(const SkImageInfo& dstInfo);
494
495 /**
496 * Write the next countLines scanlines into dst.
497 *
498 * Not valid to call before calling startScanlineDecode().
499 *
500 * @param dst Must be non-null, and large enough to hold countLines
501 * scanlines of size rowBytes.
502 * @param countLines Number of lines to write.
503 * @param rowBytes Number of bytes per row. Must be large enough to hold
504 * a scanline based on the SkImageInfo used to create this object.
msarette6dd0042015-10-09 11:07:34 -0700505 * @return the number of lines successfully decoded. If this value is
506 * less than countLines, this will fill the remaining lines with a
507 * default value.
scroggo46c57472015-09-30 08:57:13 -0700508 */
msarette6dd0042015-10-09 11:07:34 -0700509 int getScanlines(void* dst, int countLines, size_t rowBytes);
scroggo46c57472015-09-30 08:57:13 -0700510
511 /**
512 * Skip count scanlines.
513 *
514 * Not valid to call before calling startScanlineDecode().
515 *
516 * The default version just calls onGetScanlines and discards the dst.
517 * NOTE: If skipped lines are the only lines with alpha, this default
518 * will make reallyHasAlpha return true, when it could have returned
519 * false.
msarette6dd0042015-10-09 11:07:34 -0700520 *
521 * @return true if the scanlines were successfully skipped
522 * false on failure, possible reasons for failure include:
523 * An incomplete input image stream.
524 * Calling this function before calling startScanlineDecode().
525 * If countLines is less than zero or so large that it moves
526 * the current scanline past the end of the image.
scroggo46c57472015-09-30 08:57:13 -0700527 */
msarette6dd0042015-10-09 11:07:34 -0700528 bool skipScanlines(int countLines);
scroggo46c57472015-09-30 08:57:13 -0700529
530 /**
531 * The order in which rows are output from the scanline decoder is not the
532 * same for all variations of all image types. This explains the possible
533 * output row orderings.
534 */
535 enum SkScanlineOrder {
536 /*
537 * By far the most common, this indicates that the image can be decoded
538 * reliably using the scanline decoder, and that rows will be output in
539 * the logical order.
540 */
541 kTopDown_SkScanlineOrder,
542
543 /*
544 * This indicates that the scanline decoder reliably outputs rows, but
545 * they will be returned in reverse order. If the scanline format is
546 * kBottomUp, the nextScanline() API can be used to determine the actual
547 * y-coordinate of the next output row, but the client is not forced
548 * to take advantage of this, given that it's not too tough to keep
549 * track independently.
550 *
551 * For full image decodes, it is safe to get all of the scanlines at
552 * once, since the decoder will handle inverting the rows as it
553 * decodes.
554 *
555 * For subset decodes and sampling, it is simplest to get and skip
556 * scanlines one at a time, using the nextScanline() API. It is
557 * possible to ask for larger chunks at a time, but this should be used
558 * with caution. As with full image decodes, the decoder will handle
559 * inverting the requested rows, but rows will still be delivered
560 * starting from the bottom of the image.
561 *
562 * Upside down bmps are an example.
563 */
564 kBottomUp_SkScanlineOrder,
scroggo46c57472015-09-30 08:57:13 -0700565 };
566
567 /**
568 * An enum representing the order in which scanlines will be returned by
569 * the scanline decoder.
msarettbe8216a2015-12-04 08:00:50 -0800570 *
571 * This is undefined before startScanlineDecode() is called.
scroggo46c57472015-09-30 08:57:13 -0700572 */
573 SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
574
575 /**
576 * Returns the y-coordinate of the next row to be returned by the scanline
msarette6dd0042015-10-09 11:07:34 -0700577 * decoder.
578 *
579 * This will equal fCurrScanline, except in the case of strangely
scroggo19b91532016-10-24 09:03:26 -0700580 * encoded image types (bottom-up bmps).
scroggo46c57472015-09-30 08:57:13 -0700581 *
582 * Results are undefined when not in scanline decoding mode.
583 */
msarette6dd0042015-10-09 11:07:34 -0700584 int nextScanline() const { return this->outputScanline(fCurrScanline); }
585
586 /**
msarettcb0d5c92015-12-03 12:23:43 -0800587 * Returns the output y-coordinate of the row that corresponds to an input
588 * y-coordinate. The input y-coordinate represents where the scanline
589 * is located in the encoded data.
msarette6dd0042015-10-09 11:07:34 -0700590 *
591 * This will equal inputScanline, except in the case of strangely
592 * encoded image types (bottom-up bmps, interlaced gifs).
593 */
594 int outputScanline(int inputScanline) const;
scroggo46c57472015-09-30 08:57:13 -0700595
scroggo19b91532016-10-24 09:03:26 -0700596 // The required frame for an independent frame is marked as
597 // kNone.
598 static constexpr size_t kNone = static_cast<size_t>(-1);
599
600 /**
601 * Information about individual frames in a multi-framed image.
602 */
603 struct FrameInfo {
604 /**
605 * The frame that this frame needs to be blended with, or
606 * kNone.
607 */
608 size_t fRequiredFrame;
609
610 /**
611 * Number of milliseconds to show this frame.
612 */
613 size_t fDuration;
Leon Scroggins III3639faa2016-12-08 11:38:58 -0500614
615 /**
616 * Whether the end marker for this frame is contained in the stream.
617 *
618 * Note: this does not guarantee that an attempt to decode will be complete.
619 * There could be an error in the stream.
620 */
621 bool fFullyReceived;
Leon Scroggins IIIa4db9be2017-04-11 10:32:02 -0400622
623 /**
624 * This is conservative; it will still return non-opaque if e.g. a
625 * color index-based frame has a color with alpha but does not use it.
626 */
627 SkAlphaType fAlphaType;
scroggo19b91532016-10-24 09:03:26 -0700628 };
629
630 /**
631 * Return info about the frames in the image.
632 *
scroggoe71b1a12016-11-01 08:28:28 -0700633 * May require reading through the stream to determine info about the
634 * frames (including the count).
scroggo19b91532016-10-24 09:03:26 -0700635 *
636 * As such, future decoding calls may require a rewind.
637 *
638 * For single-frame images, this will return an empty vector.
639 */
640 std::vector<FrameInfo> getFrameInfo() {
641 return this->onGetFrameInfo();
642 }
643
scroggoe71b1a12016-11-01 08:28:28 -0700644 static constexpr int kRepetitionCountInfinite = -1;
645
646 /**
647 * Return the number of times to repeat, if this image is animated.
648 *
649 * May require reading the stream to find the repetition count.
650 *
651 * As such, future decoding calls may require a rewind.
652 *
653 * For single-frame images, this will return 0.
654 */
655 int getRepetitionCount() {
656 return this->onGetRepetitionCount();
657 }
658
scroggof24f2242015-03-03 08:59:20 -0800659protected:
msarett6a738212016-03-04 13:27:35 -0800660 /**
661 * Takes ownership of SkStream*
msarett6a738212016-03-04 13:27:35 -0800662 */
msarettc30c4182016-04-20 11:53:35 -0700663 SkCodec(int width,
664 int height,
665 const SkEncodedInfo&,
msarett0e6274f2016-03-21 08:04:40 -0700666 SkStream*,
Matt Sarett7f650bd2016-10-30 21:25:34 -0400667 sk_sp<SkColorSpace>,
msarett0e6274f2016-03-21 08:04:40 -0700668 Origin = kTopLeft_Origin);
scroggof24f2242015-03-03 08:59:20 -0800669
msarett549ca322016-08-17 08:54:08 -0700670 /**
671 * Takes ownership of SkStream*
672 * Allows the subclass to set the recommended SkImageInfo
673 */
674 SkCodec(const SkEncodedInfo&,
675 const SkImageInfo&,
676 SkStream*,
677 Origin = kTopLeft_Origin);
678
msarettb714fb02016-01-22 14:46:42 -0800679 virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
scroggof24f2242015-03-03 08:59:20 -0800680 // By default, scaling is not supported.
halcanaryb880d7f2015-03-26 06:29:03 -0700681 return this->getInfo().dimensions();
scroggof24f2242015-03-03 08:59:20 -0800682 }
683
scroggoe7fc14b2015-10-02 13:14:46 -0700684 // FIXME: What to do about subsets??
685 /**
686 * Subclasses should override if they support dimensions other than the
687 * srcInfo's.
688 */
689 virtual bool onDimensionsSupported(const SkISize&) {
690 return false;
691 }
692
Hal Canarydb683012016-11-23 08:55:18 -0700693 virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
scroggo1dd3ea92015-03-20 11:55:55 -0700694
msarette6dd0042015-10-09 11:07:34 -0700695 /**
696 * @param rowsDecoded When the encoded image stream is incomplete, this function
697 * will return kIncompleteInput and rowsDecoded will be set to
698 * the number of scanlines that were successfully decoded.
699 * This will allow getPixels() to fill the uninitialized memory.
700 */
scroggoeb602a52015-07-09 08:16:03 -0700701 virtual Result onGetPixels(const SkImageInfo& info,
702 void* pixels, size_t rowBytes, const Options&,
msarette6dd0042015-10-09 11:07:34 -0700703 SkPMColor ctable[], int* ctableCount,
704 int* rowsDecoded) = 0;
scroggoeb602a52015-07-09 08:16:03 -0700705
msarett4984c3c2016-03-10 05:44:43 -0800706 virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const {
msarettb714fb02016-01-22 14:46:42 -0800707 return false;
708 }
709
msarett4984c3c2016-03-10 05:44:43 -0800710 virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {
msarettb714fb02016-01-22 14:46:42 -0800711 return kUnimplemented;
712 }
713
714 virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
scroggob636b452015-07-22 07:16:20 -0700715 // By default, subsets are not supported.
716 return false;
717 }
718
msarett90c4d5f2015-12-10 13:09:24 -0800719 /**
scroggof24f2242015-03-03 08:59:20 -0800720 * If the stream was previously read, attempt to rewind.
scroggob427db12015-08-12 07:24:13 -0700721 *
722 * If the stream needed to be rewound, call onRewind.
723 * @returns true if the codec is at the right position and can be used.
724 * false if there was a failure to rewind.
halcanarya096d7a2015-03-27 12:16:53 -0700725 *
scroggo3a7701c2015-09-30 09:15:14 -0700726 * This is called by getPixels() and start(). Subclasses may call if they
727 * need to rewind at another time.
scroggof24f2242015-03-03 08:59:20 -0800728 */
scroggob427db12015-08-12 07:24:13 -0700729 bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
730
731 /**
732 * Called by rewindIfNeeded, if the stream needed to be rewound.
733 *
734 * Subclasses should do any set up needed after a rewind.
735 */
736 virtual bool onRewind() {
737 return true;
738 }
scroggof24f2242015-03-03 08:59:20 -0800739
msarettc0e80c12015-07-01 06:50:35 -0700740 /**
msarette6dd0042015-10-09 11:07:34 -0700741 * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
742 * scanlines. This allows the subclass to indicate what value to fill with.
743 *
msarettf7eb6fc2016-09-13 09:04:11 -0700744 * @param dstInfo Describes the destination.
msarette6dd0042015-10-09 11:07:34 -0700745 * @return The value with which to fill uninitialized pixels.
746 *
msarettf7eb6fc2016-09-13 09:04:11 -0700747 * Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor,
748 * a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table,
749 * depending on the color type.
msarette6dd0042015-10-09 11:07:34 -0700750 */
msarettf7eb6fc2016-09-13 09:04:11 -0700751 uint64_t getFillValue(const SkImageInfo& dstInfo) const {
752 return this->onGetFillValue(dstInfo);
msarette6dd0042015-10-09 11:07:34 -0700753 }
754
755 /**
756 * Some subclasses will override this function, but this is a useful default for the color
msarettf7eb6fc2016-09-13 09:04:11 -0700757 * types that we support. Note that for color types that do not use the full 64-bits,
msarette6dd0042015-10-09 11:07:34 -0700758 * we will simply take the low bits of the fill value.
759 *
msarettf7eb6fc2016-09-13 09:04:11 -0700760 * The defaults are:
761 * kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type
scroggoc5560be2016-02-03 09:42:42 -0800762 * kN32_SkColorType: Transparent or Black, depending on the src alpha type
msarette6dd0042015-10-09 11:07:34 -0700763 * kRGB_565_SkColorType: Black
764 * kGray_8_SkColorType: Black
765 * kIndex_8_SkColorType: First color in color table
766 */
msarettf7eb6fc2016-09-13 09:04:11 -0700767 virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const;
msarette6dd0042015-10-09 11:07:34 -0700768
769 /**
msarett74114382015-03-16 11:55:18 -0700770 * Get method for the input stream
msarett74114382015-03-16 11:55:18 -0700771 */
772 SkStream* stream() {
773 return fStream.get();
774 }
775
scroggo46c57472015-09-30 08:57:13 -0700776 /**
777 * The remaining functions revolve around decoding scanlines.
778 */
779
780 /**
781 * Most images types will be kTopDown and will not need to override this function.
782 */
783 virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
784
scroggo46c57472015-09-30 08:57:13 -0700785 const SkImageInfo& dstInfo() const { return fDstInfo; }
786
787 const SkCodec::Options& options() const { return fOptions; }
788
msarettcb0d5c92015-12-03 12:23:43 -0800789 /**
790 * Returns the number of scanlines that have been decoded so far.
791 * This is unaffected by the SkScanlineOrder.
792 *
793 * Returns -1 if we have not started a scanline decode.
794 */
795 int currScanline() const { return fCurrScanline; }
796
msarette6dd0042015-10-09 11:07:34 -0700797 virtual int onOutputScanline(int inputScanline) const;
798
Matt Sarettcf3f2342017-03-23 15:32:25 -0400799 bool initializeColorXform(const SkImageInfo& dstInfo,
800 SkTransferFunctionBehavior premulBehavior);
Matt Sarett313c4632016-10-20 12:35:23 -0400801 SkColorSpaceXform* colorXform() const { return fColorXform.get(); }
802
scroggo19b91532016-10-24 09:03:26 -0700803 virtual std::vector<FrameInfo> onGetFrameInfo() {
804 // empty vector - this is not animated.
Leon Scroggins III0dd69872016-12-02 09:23:03 -0500805 return std::vector<FrameInfo>{};
scroggo19b91532016-10-24 09:03:26 -0700806 }
807
scroggoe71b1a12016-11-01 08:28:28 -0700808 virtual int onGetRepetitionCount() {
809 return 0;
810 }
811
raftiasd737bee2016-12-08 10:53:24 -0500812 void setUnsupportedICC(bool SkDEBUGCODE(value)) { SkDEBUGCODE(fUnsupportedICC = value); }
813
Matt Sarett313c4632016-10-20 12:35:23 -0400814private:
815 const SkEncodedInfo fEncodedInfo;
816 const SkImageInfo fSrcInfo;
bungeman6bd52842016-10-27 09:30:08 -0700817 std::unique_ptr<SkStream> fStream;
Matt Sarett313c4632016-10-20 12:35:23 -0400818 bool fNeedsRewind;
819 const Origin fOrigin;
820
821 SkImageInfo fDstInfo;
822 SkCodec::Options fOptions;
823 std::unique_ptr<SkColorSpaceXform> fColorXform;
scroggo8e6c7ad2016-09-16 08:20:38 -0700824
825 // Only meaningful during scanline decodes.
Matt Sarett313c4632016-10-20 12:35:23 -0400826 int fCurrScanline;
scroggo46c57472015-09-30 08:57:13 -0700827
Matt Sarett313c4632016-10-20 12:35:23 -0400828 bool fStartedIncrementalDecode;
raftiasd737bee2016-12-08 10:53:24 -0500829#ifdef SK_DEBUG
830 bool fUnsupportedICC = false;
831#endif
scroggo8e6c7ad2016-09-16 08:20:38 -0700832
scroggoe7fc14b2015-10-02 13:14:46 -0700833 /**
834 * Return whether these dimensions are supported as a scale.
835 *
836 * The codec may choose to cache the information about scale and subset.
837 * Either way, the same information will be passed to onGetPixels/onStart
838 * on success.
839 *
840 * This must return true for a size returned from getScaledDimensions.
841 */
842 bool dimensionsSupported(const SkISize& dim) {
843 return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
844 }
845
scroggo46c57472015-09-30 08:57:13 -0700846 // Methods for scanline decoding.
msarett33bee092015-11-11 12:43:07 -0800847 virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
848 const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) {
scroggo46c57472015-09-30 08:57:13 -0700849 return kUnimplemented;
850 }
851
scroggo8e6c7ad2016-09-16 08:20:38 -0700852 virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
853 const SkCodec::Options&, SkPMColor*, int*) {
854 return kUnimplemented;
855 }
856
857 virtual Result onIncrementalDecode(int*) {
858 return kUnimplemented;
859 }
860
861
msarett9b9497e2016-02-11 13:29:36 -0800862 virtual bool onSkipScanlines(int /*countLines*/) { return false; }
scroggo46c57472015-09-30 08:57:13 -0700863
msarett33bee092015-11-11 12:43:07 -0800864 virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
msarette6dd0042015-10-09 11:07:34 -0700865
866 /**
867 * On an incomplete decode, getPixels() and getScanlines() will call this function
868 * to fill any uinitialized memory.
869 *
870 * @param dstInfo Contains the destination color type
871 * Contains the destination alpha type
872 * Contains the destination width
873 * The height stored in this info is unused
874 * @param dst Pointer to the start of destination pixel memory
875 * @param rowBytes Stride length in destination pixel memory
876 * @param zeroInit Indicates if memory is zero initialized
877 * @param linesRequested Number of lines that the client requested
878 * @param linesDecoded Number of lines that were successfully decoded
879 */
880 void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
881 ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
scroggo46c57472015-09-30 08:57:13 -0700882
scroggoe7fc14b2015-10-02 13:14:46 -0700883 /**
884 * Return an object which will allow forcing scanline decodes to sample in X.
885 *
886 * May create a sampler, if one is not currently being used. Otherwise, does
887 * not affect ownership.
888 *
scroggo19b91532016-10-24 09:03:26 -0700889 * Only valid during scanline decoding or incremental decoding.
scroggoe7fc14b2015-10-02 13:14:46 -0700890 */
msarett33bee092015-11-11 12:43:07 -0800891 virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
scroggoe7fc14b2015-10-02 13:14:46 -0700892
scroggo8e6c7ad2016-09-16 08:20:38 -0700893 friend class DM::CodecSrc; // for fillIncompleteImage
msarett3d9d7a72015-10-21 10:27:10 -0700894 friend class SkSampledCodec;
msarettbe8216a2015-12-04 08:00:50 -0800895 friend class SkIcoCodec;
raftiasd737bee2016-12-08 10:53:24 -0500896 friend struct Sniffer; // for fUnsupportedICC
897 friend class AutoCleanPng; // for setUnsupportedICC()
scroggof24f2242015-03-03 08:59:20 -0800898};
899#endif // SkCodec_DEFINED