blob: e462be2e7d64c494de89cc03241da7c5de4c08d9 [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
scroggo1dd3ea92015-03-20 11:55:55 -070011#include "SkEncodedFormat.h"
scroggof24f2242015-03-03 08:59:20 -080012#include "SkImageGenerator.h"
13#include "SkImageInfo.h"
scroggo05245902015-03-25 11:11:52 -070014#include "SkScanlineDecoder.h"
scroggof24f2242015-03-03 08:59:20 -080015#include "SkSize.h"
scroggofffeede2015-03-18 10:50:37 -070016#include "SkStream.h"
scroggof24f2242015-03-03 08:59:20 -080017#include "SkTemplates.h"
18#include "SkTypes.h"
19
20class SkData;
scroggof24f2242015-03-03 08:59:20 -080021
22/**
23 * Abstraction layer directly on top of an image codec.
24 */
25class SkCodec : public SkImageGenerator {
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 /**
45 * Return a size that approximately supports the desired scale factor.
46 * The codec may not be able to scale efficiently to the exact scale
47 * factor requested, so return a size that approximates that scale.
48 *
49 * FIXME: Move to SkImageGenerator?
50 */
scroggofffeede2015-03-18 10:50:37 -070051 SkISize getScaledDimensions(float desiredScale) const {
52 return this->onGetScaledDimensions(desiredScale);
53 }
scroggof24f2242015-03-03 08:59:20 -080054
scroggo1dd3ea92015-03-20 11:55:55 -070055 /**
56 * Format of the encoded data.
57 */
58 SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
59
scroggo05245902015-03-25 11:11:52 -070060 /**
61 * Return an object which can be used to decode individual scanlines.
62 *
63 * This object is owned by the SkCodec, which will handle its lifetime. The
64 * returned object is only valid until the SkCodec is deleted or the next
65 * call to getScanlineDecoder, whichever comes first.
66 *
67 * Calling a second time will rewind and replace the existing one with a
68 * new one. If the stream cannot be rewound, this will delete the existing
69 * one and return NULL.
70 *
71 * @param dstInfo Info of the destination. If the dimensions do not match
72 * those of getInfo, this implies a scale.
msarett9e43cab2015-04-29 07:38:43 -070073 * @param options Contains decoding options, including if memory is zero
74 * initialized.
75 * @param ctable A pointer to a color table. When dstInfo.colorType() is
76 * kIndex8, this should be non-NULL and have enough storage for 256
77 * colors. The color table will be populated after decoding the palette.
78 * @param ctableCount A pointer to the size of the color table. When
79 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
80 * be modified to the true size of the color table (<= 256) after
81 * decoding the palette.
scroggo05245902015-03-25 11:11:52 -070082 * @return New SkScanlineDecoder, or NULL on failure.
83 *
84 * NOTE: If any rows were previously decoded, this requires rewinding the
85 * SkStream.
86 *
87 * NOTE: The scanline decoder is owned by the SkCodec and will delete it
88 * when the SkCodec is deleted.
89 */
msarett9e43cab2015-04-29 07:38:43 -070090 SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
91 SkPMColor ctable[], int* ctableCount);
92
93 /**
94 * Simplified version of getScanlineDecoder() that asserts that info is NOT
95 * kIndex8_SkColorType and uses the default Options.
96 */
scroggo05245902015-03-25 11:11:52 -070097 SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo);
98
99 /**
100 * Some images may initially report that they have alpha due to the format
101 * of the encoded data, but then never use any colors which have alpha
102 * less than 100%. This function can be called *after* decoding to
103 * determine if such an image truly had alpha. Calling it before decoding
104 * is undefined.
105 * FIXME: see skbug.com/3582.
106 */
107 bool reallyHasAlpha() const {
108 return this->onReallyHasAlpha();
109 }
110
scroggof24f2242015-03-03 08:59:20 -0800111protected:
112 SkCodec(const SkImageInfo&, SkStream*);
113
scroggof24f2242015-03-03 08:59:20 -0800114 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const {
115 // By default, scaling is not supported.
halcanaryb880d7f2015-03-26 06:29:03 -0700116 return this->getInfo().dimensions();
scroggof24f2242015-03-03 08:59:20 -0800117 }
118
scroggo1dd3ea92015-03-20 11:55:55 -0700119 virtual SkEncodedFormat onGetEncodedFormat() const = 0;
120
scroggof24f2242015-03-03 08:59:20 -0800121 /**
scroggo05245902015-03-25 11:11:52 -0700122 * Override if your codec supports scanline decoding.
123 *
scroggo58421542015-04-01 11:25:20 -0700124 * As in onGetPixels(), the implementation must call rewindIfNeeded() and
125 * handle as appropriate.
scroggo05245902015-03-25 11:11:52 -0700126 *
127 * @param dstInfo Info of the destination. If the dimensions do not match
128 * those of getInfo, this implies a scale.
msarett9e43cab2015-04-29 07:38:43 -0700129 * @param options Contains decoding options, including if memory is zero
130 * initialized.
131 * @param ctable A pointer to a color table. When dstInfo.colorType() is
132 * kIndex8, this should be non-NULL and have enough storage for 256
133 * colors. The color table will be populated after decoding the palette.
134 * @param ctableCount A pointer to the size of the color table. When
135 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
136 * be modified to the true size of the color table (<= 256) after
137 * decoding the palette.
scroggo05245902015-03-25 11:11:52 -0700138 * @return New SkScanlineDecoder on success, NULL otherwise. The SkCodec
139 * will take ownership of the returned scanline decoder.
140 */
msarett9e43cab2015-04-29 07:38:43 -0700141 virtual SkScanlineDecoder* onGetScanlineDecoder(const SkImageInfo& dstInfo,
142 const Options& options,
143 SkPMColor ctable[],
144 int* ctableCount) {
scroggo05245902015-03-25 11:11:52 -0700145 return NULL;
146 }
147
148 virtual bool onReallyHasAlpha() const { return false; }
149
halcanarya096d7a2015-03-27 12:16:53 -0700150 enum RewindState {
151 kRewound_RewindState,
152 kNoRewindNecessary_RewindState,
153 kCouldNotRewind_RewindState
154 };
scroggo05245902015-03-25 11:11:52 -0700155 /**
scroggof24f2242015-03-03 08:59:20 -0800156 * If the stream was previously read, attempt to rewind.
157 * @returns:
halcanarya096d7a2015-03-27 12:16:53 -0700158 * kRewound if the stream needed to be rewound, and the
159 * rewind succeeded.
160 * kNoRewindNecessary if the stream did not need to be
161 * rewound.
162 * kCouldNotRewind if the stream needed to be rewound, and
163 * rewind failed.
164 *
scroggof24f2242015-03-03 08:59:20 -0800165 * Subclasses MUST call this function before reading the stream (e.g. in
166 * onGetPixels). If it returns false, onGetPixels should return
167 * kCouldNotRewind.
168 */
halcanarya096d7a2015-03-27 12:16:53 -0700169 RewindState SK_WARN_UNUSED_RESULT rewindIfNeeded();
scroggof24f2242015-03-03 08:59:20 -0800170
msarettc0e80c12015-07-01 06:50:35 -0700171 /**
msarett74114382015-03-16 11:55:18 -0700172 * Get method for the input stream
msarett74114382015-03-16 11:55:18 -0700173 */
174 SkStream* stream() {
175 return fStream.get();
176 }
177
msarettc0e80c12015-07-01 06:50:35 -0700178 /**
179 * If the codec has a scanline decoder, return it (no ownership change occurs)
180 * else return NULL.
181 * The returned decoder is valid while the codec exists and the client has not
182 * created a new scanline decoder.
183 */
184 SkScanlineDecoder* scanlineDecoder() {
185 return fScanlineDecoder.get();
186 }
187
188 /**
189 * Allow the codec subclass to detach and take ownership of the scanline decoder.
190 * This will likely be used when the scanline decoder needs to be destroyed
191 * in the destructor of the subclass.
192 */
193 SkScanlineDecoder* detachScanlineDecoder() {
194 return fScanlineDecoder.detach();
195 }
196
scroggof24f2242015-03-03 08:59:20 -0800197private:
scroggo05245902015-03-25 11:11:52 -0700198 SkAutoTDelete<SkStream> fStream;
199 bool fNeedsRewind;
200 SkAutoTDelete<SkScanlineDecoder> fScanlineDecoder;
reed3ef71e32015-03-19 08:31:14 -0700201
202 typedef SkImageGenerator INHERITED;
scroggof24f2242015-03-03 08:59:20 -0800203};
204#endif // SkCodec_DEFINED