blob: 8dfa8ba5fe81d72eaab1fa77b0d31a7ad77749b1 [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"
Hal Canary1fcc4042016-11-30 17:07:59 -050012#include "SkEncodedImageFormat.h"
msarett3d9d7a72015-10-21 10:27:10 -070013#include "SkStream.h"
14#include "SkTypes.h"
15
16/**
17 * Abstract interface defining image codec functionality that is necessary for
18 * Android.
19 */
Derek Sollenberger2fbf1bc2017-09-20 15:51:08 -040020class SK_API SkAndroidCodec : SkNoncopyable {
msarett3d9d7a72015-10-21 10:27:10 -070021public:
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 */
Mike Reedede7bac2017-07-23 15:30:02 -040032 static std::unique_ptr<SkAndroidCodec> MakeFromStream(std::unique_ptr<SkStream>,
33 SkPngChunkReader* = nullptr);
msarett3d9d7a72015-10-21 10:27:10 -070034
35 /**
36 * If this data represents an encoded image that we know how to decode,
37 * return an SkAndroidCodec that can decode it. Otherwise return NULL.
38 *
msarett7d5105c2015-12-02 07:02:41 -080039 * The SkPngChunkReader handles unknown chunks in PNGs.
40 * See SkCodec.h for more details.
msarett3d9d7a72015-10-21 10:27:10 -070041 */
Mike Reedede7bac2017-07-23 15:30:02 -040042 static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
43
Leon Scroggins III07418182017-08-15 12:24:02 -040044 virtual ~SkAndroidCodec();
msarett3d9d7a72015-10-21 10:27:10 -070045
Leon Scroggins III07418182017-08-15 12:24:02 -040046 const SkEncodedInfo& getEncodedInfo() const;
msarett3d9d7a72015-10-21 10:27:10 -070047
48 const SkImageInfo& getInfo() const { return fInfo; }
49
50 /**
51 * Format of the encoded data.
52 */
Hal Canary1fcc4042016-11-30 17:07:59 -050053 SkEncodedImageFormat 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 *
Matt Sarett8dcc84f2016-12-14 10:23:41 -050058 * |requestedColorType| may be overriden. We will default to kF16
Leon Scroggins571b30f2017-07-11 17:35:31 +000059 * for high precision images.
Matt Sarett8dcc84f2016-12-14 10:23:41 -050060 *
61 * In the general case, if it is possible to decode to
62 * |requestedColorType|, this returns |requestedColorType|.
63 * Otherwise, this returns a color type that is an appropriate
64 * match for the the encoded data.
msarett9a0e3462015-12-11 07:38:50 -080065 */
66 SkColorType computeOutputColorType(SkColorType requestedColorType);
67
68 /**
69 * @param requestedUnpremul Indicates if the client requested
70 * unpremultiplied output
71 *
72 * Returns the appropriate alpha type to decode to. If the image
73 * has alpha, the value of requestedUnpremul will be honored.
74 */
75 SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
76
77 /**
Matt Sarett68feef42017-04-11 09:51:32 -040078 * @param outputColorType Color type that the client will decode to.
79 * @param prefColorSpace Preferred color space to decode to.
80 * This may not return |prefColorSpace| for a couple reasons.
81 * (1) Android Principles: 565 must be sRGB, F16 must be
82 * linear sRGB, transfer function must be parametric.
83 * (2) Codec Limitations: F16 requires a linear color space.
Matt Sarett966bb342016-12-12 16:30:13 -050084 *
85 * Returns the appropriate color space to decode to.
Matt Sarett966bb342016-12-12 16:30:13 -050086 */
Matt Sarett68feef42017-04-11 09:51:32 -040087 sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
88 sk_sp<SkColorSpace> prefColorSpace = nullptr);
Matt Sarett966bb342016-12-12 16:30:13 -050089
90 /**
msarett3d9d7a72015-10-21 10:27:10 -070091 * Returns the dimensions of the scaled output image, for an input
92 * sampleSize.
93 *
94 * When the sample size divides evenly into the original dimensions, the
95 * scaled output dimensions will simply be equal to the original
96 * dimensions divided by the sample size.
97 *
98 * When the sample size does not divide even into the original
99 * dimensions, the codec may round up or down, depending on what is most
100 * efficient to decode.
101 *
102 * Finally, the codec will always recommend a non-zero output, so the output
103 * dimension will always be one if the sampleSize is greater than the
104 * original dimension.
105 */
106 SkISize getSampledDimensions(int sampleSize) const;
107
108 /**
109 * Return (via desiredSubset) a subset which can decoded from this codec,
110 * or false if the input subset is invalid.
111 *
112 * @param desiredSubset in/out parameter
113 * As input, a desired subset of the original bounds
114 * (as specified by getInfo).
115 * As output, if true is returned, desiredSubset may
116 * have been modified to a subset which is
117 * supported. Although a particular change may have
118 * been made to desiredSubset to create something
119 * supported, it is possible other changes could
120 * result in a valid subset. If false is returned,
121 * desiredSubset's value is undefined.
122 * @return true If the input desiredSubset is valid.
123 * desiredSubset may be modified to a subset
124 * supported by the codec.
125 * false If desiredSubset is invalid (NULL or not fully
126 * contained within the image).
127 */
128 bool getSupportedSubset(SkIRect* desiredSubset) const;
129 // TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()
130
131 /**
132 * Returns the dimensions of the scaled, partial output image, for an
133 * input sampleSize and subset.
134 *
135 * @param sampleSize Factor to scale down by.
136 * @param subset Must be a valid subset of the original image
137 * dimensions and a subset supported by SkAndroidCodec.
138 * getSubset() can be used to obtain a subset supported
139 * by SkAndroidCodec.
140 * @return Size of the scaled partial image. Or zero size
141 * if either of the inputs is invalid.
142 */
143 SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;
144
145 /**
146 * Additional options to pass to getAndroidPixels().
147 */
148 // FIXME: It's a bit redundant to name these AndroidOptions when this class is already
149 // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
150 // these Options when SkCodec has a slightly different set of Options. Maybe these
151 // should be DecodeOptions or SamplingOptions?
152 struct AndroidOptions {
153 AndroidOptions()
154 : fZeroInitialized(SkCodec::kNo_ZeroInitialized)
155 , fSubset(nullptr)
msarett3d9d7a72015-10-21 10:27:10 -0700156 , fSampleSize(1)
157 {}
158
159 /**
160 * Indicates is destination pixel memory is zero initialized.
scroggo7b5e5532016-02-04 06:14:24 -0800161 *
162 * The default is SkCodec::kNo_ZeroInitialized.
msarett3d9d7a72015-10-21 10:27:10 -0700163 */
164 SkCodec::ZeroInitialized fZeroInitialized;
165
166 /**
167 * If not NULL, represents a subset of the original image to decode.
168 *
169 * Must be within the bounds returned by getInfo().
170 *
Hal Canarydb683012016-11-23 08:55:18 -0700171 * If the EncodedFormat is SkEncodedImageFormat::kWEBP, the top and left
msarett3d9d7a72015-10-21 10:27:10 -0700172 * values must be even.
scroggo7b5e5532016-02-04 06:14:24 -0800173 *
174 * The default is NULL, meaning a decode of the entire image.
msarett3d9d7a72015-10-21 10:27:10 -0700175 */
176 SkIRect* fSubset;
177
178 /**
msarett3d9d7a72015-10-21 10:27:10 -0700179 * The client may provide an integer downscale factor for the decode.
180 * The codec may implement this downscaling by sampling or another
181 * method if it is more efficient.
scroggo7b5e5532016-02-04 06:14:24 -0800182 *
183 * The default is 1, representing no downscaling.
msarett3d9d7a72015-10-21 10:27:10 -0700184 */
185 int fSampleSize;
186 };
187
188 /**
189 * Decode into the given pixels, a block of memory of size at
190 * least (info.fHeight - 1) * rowBytes + (info.fWidth *
191 * bytesPerPixel)
192 *
193 * Repeated calls to this function should give the same results,
194 * allowing the PixelRef to be immutable.
195 *
196 * @param info A description of the format (config, size)
197 * expected by the caller. This can simply be identical
198 * to the info returned by getInfo().
199 *
200 * This contract also allows the caller to specify
201 * different output-configs, which the implementation can
202 * decide to support or not.
203 *
204 * A size that does not match getInfo() implies a request
205 * to scale or subset. If the codec cannot perform this
206 * scaling or subsetting, it will return an error code.
207 *
msarett3d9d7a72015-10-21 10:27:10 -0700208 * The AndroidOptions object is also used to specify any requested scaling or subsetting
scroggo7b5e5532016-02-04 06:14:24 -0800209 * using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above
210 * for AndroidOptions) are used.
msarett3d9d7a72015-10-21 10:27:10 -0700211 *
212 * @return Result kSuccess, or another value explaining the type of failure.
213 */
214 // FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already
215 // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
216 // this getPixels() when it is a slightly different API than SkCodec's getPixels().
217 // Maybe this should be decode() or decodeSubset()?
218 SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
scroggoe95a0682015-11-04 04:31:12 -0800219 const AndroidOptions* options);
msarett3d9d7a72015-10-21 10:27:10 -0700220
221 /**
scroggo7b5e5532016-02-04 06:14:24 -0800222 * Simplified version of getAndroidPixels() where we supply the default AndroidOptions as
Leon Scroggins571b30f2017-07-11 17:35:31 +0000223 * specified above for AndroidOptions. It will not perform any scaling or subsetting.
msarett3d9d7a72015-10-21 10:27:10 -0700224 */
225 SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
226
scroggo7b5e5532016-02-04 06:14:24 -0800227 SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
228 return this->getAndroidPixels(info, pixels, rowBytes);
229 }
230
msarett3d9d7a72015-10-21 10:27:10 -0700231protected:
232
msarett90c4d5f2015-12-10 13:09:24 -0800233 SkAndroidCodec(SkCodec*);
msarett3d9d7a72015-10-21 10:27:10 -0700234
msarett90c4d5f2015-12-10 13:09:24 -0800235 SkCodec* codec() const { return fCodec.get(); }
msarett3d9d7a72015-10-21 10:27:10 -0700236
237 virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
238
239 virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
240
241 virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
scroggoe95a0682015-11-04 04:31:12 -0800242 size_t rowBytes, const AndroidOptions& options) = 0;
msarett3d9d7a72015-10-21 10:27:10 -0700243
244private:
245
246 // This will always be a reference to the info that is contained by the
247 // embedded SkCodec.
248 const SkImageInfo& fInfo;
msarett90c4d5f2015-12-10 13:09:24 -0800249
bungeman6bd52842016-10-27 09:30:08 -0700250 std::unique_ptr<SkCodec> fCodec;
msarett3d9d7a72015-10-21 10:27:10 -0700251};
252#endif // SkAndroidCodec_DEFINED