• 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 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  */
20 class SkAndroidCodec : SkNoncopyable {
21 public:
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      *
26      *  The SkPngChunkReader handles unknown chunks in PNGs.
27      *  See SkCodec.h for more details.
28      *
29      *  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      */
32     static SkAndroidCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
33 
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      *
38      *  The SkPngChunkReader handles unknown chunks in PNGs.
39      *  See SkCodec.h for more details.
40      *
41      *  Will take a ref if it returns a codec, else will not affect the data.
42      */
43     static SkAndroidCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
44 
~SkAndroidCodec()45     virtual ~SkAndroidCodec() {}
46 
47 
getInfo()48     const SkImageInfo& getInfo() const { return fInfo; }
49 
50     /**
51      *  Format of the encoded data.
52      */
getEncodedFormat()53     SkEncodedFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
54 
55     /**
56      *  @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     /**
74      *  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 {
AndroidOptionsAndroidOptions136         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.
146          *
147          *  The default is SkCodec::kNo_ZeroInitialized.
148          */
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.
158          *
159          *  The default is NULL, meaning a decode of the entire image.
160          */
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.
173          *
174          *  The default is NULL for both pointers.
175          */
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.
183          *
184          *  The default is 1, representing no downscaling.
185          */
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
218      *  using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above
219      *  for AndroidOptions) are used.
220      *
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,
228             const AndroidOptions* options);
229 
230     /**
231      *  Simplified version of getAndroidPixels() where we supply the default AndroidOptions as
232      *  specified above for AndroidOptions.
233      *
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 
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes)239     SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
240         return this->getAndroidPixels(info, pixels, rowBytes);
241     }
242 
243 protected:
244 
245     SkAndroidCodec(SkCodec*);
246 
codec()247     SkCodec* codec() const { return fCodec.get(); }
248 
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,
254             size_t rowBytes, const AndroidOptions& options) = 0;
255 
256 private:
257 
258     // This will always be a reference to the info that is contained by the
259     // embedded SkCodec.
260     const SkImageInfo& fInfo;
261 
262     SkAutoTDelete<SkCodec> fCodec;
263 };
264 #endif // SkAndroidCodec_DEFINED
265