• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SkCodec_DEFINED
9 #define SkCodec_DEFINED
10 
11 #include "../private/SkTemplates.h"
12 #include "../private/SkEncodedInfo.h"
13 #include "SkCodecAnimation.h"
14 #include "SkColor.h"
15 #include "SkColorSpaceXform.h"
16 #include "SkEncodedImageFormat.h"
17 #include "SkEncodedOrigin.h"
18 #include "SkImageInfo.h"
19 #include "SkPixmap.h"
20 #include "SkSize.h"
21 #include "SkStream.h"
22 #include "SkTypes.h"
23 #include "SkYUVSizeInfo.h"
24 
25 #include <vector>
26 
27 class SkColorSpace;
28 class SkData;
29 class SkFrameHolder;
30 class SkPngChunkReader;
31 class SkSampler;
32 
33 namespace DM {
34 class CodecSrc;
35 class ColorCodecSrc;
36 }
37 class ColorCodecBench;
38 
39 /**
40  *  Abstraction layer directly on top of an image codec.
41  */
42 class SK_API SkCodec : SkNoncopyable {
43 public:
44     /**
45      *  Minimum number of bytes that must be buffered in SkStream input.
46      *
47      *  An SkStream passed to NewFromStream must be able to use this many
48      *  bytes to determine the image type. Then the same SkStream must be
49      *  passed to the correct decoder to read from the beginning.
50      *
51      *  This can be accomplished by implementing peek() to support peeking
52      *  this many bytes, or by implementing rewind() to be able to rewind()
53      *  after reading this many bytes.
54      */
MinBufferedBytesNeeded()55     static constexpr size_t MinBufferedBytesNeeded() { return 32; }
56 
57     /**
58      *  Error codes for various SkCodec methods.
59      */
60     enum Result {
61         /**
62          *  General return value for success.
63          */
64         kSuccess,
65         /**
66          *  The input is incomplete. A partial image was generated.
67          */
68         kIncompleteInput,
69         /**
70          *  Like kIncompleteInput, except the input had an error.
71          *
72          *  If returned from an incremental decode, decoding cannot continue,
73          *  even with more data.
74          */
75         kErrorInInput,
76         /**
77          *  The generator cannot convert to match the request, ignoring
78          *  dimensions.
79          */
80         kInvalidConversion,
81         /**
82          *  The generator cannot scale to requested size.
83          */
84         kInvalidScale,
85         /**
86          *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
87          *  too small, etc.
88          */
89         kInvalidParameters,
90         /**
91          *  The input did not contain a valid image.
92          */
93         kInvalidInput,
94         /**
95          *  Fulfilling this request requires rewinding the input, which is not
96          *  supported for this input.
97          */
98         kCouldNotRewind,
99         /**
100          *  An internal error, such as OOM.
101          */
102         kInternalError,
103         /**
104          *  This method is not implemented by this codec.
105          *  FIXME: Perhaps this should be kUnsupported?
106          */
107         kUnimplemented,
108     };
109 
110     /**
111      *  Readable string representing the error code.
112      */
113     static const char* ResultToString(Result);
114 
115     /**
116      *  If this stream represents an encoded image that we know how to decode,
117      *  return an SkCodec that can decode it. Otherwise return NULL.
118      *
119      *  As stated above, this call must be able to peek or read
120      *  MinBufferedBytesNeeded to determine the correct format, and then start
121      *  reading from the beginning. First it will attempt to peek, and it
122      *  assumes that if less than MinBufferedBytesNeeded bytes (but more than
123      *  zero) are returned, this is because the stream is shorter than this,
124      *  so falling back to reading would not provide more data. If peek()
125      *  returns zero bytes, this call will instead attempt to read(). This
126      *  will require that the stream can be rewind()ed.
127      *
128      *  If Result is not NULL, it will be set to either kSuccess if an SkCodec
129      *  is returned or a reason for the failure if NULL is returned.
130      *
131      *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
132      *  the image is a png.
133      *
134      *  If the SkPngChunkReader is not NULL then:
135      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
136      *      If the image is a PNG, the SkPngChunkReader will be reffed.
137      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
138      *      to handle these chunks.  SkPngChunkReader will be called to read
139      *      any unknown chunk at any point during the creation of the codec
140      *      or the decode.  Note that if SkPngChunkReader fails to read a
141      *      chunk, this could result in a failure to create the codec or a
142      *      failure to decode the image.
143      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
144      *      will not be used or modified.
145      *
146      *  If NULL is returned, the stream is deleted immediately. Otherwise, the
147      *  SkCodec takes ownership of it, and will delete it when done with it.
148      */
149     static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result* = nullptr,
150                                                    SkPngChunkReader* = nullptr);
151 
152     /**
153      *  If this data represents an encoded image that we know how to decode,
154      *  return an SkCodec that can decode it. Otherwise return NULL.
155      *
156      *  If the SkPngChunkReader is not NULL then:
157      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
158      *      If the image is a PNG, the SkPngChunkReader will be reffed.
159      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
160      *      to handle these chunks.  SkPngChunkReader will be called to read
161      *      any unknown chunk at any point during the creation of the codec
162      *      or the decode.  Note that if SkPngChunkReader fails to read a
163      *      chunk, this could result in a failure to create the codec or a
164      *      failure to decode the image.
165      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
166      *      will not be used or modified.
167      */
168     static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
169 
170     virtual ~SkCodec();
171 
172     /**
173      *  Return the ImageInfo associated with this codec.
174      */
getInfo()175     const SkImageInfo& getInfo() const { return fSrcInfo; }
176 
177     /**
178      *  Returns the image orientation stored in the EXIF data.
179      *  If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
180      */
getOrigin()181     SkEncodedOrigin getOrigin() const { return fOrigin; }
182 
183     /**
184      *  Return a size that approximately supports the desired scale factor.
185      *  The codec may not be able to scale efficiently to the exact scale
186      *  factor requested, so return a size that approximates that scale.
187      *  The returned value is the codec's suggestion for the closest valid
188      *  scale that it can natively support
189      */
getScaledDimensions(float desiredScale)190     SkISize getScaledDimensions(float desiredScale) const {
191         // Negative and zero scales are errors.
192         SkASSERT(desiredScale > 0.0f);
193         if (desiredScale <= 0.0f) {
194             return SkISize::Make(0, 0);
195         }
196 
197         // Upscaling is not supported. Return the original size if the client
198         // requests an upscale.
199         if (desiredScale >= 1.0f) {
200             return this->getInfo().dimensions();
201         }
202         return this->onGetScaledDimensions(desiredScale);
203     }
204 
205     /**
206      *  Return (via desiredSubset) a subset which can decoded from this codec,
207      *  or false if this codec cannot decode subsets or anything similar to
208      *  desiredSubset.
209      *
210      *  @param desiredSubset In/out parameter. As input, a desired subset of
211      *      the original bounds (as specified by getInfo). If true is returned,
212      *      desiredSubset may have been modified to a subset which is
213      *      supported. Although a particular change may have been made to
214      *      desiredSubset to create something supported, it is possible other
215      *      changes could result in a valid subset.
216      *      If false is returned, desiredSubset's value is undefined.
217      *  @return true if this codec supports decoding desiredSubset (as
218      *      returned, potentially modified)
219      */
getValidSubset(SkIRect * desiredSubset)220     bool getValidSubset(SkIRect* desiredSubset) const {
221         return this->onGetValidSubset(desiredSubset);
222     }
223 
224     /**
225      *  Format of the encoded data.
226      */
getEncodedFormat()227     SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
228 
229     /**
230      *  Whether or not the memory passed to getPixels is zero initialized.
231      */
232     enum ZeroInitialized {
233         /**
234          *  The memory passed to getPixels is zero initialized. The SkCodec
235          *  may take advantage of this by skipping writing zeroes.
236          */
237         kYes_ZeroInitialized,
238         /**
239          *  The memory passed to getPixels has not been initialized to zero,
240          *  so the SkCodec must write all zeroes to memory.
241          *
242          *  This is the default. It will be used if no Options struct is used.
243          */
244         kNo_ZeroInitialized,
245     };
246 
247     /**
248      *  Additional options to pass to getPixels.
249      */
250     struct Options {
OptionsOptions251         Options()
252             : fZeroInitialized(kNo_ZeroInitialized)
253             , fSubset(nullptr)
254             , fFrameIndex(0)
255             , fPriorFrame(kNone)
256             , fPremulBehavior(SkTransferFunctionBehavior::kRespect)
257         {}
258 
259         ZeroInitialized            fZeroInitialized;
260         /**
261          *  If not NULL, represents a subset of the original image to decode.
262          *  Must be within the bounds returned by getInfo().
263          *  If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
264          *  currently supports subsets), the top and left values must be even.
265          *
266          *  In getPixels and incremental decode, we will attempt to decode the
267          *  exact rectangular subset specified by fSubset.
268          *
269          *  In a scanline decode, it does not make sense to specify a subset
270          *  top or subset height, since the client already controls which rows
271          *  to get and which rows to skip.  During scanline decodes, we will
272          *  require that the subset top be zero and the subset height be equal
273          *  to the full height.  We will, however, use the values of
274          *  subset left and subset width to decode partial scanlines on calls
275          *  to getScanlines().
276          */
277         const SkIRect*             fSubset;
278 
279         /**
280          *  The frame to decode.
281          *
282          *  Only meaningful for multi-frame images.
283          */
284         int                        fFrameIndex;
285 
286         /**
287          *  If not kNone, the dst already contains the prior frame at this index.
288          *
289          *  Only meaningful for multi-frame images.
290          *
291          *  If fFrameIndex needs to be blended with a prior frame (as reported by
292          *  getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to
293          *  any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to
294          *  indicate that that frame is already in the dst. Options.fZeroInitialized
295          *  is ignored in this case.
296          *
297          *  If set to kNone, the codec will decode any necessary required frame(s) first.
298          */
299         int                        fPriorFrame;
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;
308     };
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      *
330      *         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      *
336      *  If a scanline decode is in progress, scanline mode will end, requiring the client to call
337      *  startScanlineDecode() in order to return to decoding scanlines.
338      *
339      *  @return Result kSuccess, or another value explaining the type of failure.
340      */
341     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*);
342 
343     /**
344      *  Simplified version of getPixels() that uses the default Options.
345      */
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes)346     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
347         return this->getPixels(info, pixels, rowBytes, nullptr);
348     }
349 
350     Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {
351         return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
352     }
353 
354     /**
355      *  If decoding to YUV is supported, this returns true.  Otherwise, this
356      *  returns false and does not modify any of the parameters.
357      *
358      *  @param sizeInfo   Output parameter indicating the sizes and required
359      *                    allocation widths of the Y, U, and V planes.
360      *  @param colorSpace Output parameter.  If non-NULL this is set to kJPEG,
361      *                    otherwise this is ignored.
362      */
queryYUV8(SkYUVSizeInfo * sizeInfo,SkYUVColorSpace * colorSpace)363     bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
364         if (nullptr == sizeInfo) {
365             return false;
366         }
367 
368         return this->onQueryYUV8(sizeInfo, colorSpace);
369     }
370 
371     /**
372      *  Returns kSuccess, or another value explaining the type of failure.
373      *  This always attempts to perform a full decode.  If the client only
374      *  wants size, it should call queryYUV8().
375      *
376      *  @param sizeInfo   Needs to exactly match the values returned by the
377      *                    query, except the WidthBytes may be larger than the
378      *                    recommendation (but not smaller).
379      *  @param planes     Memory for each of the Y, U, and V planes.
380      */
getYUV8Planes(const SkYUVSizeInfo & sizeInfo,void * planes[3])381     Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
382         if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||
383                 nullptr == planes[2]) {
384             return kInvalidInput;
385         }
386 
387         if (!this->rewindIfNeeded()) {
388             return kCouldNotRewind;
389         }
390 
391         return this->onGetYUV8Planes(sizeInfo, planes);
392     }
393 
394     /**
395      *  Prepare for an incremental decode with the specified options.
396      *
397      *  This may require a rewind.
398      *
399      *  @param dstInfo Info of the destination. If the dimensions do not match
400      *      those of getInfo, this implies a scale.
401      *  @param dst Memory to write to. Needs to be large enough to hold the subset,
402      *      if present, or the full image as described in dstInfo.
403      *  @param options Contains decoding options, including if memory is zero
404      *      initialized and whether to decode a subset.
405      *  @return Enum representing success or reason for failure.
406      */
407     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
408             const Options*);
409 
startIncrementalDecode(const SkImageInfo & dstInfo,void * dst,size_t rowBytes)410     Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
411         return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);
412     }
413 
414     /**
415      *  Start/continue the incremental decode.
416      *
417      *  Not valid to call before calling startIncrementalDecode().
418      *
419      *  After the first call, should only be called again if more data has been
420      *  provided to the source SkStream.
421      *
422      *  Unlike getPixels and getScanlines, this does not do any filling. This is
423      *  left up to the caller, since they may be skipping lines or continuing the
424      *  decode later. In the latter case, they may choose to initialize all lines
425      *  first, or only initialize the remaining lines after the first call.
426      *
427      *  @param rowsDecoded Optional output variable returning the total number of
428      *      lines initialized. Only meaningful if this method returns kIncompleteInput.
429      *      Otherwise the implementation may not set it.
430      *      Note that some implementations may have initialized this many rows, but
431      *      not necessarily finished those rows (e.g. interlaced PNG). This may be
432      *      useful for determining what rows the client needs to initialize.
433      *  @return kSuccess if all lines requested in startIncrementalDecode have
434      *      been completely decoded. kIncompleteInput otherwise.
435      */
436     Result incrementalDecode(int* rowsDecoded = nullptr) {
437         if (!fStartedIncrementalDecode) {
438             return kInvalidParameters;
439         }
440         return this->onIncrementalDecode(rowsDecoded);
441     }
442 
443     /**
444      * The remaining functions revolve around decoding scanlines.
445      */
446 
447     /**
448      *  Prepare for a scanline decode with the specified options.
449      *
450      *  After this call, this class will be ready to decode the first scanline.
451      *
452      *  This must be called in order to call getScanlines or skipScanlines.
453      *
454      *  This may require rewinding the stream.
455      *
456      *  Not all SkCodecs support this.
457      *
458      *  @param dstInfo Info of the destination. If the dimensions do not match
459      *      those of getInfo, this implies a scale.
460      *  @param options Contains decoding options, including if memory is zero
461      *      initialized.
462      *  @return Enum representing success or reason for failure.
463      */
464     Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options);
465 
466     /**
467      *  Simplified version of startScanlineDecode() that uses the default Options.
468      */
startScanlineDecode(const SkImageInfo & dstInfo)469     Result startScanlineDecode(const SkImageInfo& dstInfo) {
470         return this->startScanlineDecode(dstInfo, nullptr);
471     }
472 
473     /**
474      *  Write the next countLines scanlines into dst.
475      *
476      *  Not valid to call before calling startScanlineDecode().
477      *
478      *  @param dst Must be non-null, and large enough to hold countLines
479      *      scanlines of size rowBytes.
480      *  @param countLines Number of lines to write.
481      *  @param rowBytes Number of bytes per row. Must be large enough to hold
482      *      a scanline based on the SkImageInfo used to create this object.
483      *  @return the number of lines successfully decoded.  If this value is
484      *      less than countLines, this will fill the remaining lines with a
485      *      default value.
486      */
487     int getScanlines(void* dst, int countLines, size_t rowBytes);
488 
489     /**
490      *  Skip count scanlines.
491      *
492      *  Not valid to call before calling startScanlineDecode().
493      *
494      *  The default version just calls onGetScanlines and discards the dst.
495      *  NOTE: If skipped lines are the only lines with alpha, this default
496      *  will make reallyHasAlpha return true, when it could have returned
497      *  false.
498      *
499      *  @return true if the scanlines were successfully skipped
500      *          false on failure, possible reasons for failure include:
501      *              An incomplete input image stream.
502      *              Calling this function before calling startScanlineDecode().
503      *              If countLines is less than zero or so large that it moves
504      *                  the current scanline past the end of the image.
505      */
506     bool skipScanlines(int countLines);
507 
508     /**
509      *  The order in which rows are output from the scanline decoder is not the
510      *  same for all variations of all image types.  This explains the possible
511      *  output row orderings.
512      */
513     enum SkScanlineOrder {
514         /*
515          * By far the most common, this indicates that the image can be decoded
516          * reliably using the scanline decoder, and that rows will be output in
517          * the logical order.
518          */
519         kTopDown_SkScanlineOrder,
520 
521         /*
522          * This indicates that the scanline decoder reliably outputs rows, but
523          * they will be returned in reverse order.  If the scanline format is
524          * kBottomUp, the nextScanline() API can be used to determine the actual
525          * y-coordinate of the next output row, but the client is not forced
526          * to take advantage of this, given that it's not too tough to keep
527          * track independently.
528          *
529          * For full image decodes, it is safe to get all of the scanlines at
530          * once, since the decoder will handle inverting the rows as it
531          * decodes.
532          *
533          * For subset decodes and sampling, it is simplest to get and skip
534          * scanlines one at a time, using the nextScanline() API.  It is
535          * possible to ask for larger chunks at a time, but this should be used
536          * with caution.  As with full image decodes, the decoder will handle
537          * inverting the requested rows, but rows will still be delivered
538          * starting from the bottom of the image.
539          *
540          * Upside down bmps are an example.
541          */
542         kBottomUp_SkScanlineOrder,
543     };
544 
545     /**
546      *  An enum representing the order in which scanlines will be returned by
547      *  the scanline decoder.
548      *
549      *  This is undefined before startScanlineDecode() is called.
550      */
getScanlineOrder()551     SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
552 
553     /**
554      *  Returns the y-coordinate of the next row to be returned by the scanline
555      *  decoder.
556      *
557      *  This will equal fCurrScanline, except in the case of strangely
558      *  encoded image types (bottom-up bmps).
559      *
560      *  Results are undefined when not in scanline decoding mode.
561      */
nextScanline()562     int nextScanline() const { return this->outputScanline(fCurrScanline); }
563 
564     /**
565      *  Returns the output y-coordinate of the row that corresponds to an input
566      *  y-coordinate.  The input y-coordinate represents where the scanline
567      *  is located in the encoded data.
568      *
569      *  This will equal inputScanline, except in the case of strangely
570      *  encoded image types (bottom-up bmps, interlaced gifs).
571      */
572     int outputScanline(int inputScanline) const;
573 
574     /**
575      *  Return the number of frames in the image.
576      *
577      *  May require reading through the stream.
578      */
getFrameCount()579     int getFrameCount() {
580         return this->onGetFrameCount();
581     }
582 
583     // The required frame for an independent frame is marked as
584     // kNone.
585     static constexpr int kNone = -1;
586 
587     /**
588      *  Information about individual frames in a multi-framed image.
589      */
590     struct FrameInfo {
591         /**
592          *  The frame that this frame needs to be blended with, or
593          *  kNone if this frame is independent.
594          *
595          *  Note that this is the *earliest* frame that can be used
596          *  for blending. Any frame from [fRequiredFrame, i) can be
597          *  used, unless its fDisposalMethod is kRestorePrevious.
598          */
599         int fRequiredFrame;
600 
601         /**
602          *  Number of milliseconds to show this frame.
603          */
604         int fDuration;
605 
606         /**
607          *  Whether the end marker for this frame is contained in the stream.
608          *
609          *  Note: this does not guarantee that an attempt to decode will be complete.
610          *  There could be an error in the stream.
611          */
612         bool fFullyReceived;
613 
614         /**
615          *  This is conservative; it will still return non-opaque if e.g. a
616          *  color index-based frame has a color with alpha but does not use it.
617          */
618         SkAlphaType fAlphaType;
619 
620         /**
621          *  How this frame should be modified before decoding the next one.
622          */
623         SkCodecAnimation::DisposalMethod fDisposalMethod;
624     };
625 
626     /**
627      *  Return info about a single frame.
628      *
629      *  Only supported by multi-frame images. Does not read through the stream,
630      *  so it should be called after getFrameCount() to parse any frames that
631      *  have not already been parsed.
632      */
getFrameInfo(int index,FrameInfo * info)633     bool getFrameInfo(int index, FrameInfo* info) const {
634         if (index < 0) {
635             return false;
636         }
637         return this->onGetFrameInfo(index, info);
638     }
639 
640     /**
641      *  Return info about all the frames in the image.
642      *
643      *  May require reading through the stream to determine info about the
644      *  frames (including the count).
645      *
646      *  As such, future decoding calls may require a rewind.
647      *
648      *  For single-frame images, this will return an empty vector.
649      */
650     std::vector<FrameInfo> getFrameInfo();
651 
652     static constexpr int kRepetitionCountInfinite = -1;
653 
654     /**
655      *  Return the number of times to repeat, if this image is animated.
656      *
657      *  May require reading the stream to find the repetition count.
658      *
659      *  As such, future decoding calls may require a rewind.
660      *
661      *  For single-frame images, this will return 0.
662      */
getRepetitionCount()663     int getRepetitionCount() {
664         return this->onGetRepetitionCount();
665     }
666 
667 protected:
getEncodedInfo()668     const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
669 
670     using XformFormat = SkColorSpaceXform::ColorFormat;
671 
672     SkCodec(int width,
673             int height,
674             const SkEncodedInfo&,
675             XformFormat srcFormat,
676             std::unique_ptr<SkStream>,
677             sk_sp<SkColorSpace>,
678             SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
679 
680     /**
681      *  Allows the subclass to set the recommended SkImageInfo
682      */
683     SkCodec(const SkEncodedInfo&,
684             const SkImageInfo&,
685             XformFormat srcFormat,
686             std::unique_ptr<SkStream>,
687             SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
688 
onGetScaledDimensions(float)689     virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
690         // By default, scaling is not supported.
691         return this->getInfo().dimensions();
692     }
693 
694     // FIXME: What to do about subsets??
695     /**
696      *  Subclasses should override if they support dimensions other than the
697      *  srcInfo's.
698      */
onDimensionsSupported(const SkISize &)699     virtual bool onDimensionsSupported(const SkISize&) {
700         return false;
701     }
702 
703     virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
704 
705     /**
706      * @param rowsDecoded When the encoded image stream is incomplete, this function
707      *                    will return kIncompleteInput and rowsDecoded will be set to
708      *                    the number of scanlines that were successfully decoded.
709      *                    This will allow getPixels() to fill the uninitialized memory.
710      */
711     virtual Result onGetPixels(const SkImageInfo& info,
712                                void* pixels, size_t rowBytes, const Options&,
713                                int* rowsDecoded) = 0;
714 
onQueryYUV8(SkYUVSizeInfo *,SkYUVColorSpace *)715     virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const {
716         return false;
717     }
718 
onGetYUV8Planes(const SkYUVSizeInfo &,void * [3])719     virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {
720         return kUnimplemented;
721     }
722 
onGetValidSubset(SkIRect *)723     virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
724         // By default, subsets are not supported.
725         return false;
726     }
727 
728     /**
729      *  If the stream was previously read, attempt to rewind.
730      *
731      *  If the stream needed to be rewound, call onRewind.
732      *  @returns true if the codec is at the right position and can be used.
733      *      false if there was a failure to rewind.
734      *
735      *  This is called by getPixels() and start(). Subclasses may call if they
736      *  need to rewind at another time.
737      */
738     bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
739 
740     /**
741      *  Called by rewindIfNeeded, if the stream needed to be rewound.
742      *
743      *  Subclasses should do any set up needed after a rewind.
744      */
onRewind()745     virtual bool onRewind() {
746         return true;
747     }
748 
749     /**
750      * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
751      * scanlines.  This allows the subclass to indicate what value to fill with.
752      *
753      * @param dstInfo   Describes the destination.
754      * @return          The value with which to fill uninitialized pixels.
755      *
756      * Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor,
757      * a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table,
758      * depending on the color type.
759      */
getFillValue(const SkImageInfo & dstInfo)760     uint64_t getFillValue(const SkImageInfo& dstInfo) const {
761         return this->onGetFillValue(dstInfo);
762     }
763 
764     /**
765      * Some subclasses will override this function, but this is a useful default for the color
766      * types that we support.  Note that for color types that do not use the full 64-bits,
767      * we will simply take the low bits of the fill value.
768      *
769      * The defaults are:
770      * kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type
771      * kN32_SkColorType: Transparent or Black, depending on the src alpha type
772      * kRGB_565_SkColorType: Black
773      * kGray_8_SkColorType: Black
774      */
775     virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const;
776 
777     /**
778      * Get method for the input stream
779      */
stream()780     SkStream* stream() {
781         return fStream.get();
782     }
783 
784     /**
785      *  The remaining functions revolve around decoding scanlines.
786      */
787 
788     /**
789      *  Most images types will be kTopDown and will not need to override this function.
790      */
onGetScanlineOrder()791     virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
792 
dstInfo()793     const SkImageInfo& dstInfo() const { return fDstInfo; }
794 
options()795     const Options& options() const { return fOptions; }
796 
797     /**
798      *  Returns the number of scanlines that have been decoded so far.
799      *  This is unaffected by the SkScanlineOrder.
800      *
801      *  Returns -1 if we have not started a scanline decode.
802      */
currScanline()803     int currScanline() const { return fCurrScanline; }
804 
805     virtual int onOutputScanline(int inputScanline) const;
806 
807     bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha,
808                               SkTransferFunctionBehavior premulBehavior);
809     // Some classes never need a colorXform e.g.
810     // - ICO uses its embedded codec's colorXform
811     // - WBMP is just Black/White
usesColorXform()812     virtual bool usesColorXform() const { return true; }
813     void applyColorXform(void* dst, const void* src, int count, SkAlphaType) const;
814     void applyColorXform(void* dst, const void* src, int count) const;
815 
colorXform()816     SkColorSpaceXform* colorXform() const { return fColorXform.get(); }
xformOnDecode()817     bool xformOnDecode() const { return fXformOnDecode; }
818 
onGetFrameCount()819     virtual int onGetFrameCount() {
820         return 1;
821     }
822 
onGetFrameInfo(int,FrameInfo *)823     virtual bool onGetFrameInfo(int, FrameInfo*) const {
824         return false;
825     }
826 
onGetRepetitionCount()827     virtual int onGetRepetitionCount() {
828         return 0;
829     }
830 
831 private:
832     const SkEncodedInfo                fEncodedInfo;
833     const SkImageInfo                  fSrcInfo;
834     const XformFormat                  fSrcXformFormat;
835     std::unique_ptr<SkStream>          fStream;
836     bool                               fNeedsRewind;
837     const SkEncodedOrigin              fOrigin;
838 
839     SkImageInfo                        fDstInfo;
840     Options                            fOptions;
841     XformFormat                        fDstXformFormat; // Based on fDstInfo.
842     std::unique_ptr<SkColorSpaceXform> fColorXform;
843     bool                               fXformOnDecode;
844 
845     // Only meaningful during scanline decodes.
846     int                                fCurrScanline;
847 
848     bool                               fStartedIncrementalDecode;
849 
850     /**
851      *  Return whether {srcColor, srcIsOpaque, srcCS} can convert to dst.
852      *
853      *  Will be called for the appropriate frame, prior to initializing the colorXform.
854      */
855     virtual bool conversionSupported(const SkImageInfo& dst, SkColorType srcColor,
856                                      bool srcIsOpaque, const SkColorSpace* srcCS) const;
857     /**
858      *  Return whether these dimensions are supported as a scale.
859      *
860      *  The codec may choose to cache the information about scale and subset.
861      *  Either way, the same information will be passed to onGetPixels/onStart
862      *  on success.
863      *
864      *  This must return true for a size returned from getScaledDimensions.
865      */
dimensionsSupported(const SkISize & dim)866     bool dimensionsSupported(const SkISize& dim) {
867         return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
868     }
869 
870     /**
871      *  For multi-framed images, return the object with information about the frames.
872      */
getFrameHolder()873     virtual const SkFrameHolder* getFrameHolder() const {
874         return nullptr;
875     }
876 
877     /**
878      *  Check for a valid Options.fFrameIndex, and decode prior frames if necessary.
879      */
880     Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&);
881 
882     // Methods for scanline decoding.
onStartScanlineDecode(const SkImageInfo &,const Options &)883     virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
884             const Options& /*options*/) {
885         return kUnimplemented;
886     }
887 
onStartIncrementalDecode(const SkImageInfo &,void *,size_t,const Options &)888     virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
889             const Options&) {
890         return kUnimplemented;
891     }
892 
onIncrementalDecode(int *)893     virtual Result onIncrementalDecode(int*) {
894         return kUnimplemented;
895     }
896 
897 
onSkipScanlines(int)898     virtual bool onSkipScanlines(int /*countLines*/) { return false; }
899 
onGetScanlines(void *,int,size_t)900     virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
901 
902     /**
903      * On an incomplete decode, getPixels() and getScanlines() will call this function
904      * to fill any uinitialized memory.
905      *
906      * @param dstInfo        Contains the destination color type
907      *                       Contains the destination alpha type
908      *                       Contains the destination width
909      *                       The height stored in this info is unused
910      * @param dst            Pointer to the start of destination pixel memory
911      * @param rowBytes       Stride length in destination pixel memory
912      * @param zeroInit       Indicates if memory is zero initialized
913      * @param linesRequested Number of lines that the client requested
914      * @param linesDecoded   Number of lines that were successfully decoded
915      */
916     void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
917             ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
918 
919     /**
920      *  Return an object which will allow forcing scanline decodes to sample in X.
921      *
922      *  May create a sampler, if one is not currently being used. Otherwise, does
923      *  not affect ownership.
924      *
925      *  Only valid during scanline decoding or incremental decoding.
926      */
getSampler(bool)927     virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
928 
929     friend class DM::CodecSrc;  // for fillIncompleteImage
930     friend class SkSampledCodec;
931     friend class SkIcoCodec;
932     friend class SkAndroidCodec; // for fEncodedInfo
933 };
934 #endif // SkCodec_DEFINED
935