blob: 7fee5be255f5b6406b76ac8b9f22d0b267cbe389 [file] [log] [blame]
msarett3d9d7a72015-10-21 10:27:10 -07001/*
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 SkAndroidCodec_DEFINED
9#define SkAndroidCodec_DEFINED
10
11#include "SkCodec.h"
12#include "SkEncodedFormat.h"
13#include "SkStream.h"
14#include "SkTypes.h"
15
16/**
17 * Abstract interface defining image codec functionality that is necessary for
18 * Android.
19 */
20class SkAndroidCodec : SkNoncopyable {
21public:
22 /**
23 * If this stream represents an encoded image that we know how to decode,
24 * return an SkAndroidCodec that can decode it. Otherwise return NULL.
25 *
msarett7d5105c2015-12-02 07:02:41 -080026 * The SkPngChunkReader handles unknown chunks in PNGs.
27 * See SkCodec.h for more details.
28 *
msarett3d9d7a72015-10-21 10:27:10 -070029 * If NULL is returned, the stream is deleted immediately. Otherwise, the
30 * SkCodec takes ownership of it, and will delete it when done with it.
31 */
msarett7d5105c2015-12-02 07:02:41 -080032 static SkAndroidCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
msarett3d9d7a72015-10-21 10:27:10 -070033
34 /**
35 * If this data represents an encoded image that we know how to decode,
36 * return an SkAndroidCodec that can decode it. Otherwise return NULL.
37 *
msarett7d5105c2015-12-02 07:02:41 -080038 * The SkPngChunkReader handles unknown chunks in PNGs.
39 * See SkCodec.h for more details.
40 *
msarett3d9d7a72015-10-21 10:27:10 -070041 * Will take a ref if it returns a codec, else will not affect the data.
42 */
msarett7d5105c2015-12-02 07:02:41 -080043 static SkAndroidCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
msarett3d9d7a72015-10-21 10:27:10 -070044
45 virtual ~SkAndroidCodec() {}
46
47
48 const SkImageInfo& getInfo() const { return fInfo; }
49
50 /**
51 * Format of the encoded data.
52 */
msarett90c4d5f2015-12-10 13:09:24 -080053 SkEncodedFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
msarett3d9d7a72015-10-21 10:27:10 -070054
55 /**
msarett9a0e3462015-12-11 07:38:50 -080056 * @param requestedColorType Color type requested by the client
57 *
58 * If it is possible to decode to requestedColorType, this returns
59 * requestedColorType. Otherwise, this returns whichever color type
60 * is suggested by the codec as the best match for the encoded data.
61 */
62 SkColorType computeOutputColorType(SkColorType requestedColorType);
63
64 /**
65 * @param requestedUnpremul Indicates if the client requested
66 * unpremultiplied output
67 *
68 * Returns the appropriate alpha type to decode to. If the image
69 * has alpha, the value of requestedUnpremul will be honored.
70 */
71 SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
72
73 /**
msarett3d9d7a72015-10-21 10:27:10 -070074 * Returns the dimensions of the scaled output image, for an input
75 * sampleSize.
76 *
77 * When the sample size divides evenly into the original dimensions, the
78 * scaled output dimensions will simply be equal to the original
79 * dimensions divided by the sample size.
80 *
81 * When the sample size does not divide even into the original
82 * dimensions, the codec may round up or down, depending on what is most
83 * efficient to decode.
84 *
85 * Finally, the codec will always recommend a non-zero output, so the output
86 * dimension will always be one if the sampleSize is greater than the
87 * original dimension.
88 */
89 SkISize getSampledDimensions(int sampleSize) const;
90
91 /**
92 * Return (via desiredSubset) a subset which can decoded from this codec,
93 * or false if the input subset is invalid.
94 *
95 * @param desiredSubset in/out parameter
96 * As input, a desired subset of the original bounds
97 * (as specified by getInfo).
98 * As output, if true is returned, desiredSubset may
99 * have been modified to a subset which is
100 * supported. Although a particular change may have
101 * been made to desiredSubset to create something
102 * supported, it is possible other changes could
103 * result in a valid subset. If false is returned,
104 * desiredSubset's value is undefined.
105 * @return true If the input desiredSubset is valid.
106 * desiredSubset may be modified to a subset
107 * supported by the codec.
108 * false If desiredSubset is invalid (NULL or not fully
109 * contained within the image).
110 */
111 bool getSupportedSubset(SkIRect* desiredSubset) const;
112 // TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()
113
114 /**
115 * Returns the dimensions of the scaled, partial output image, for an
116 * input sampleSize and subset.
117 *
118 * @param sampleSize Factor to scale down by.
119 * @param subset Must be a valid subset of the original image
120 * dimensions and a subset supported by SkAndroidCodec.
121 * getSubset() can be used to obtain a subset supported
122 * by SkAndroidCodec.
123 * @return Size of the scaled partial image. Or zero size
124 * if either of the inputs is invalid.
125 */
126 SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;
127
128 /**
129 * Additional options to pass to getAndroidPixels().
130 */
131 // FIXME: It's a bit redundant to name these AndroidOptions when this class is already
132 // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
133 // these Options when SkCodec has a slightly different set of Options. Maybe these
134 // should be DecodeOptions or SamplingOptions?
135 struct AndroidOptions {
136 AndroidOptions()
137 : fZeroInitialized(SkCodec::kNo_ZeroInitialized)
138 , fSubset(nullptr)
139 , fColorPtr(nullptr)
140 , fColorCount(nullptr)
141 , fSampleSize(1)
142 {}
143
144 /**
145 * Indicates is destination pixel memory is zero initialized.
scroggo7b5e5532016-02-04 06:14:24 -0800146 *
147 * The default is SkCodec::kNo_ZeroInitialized.
msarett3d9d7a72015-10-21 10:27:10 -0700148 */
149 SkCodec::ZeroInitialized fZeroInitialized;
150
151 /**
152 * If not NULL, represents a subset of the original image to decode.
153 *
154 * Must be within the bounds returned by getInfo().
155 *
156 * If the EncodedFormat is kWEBP_SkEncodedFormat, the top and left
157 * values must be even.
scroggo7b5e5532016-02-04 06:14:24 -0800158 *
159 * The default is NULL, meaning a decode of the entire image.
msarett3d9d7a72015-10-21 10:27:10 -0700160 */
161 SkIRect* fSubset;
162
163 /**
164 * If the client has requested a decode to kIndex8_SkColorType
165 * (specified in the SkImageInfo), then the caller must provide
166 * storage for up to 256 SkPMColor values in fColorPtr. On success,
167 * the codec must copy N colors into that storage, (where N is the
168 * logical number of table entries) and set fColorCount to N.
169 *
170 * If the client does not request kIndex8_SkColorType, then the last
171 * two parameters may be NULL. If fColorCount is not null, it will be
172 * set to 0.
scroggo7b5e5532016-02-04 06:14:24 -0800173 *
174 * The default is NULL for both pointers.
msarett3d9d7a72015-10-21 10:27:10 -0700175 */
176 SkPMColor* fColorPtr;
177 int* fColorCount;
178
179 /**
180 * The client may provide an integer downscale factor for the decode.
181 * The codec may implement this downscaling by sampling or another
182 * method if it is more efficient.
scroggo7b5e5532016-02-04 06:14:24 -0800183 *
184 * The default is 1, representing no downscaling.
msarett3d9d7a72015-10-21 10:27:10 -0700185 */
186 int fSampleSize;
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 or subset. If the codec cannot perform this
207 * scaling or subsetting, it will return an error code.
208 *
209 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
210 * SkPMColor values in options->fColorPtr. On success the codec must copy N colors into
211 * that storage, (where N is the logical number of table entries) and set
212 * options->fColorCount to N.
213 *
214 * If info is not kIndex8_SkColorType, options->fColorPtr and options->fColorCount may
215 * be nullptr.
216 *
217 * The AndroidOptions object is also used to specify any requested scaling or subsetting
scroggo7b5e5532016-02-04 06:14:24 -0800218 * using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above
219 * for AndroidOptions) are used.
msarett3d9d7a72015-10-21 10:27:10 -0700220 *
221 * @return Result kSuccess, or another value explaining the type of failure.
222 */
223 // FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already
224 // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
225 // this getPixels() when it is a slightly different API than SkCodec's getPixels().
226 // Maybe this should be decode() or decodeSubset()?
227 SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
scroggoe95a0682015-11-04 04:31:12 -0800228 const AndroidOptions* options);
msarett3d9d7a72015-10-21 10:27:10 -0700229
230 /**
scroggo7b5e5532016-02-04 06:14:24 -0800231 * Simplified version of getAndroidPixels() where we supply the default AndroidOptions as
232 * specified above for AndroidOptions.
msarett3d9d7a72015-10-21 10:27:10 -0700233 *
234 * This will return an error if the info is kIndex_8_SkColorType and also will not perform
235 * any scaling or subsetting.
236 */
237 SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
238
scroggo7b5e5532016-02-04 06:14:24 -0800239 SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
240 return this->getAndroidPixels(info, pixels, rowBytes);
241 }
242
msarett3d9d7a72015-10-21 10:27:10 -0700243protected:
244
msarett90c4d5f2015-12-10 13:09:24 -0800245 SkAndroidCodec(SkCodec*);
msarett3d9d7a72015-10-21 10:27:10 -0700246
msarett90c4d5f2015-12-10 13:09:24 -0800247 SkCodec* codec() const { return fCodec.get(); }
msarett3d9d7a72015-10-21 10:27:10 -0700248
249 virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
250
251 virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
252
253 virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
scroggoe95a0682015-11-04 04:31:12 -0800254 size_t rowBytes, const AndroidOptions& options) = 0;
msarett3d9d7a72015-10-21 10:27:10 -0700255
256private:
257
258 // This will always be a reference to the info that is contained by the
259 // embedded SkCodec.
260 const SkImageInfo& fInfo;
msarett90c4d5f2015-12-10 13:09:24 -0800261
262 SkAutoTDelete<SkCodec> fCodec;
msarett3d9d7a72015-10-21 10:27:10 -0700263};
264#endif // SkAndroidCodec_DEFINED