SkCodec.h revision 93c69fff535075e86596a2b224f52f454b060be3
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 "SkColor.h"
13#include "SkEncodedFormat.h"
14#include "SkImageInfo.h"
15#include "SkSize.h"
16#include "SkStream.h"
17#include "SkTypes.h"
18
19class SkData;
20class SkSampler;
21
22/**
23 *  Abstraction layer directly on top of an image codec.
24 */
25class SkCodec : SkNoncopyable {
26public:
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
44    virtual ~SkCodec();
45
46    /**
47     *  Return the ImageInfo associated with this codec.
48     */
49    const SkImageInfo& getInfo() const { return fSrcInfo; }
50
51    /**
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.
55     *  The returned value is the codec's suggestion for the closest valid
56     *  scale that it can natively support
57     */
58    SkISize getScaledDimensions(float desiredScale) const {
59        // Negative and zero scales are errors.
60        SkASSERT(desiredScale > 0.0f);
61        if (desiredScale <= 0.0f) {
62            return SkISize::Make(0, 0);
63        }
64
65        // Upscaling is not supported. Return the original size if the client
66        // requests an upscale.
67        if (desiredScale >= 1.0f) {
68            return this->getInfo().dimensions();
69        }
70        return this->onGetScaledDimensions(desiredScale);
71    }
72
73    /**
74     *  Return (via desiredSubset) a subset which can decoded from this codec,
75     *  or false if this codec cannot decode subsets or anything similar to
76     *  desiredSubset.
77     *
78     *  @param desiredSubset In/out parameter. As input, a desired subset of
79     *      the original bounds (as specified by getInfo). If true is returned,
80     *      desiredSubset may have been modified to a subset which is
81     *      supported. Although a particular change may have been made to
82     *      desiredSubset to create something supported, it is possible other
83     *      changes could result in a valid subset.
84     *      If false is returned, desiredSubset's value is undefined.
85     *  @return true if this codec supports decoding desiredSubset (as
86     *      returned, potentially modified)
87     */
88    bool getValidSubset(SkIRect* desiredSubset) const {
89        return this->onGetValidSubset(desiredSubset);
90    }
91
92    /**
93     *  Format of the encoded data.
94     */
95    SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
96
97    /**
98     *  Used to describe the result of a call to getPixels().
99     *
100     *  Result is the union of possible results from subclasses.
101     */
102    enum Result {
103        /**
104         *  General return value for success.
105         */
106        kSuccess,
107        /**
108         *  The input is incomplete. A partial image was generated.
109         */
110        kIncompleteInput,
111        /**
112         *  The generator cannot convert to match the request, ignoring
113         *  dimensions.
114         */
115        kInvalidConversion,
116        /**
117         *  The generator cannot scale to requested size.
118         */
119        kInvalidScale,
120        /**
121         *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
122         *  too small, etc.
123         */
124        kInvalidParameters,
125        /**
126         *  The input did not contain a valid image.
127         */
128        kInvalidInput,
129        /**
130         *  Fulfilling this request requires rewinding the input, which is not
131         *  supported for this input.
132         */
133        kCouldNotRewind,
134        /**
135         *  This method is not implemented by this codec.
136         *  FIXME: Perhaps this should be kUnsupported?
137         */
138        kUnimplemented,
139    };
140
141    /**
142     *  Whether or not the memory passed to getPixels is zero initialized.
143     */
144    enum ZeroInitialized {
145        /**
146         *  The memory passed to getPixels is zero initialized. The SkCodec
147         *  may take advantage of this by skipping writing zeroes.
148         */
149        kYes_ZeroInitialized,
150        /**
151         *  The memory passed to getPixels has not been initialized to zero,
152         *  so the SkCodec must write all zeroes to memory.
153         *
154         *  This is the default. It will be used if no Options struct is used.
155         */
156        kNo_ZeroInitialized,
157    };
158
159    /**
160     *  Additional options to pass to getPixels.
161     */
162    struct Options {
163        Options()
164            : fZeroInitialized(kNo_ZeroInitialized)
165            , fSubset(NULL)
166        {}
167
168        ZeroInitialized fZeroInitialized;
169        /**
170         *  If not NULL, represents a subset of the original image to decode.
171         *  Must be within the bounds returned by getInfo().
172         *  If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which
173         *  currently supports subsets), the top and left values must be even.
174         *
175         *  In getPixels, we will attempt to decode the exact rectangular
176         *  subset specified by fSubset.
177         *
178         *  In a scanline decode, it does not make sense to specify a subset
179         *  top or subset height, since the client already controls which rows
180         *  to get and which rows to skip.  During scanline decodes, we will
181         *  require that the subset top be zero and the subset height be equal
182         *  to the full height.  We will, however, use the values of
183         *  subset left and subset width to decode partial scanlines on calls
184         *  to getScanlines().
185         */
186        SkIRect*        fSubset;
187    };
188
189    /**
190     *  Decode into the given pixels, a block of memory of size at
191     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
192     *  bytesPerPixel)
193     *
194     *  Repeated calls to this function should give the same results,
195     *  allowing the PixelRef to be immutable.
196     *
197     *  @param info A description of the format (config, size)
198     *         expected by the caller.  This can simply be identical
199     *         to the info returned by getInfo().
200     *
201     *         This contract also allows the caller to specify
202     *         different output-configs, which the implementation can
203     *         decide to support or not.
204     *
205     *         A size that does not match getInfo() implies a request
206     *         to scale. If the generator cannot perform this scale,
207     *         it will return kInvalidScale.
208     *
209     *  If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
210     *  SkPMColor values in ctable. On success the generator must copy N colors into that storage,
211     *  (where N is the logical number of table entries) and set ctableCount to N.
212     *
213     *  If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
214     *  is not null, it will be set to 0.
215     *
216     *  If a scanline decode is in progress, scanline mode will end, requiring the client to call
217     *  startScanlineDecode() in order to return to decoding scanlines.
218     *
219     *  @return Result kSuccess, or another value explaining the type of failure.
220     */
221    Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*,
222                     SkPMColor ctable[], int* ctableCount);
223
224    /**
225     *  Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
226     *  uses the default Options.
227     */
228    Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
229
230    /**
231     *  Some images may initially report that they have alpha due to the format
232     *  of the encoded data, but then never use any colors which have alpha
233     *  less than 100%. This function can be called *after* decoding to
234     *  determine if such an image truly had alpha. Calling it before decoding
235     *  is undefined.
236     *  FIXME: see skbug.com/3582.
237     */
238    bool reallyHasAlpha() const {
239        return this->onReallyHasAlpha();
240    }
241
242    /**
243     * The remaining functions revolve around decoding scanlines.
244     */
245
246    /**
247     *  Prepare for a scanline decode with the specified options.
248     *
249     *  After this call, this class will be ready to decode the first scanline.
250     *
251     *  This must be called in order to call getScanlines or skipScanlines.
252     *
253     *  This may require rewinding the stream.
254     *
255     *  Not all SkCodecs support this.
256     *
257     *  @param dstInfo Info of the destination. If the dimensions do not match
258     *      those of getInfo, this implies a scale.
259     *  @param options Contains decoding options, including if memory is zero
260     *      initialized.
261     *  @param ctable A pointer to a color table.  When dstInfo.colorType() is
262     *      kIndex8, this should be non-NULL and have enough storage for 256
263     *      colors.  The color table will be populated after decoding the palette.
264     *  @param ctableCount A pointer to the size of the color table.  When
265     *      dstInfo.colorType() is kIndex8, this should be non-NULL.  It will
266     *      be modified to the true size of the color table (<= 256) after
267     *      decoding the palette.
268     *  @return Enum representing success or reason for failure.
269     */
270    Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options,
271            SkPMColor ctable[], int* ctableCount);
272
273    /**
274     *  Simplified version of startScanlineDecode() that asserts that info is NOT
275     *  kIndex8_SkColorType and uses the default Options.
276     */
277    Result startScanlineDecode(const SkImageInfo& dstInfo);
278
279    /**
280     *  Write the next countLines scanlines into dst.
281     *
282     *  Not valid to call before calling startScanlineDecode().
283     *
284     *  @param dst Must be non-null, and large enough to hold countLines
285     *      scanlines of size rowBytes.
286     *  @param countLines Number of lines to write.
287     *  @param rowBytes Number of bytes per row. Must be large enough to hold
288     *      a scanline based on the SkImageInfo used to create this object.
289     *  @return the number of lines successfully decoded.  If this value is
290     *      less than countLines, this will fill the remaining lines with a
291     *      default value.
292     */
293    int getScanlines(void* dst, int countLines, size_t rowBytes);
294
295    /**
296     *  Skip count scanlines.
297     *
298     *  Not valid to call before calling startScanlineDecode().
299     *
300     *  The default version just calls onGetScanlines and discards the dst.
301     *  NOTE: If skipped lines are the only lines with alpha, this default
302     *  will make reallyHasAlpha return true, when it could have returned
303     *  false.
304     *
305     *  @return true if the scanlines were successfully skipped
306     *          false on failure, possible reasons for failure include:
307     *              An incomplete input image stream.
308     *              Calling this function before calling startScanlineDecode().
309     *              If countLines is less than zero or so large that it moves
310     *                  the current scanline past the end of the image.
311     */
312    bool skipScanlines(int countLines);
313
314    /**
315     *  The order in which rows are output from the scanline decoder is not the
316     *  same for all variations of all image types.  This explains the possible
317     *  output row orderings.
318     */
319    enum SkScanlineOrder {
320        /*
321         * By far the most common, this indicates that the image can be decoded
322         * reliably using the scanline decoder, and that rows will be output in
323         * the logical order.
324         */
325        kTopDown_SkScanlineOrder,
326
327        /*
328         * This indicates that the scanline decoder reliably outputs rows, but
329         * they will be returned in reverse order.  If the scanline format is
330         * kBottomUp, the nextScanline() API can be used to determine the actual
331         * y-coordinate of the next output row, but the client is not forced
332         * to take advantage of this, given that it's not too tough to keep
333         * track independently.
334         *
335         * For full image decodes, it is safe to get all of the scanlines at
336         * once, since the decoder will handle inverting the rows as it
337         * decodes.
338         *
339         * For subset decodes and sampling, it is simplest to get and skip
340         * scanlines one at a time, using the nextScanline() API.  It is
341         * possible to ask for larger chunks at a time, but this should be used
342         * with caution.  As with full image decodes, the decoder will handle
343         * inverting the requested rows, but rows will still be delivered
344         * starting from the bottom of the image.
345         *
346         * Upside down bmps are an example.
347         */
348        kBottomUp_SkScanlineOrder,
349
350        /*
351         * This indicates that the scanline decoder reliably outputs rows, but
352         * they will not be in logical order.  If the scanline format is
353         * kOutOfOrder, the nextScanline() API should be used to determine the
354         * actual y-coordinate of the next output row.
355         *
356         * For this scanline ordering, it is advisable to get and skip
357         * scanlines one at a time.
358         *
359         * Interlaced gifs are an example.
360         */
361        kOutOfOrder_SkScanlineOrder,
362
363        /*
364         * Indicates that the entire image must be decoded in order to output
365         * any amount of scanlines.  In this case, it is a REALLY BAD IDEA to
366         * request scanlines 1-by-1 or in small chunks.  The client should
367         * determine which scanlines are needed and ask for all of them in
368         * a single call to getScanlines().
369         *
370         * Interlaced pngs are an example.
371         */
372        kNone_SkScanlineOrder,
373    };
374
375    /**
376     *  An enum representing the order in which scanlines will be returned by
377     *  the scanline decoder.
378     */
379    SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
380
381    /**
382     *  Returns the y-coordinate of the next row to be returned by the scanline
383     *  decoder.
384     *
385     *  This will equal fCurrScanline, except in the case of strangely
386     *  encoded image types (bottom-up bmps, interlaced gifs).
387     *
388     *  Results are undefined when not in scanline decoding mode.
389     */
390    int nextScanline() const { return this->outputScanline(fCurrScanline); }
391
392    /**
393     * Returns the output y-coordinate of the row that corresponds to an input
394     * y-coordinate.  The input y-coordinate represents where the scanline
395     * is located in the encoded data.
396     *
397     *  This will equal inputScanline, except in the case of strangely
398     *  encoded image types (bottom-up bmps, interlaced gifs).
399     */
400    int outputScanline(int inputScanline) const;
401
402protected:
403    SkCodec(const SkImageInfo&, SkStream*);
404
405    virtual SkISize onGetScaledDimensions(float /* desiredScale */) const {
406        // By default, scaling is not supported.
407        return this->getInfo().dimensions();
408    }
409
410    // FIXME: What to do about subsets??
411    /**
412     *  Subclasses should override if they support dimensions other than the
413     *  srcInfo's.
414     */
415    virtual bool onDimensionsSupported(const SkISize&) {
416        return false;
417    }
418
419    virtual SkEncodedFormat onGetEncodedFormat() const = 0;
420
421    /**
422     * @param rowsDecoded When the encoded image stream is incomplete, this function
423     *                    will return kIncompleteInput and rowsDecoded will be set to
424     *                    the number of scanlines that were successfully decoded.
425     *                    This will allow getPixels() to fill the uninitialized memory.
426     */
427    virtual Result onGetPixels(const SkImageInfo& info,
428                               void* pixels, size_t rowBytes, const Options&,
429                               SkPMColor ctable[], int* ctableCount,
430                               int* rowsDecoded) = 0;
431
432    virtual bool onGetValidSubset(SkIRect* /* desiredSubset */) const {
433        // By default, subsets are not supported.
434        return false;
435    }
436
437    virtual bool onReallyHasAlpha() const { return false; }
438
439    /**
440     *  If the stream was previously read, attempt to rewind.
441     *
442     *  If the stream needed to be rewound, call onRewind.
443     *  @returns true if the codec is at the right position and can be used.
444     *      false if there was a failure to rewind.
445     *
446     *  This is called by getPixels() and start(). Subclasses may call if they
447     *  need to rewind at another time.
448     */
449    bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
450
451    /**
452     *  Called by rewindIfNeeded, if the stream needed to be rewound.
453     *
454     *  Subclasses should do any set up needed after a rewind.
455     */
456    virtual bool onRewind() {
457        return true;
458    }
459
460    /**
461     * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
462     * scanlines.  This allows the subclass to indicate what value to fill with.
463     *
464     * @param colorType Destination color type.
465     * @param alphaType Destination alpha type.
466     * @return          The value with which to fill uninitialized pixels.
467     *
468     * Note that we can interpret the return value as an SkPMColor, a 16-bit 565 color,
469     * an 8-bit gray color, or an 8-bit index into a color table, depending on the color
470     * type.
471     */
472    uint32_t getFillValue(SkColorType colorType, SkAlphaType alphaType) const {
473        return this->onGetFillValue(colorType, alphaType);
474    }
475
476    /**
477     * Some subclasses will override this function, but this is a useful default for the color
478     * types that we support.  Note that for color types that do not use the full 32-bits,
479     * we will simply take the low bits of the fill value.
480     *
481     * kN32_SkColorType: Transparent or Black
482     * kRGB_565_SkColorType: Black
483     * kGray_8_SkColorType: Black
484     * kIndex_8_SkColorType: First color in color table
485     */
486    virtual uint32_t onGetFillValue(SkColorType /*colorType*/, SkAlphaType alphaType) const {
487        return kOpaque_SkAlphaType == alphaType ? SK_ColorBLACK : SK_ColorTRANSPARENT;
488    }
489
490    /**
491     * Get method for the input stream
492     */
493    SkStream* stream() {
494        return fStream.get();
495    }
496
497    /**
498     *  The remaining functions revolve around decoding scanlines.
499     */
500
501    /**
502     *  Most images types will be kTopDown and will not need to override this function.
503     */
504    virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
505
506    /**
507     *  Update the next scanline. Used by interlaced png.
508     */
509    void updateNextScanline(int newY) { fCurrScanline = newY; }
510
511    const SkImageInfo& dstInfo() const { return fDstInfo; }
512
513    const SkCodec::Options& options() const { return fOptions; }
514
515    virtual int onOutputScanline(int inputScanline) const;
516
517private:
518    const SkImageInfo       fSrcInfo;
519    SkAutoTDelete<SkStream> fStream;
520    bool                    fNeedsRewind;
521    // These fields are only meaningful during scanline decodes.
522    SkImageInfo             fDstInfo;
523    SkCodec::Options        fOptions;
524    int                     fCurrScanline;
525
526    /**
527     *  Return whether these dimensions are supported as a scale.
528     *
529     *  The codec may choose to cache the information about scale and subset.
530     *  Either way, the same information will be passed to onGetPixels/onStart
531     *  on success.
532     *
533     *  This must return true for a size returned from getScaledDimensions.
534     */
535    bool dimensionsSupported(const SkISize& dim) {
536        return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
537    }
538
539    // Methods for scanline decoding.
540    virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
541            const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) {
542        return kUnimplemented;
543    }
544
545    // Naive default version just calls onGetScanlines on temp memory.
546    virtual bool onSkipScanlines(int countLines) {
547        // FIXME (msarett): Make this a pure virtual and always override this.
548        SkAutoMalloc storage(fDstInfo.minRowBytes());
549
550        // Note that we pass 0 to rowBytes so we continue to use the same memory.
551        // Also note that while getScanlines checks that rowBytes is big enough,
552        // onGetScanlines bypasses that check.
553        // Calling the virtual method also means we do not double count
554        // countLines.
555        return countLines == this->onGetScanlines(storage.get(), countLines, 0);
556    }
557
558    virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
559
560    /**
561     * On an incomplete decode, getPixels() and getScanlines() will call this function
562     * to fill any uinitialized memory.
563     *
564     * @param dstInfo        Contains the destination color type
565     *                       Contains the destination alpha type
566     *                       Contains the destination width
567     *                       The height stored in this info is unused
568     * @param dst            Pointer to the start of destination pixel memory
569     * @param rowBytes       Stride length in destination pixel memory
570     * @param zeroInit       Indicates if memory is zero initialized
571     * @param linesRequested Number of lines that the client requested
572     * @param linesDecoded   Number of lines that were successfully decoded
573     */
574    void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
575            ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
576
577    /**
578     *  Return an object which will allow forcing scanline decodes to sample in X.
579     *
580     *  May create a sampler, if one is not currently being used. Otherwise, does
581     *  not affect ownership.
582     *
583     *  Only valid during scanline decoding.
584     */
585    virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
586
587    friend class SkSampledCodec;
588};
589#endif // SkCodec_DEFINED
590