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 "SkEncodedImageFormat.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 static SkAndroidCodec* NewFromData(sk_sp<SkData>, SkPngChunkReader* = NULL); NewFromData(SkData * data,SkPngChunkReader * reader)42 static SkAndroidCodec* NewFromData(SkData* data, SkPngChunkReader* reader) { 43 return NewFromData(sk_ref_sp(data), reader); 44 } 45 ~SkAndroidCodec()46 virtual ~SkAndroidCodec() {} 47 48 getInfo()49 const SkImageInfo& getInfo() const { return fInfo; } 50 51 /** 52 * Format of the encoded data. 53 */ getEncodedFormat()54 SkEncodedImageFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); } 55 56 /** 57 * @param requestedColorType Color type requested by the client 58 * 59 * |requestedColorType| may be overriden. We will default to kF16 60 * for high precision images and kIndex8 for GIF and WBMP. 61 * 62 * In the general case, if it is possible to decode to 63 * |requestedColorType|, this returns |requestedColorType|. 64 * Otherwise, this returns a color type that is an appropriate 65 * match for the the encoded data. 66 */ 67 SkColorType computeOutputColorType(SkColorType requestedColorType); 68 69 /** 70 * @param requestedUnpremul Indicates if the client requested 71 * unpremultiplied output 72 * 73 * Returns the appropriate alpha type to decode to. If the image 74 * has alpha, the value of requestedUnpremul will be honored. 75 */ 76 SkAlphaType computeOutputAlphaType(bool requestedUnpremul); 77 78 /** 79 * @param outputColorType Color type that the client will decode to. 80 * @param prefColorSpace Preferred color space to decode to. 81 * This may not return |prefColorSpace| for a couple reasons. 82 * (1) Android Principles: 565 must be sRGB, F16 must be 83 * linear sRGB, transfer function must be parametric. 84 * (2) Codec Limitations: F16 requires a linear color space. 85 * 86 * Returns the appropriate color space to decode to. 87 */ 88 sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType, 89 sk_sp<SkColorSpace> prefColorSpace = nullptr); 90 91 /** 92 * Returns the dimensions of the scaled output image, for an input 93 * sampleSize. 94 * 95 * When the sample size divides evenly into the original dimensions, the 96 * scaled output dimensions will simply be equal to the original 97 * dimensions divided by the sample size. 98 * 99 * When the sample size does not divide even into the original 100 * dimensions, the codec may round up or down, depending on what is most 101 * efficient to decode. 102 * 103 * Finally, the codec will always recommend a non-zero output, so the output 104 * dimension will always be one if the sampleSize is greater than the 105 * original dimension. 106 */ 107 SkISize getSampledDimensions(int sampleSize) const; 108 109 /** 110 * Return (via desiredSubset) a subset which can decoded from this codec, 111 * or false if the input subset is invalid. 112 * 113 * @param desiredSubset in/out parameter 114 * As input, a desired subset of the original bounds 115 * (as specified by getInfo). 116 * As output, if true is returned, desiredSubset may 117 * have been modified to a subset which is 118 * supported. Although a particular change may have 119 * been made to desiredSubset to create something 120 * supported, it is possible other changes could 121 * result in a valid subset. If false is returned, 122 * desiredSubset's value is undefined. 123 * @return true If the input desiredSubset is valid. 124 * desiredSubset may be modified to a subset 125 * supported by the codec. 126 * false If desiredSubset is invalid (NULL or not fully 127 * contained within the image). 128 */ 129 bool getSupportedSubset(SkIRect* desiredSubset) const; 130 // TODO: Rename SkCodec::getValidSubset() to getSupportedSubset() 131 132 /** 133 * Returns the dimensions of the scaled, partial output image, for an 134 * input sampleSize and subset. 135 * 136 * @param sampleSize Factor to scale down by. 137 * @param subset Must be a valid subset of the original image 138 * dimensions and a subset supported by SkAndroidCodec. 139 * getSubset() can be used to obtain a subset supported 140 * by SkAndroidCodec. 141 * @return Size of the scaled partial image. Or zero size 142 * if either of the inputs is invalid. 143 */ 144 SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const; 145 146 /** 147 * Additional options to pass to getAndroidPixels(). 148 */ 149 // FIXME: It's a bit redundant to name these AndroidOptions when this class is already 150 // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call 151 // these Options when SkCodec has a slightly different set of Options. Maybe these 152 // should be DecodeOptions or SamplingOptions? 153 struct AndroidOptions { AndroidOptionsAndroidOptions154 AndroidOptions() 155 : fZeroInitialized(SkCodec::kNo_ZeroInitialized) 156 , fSubset(nullptr) 157 , fColorPtr(nullptr) 158 , fColorCount(nullptr) 159 , fSampleSize(1) 160 {} 161 162 /** 163 * Indicates is destination pixel memory is zero initialized. 164 * 165 * The default is SkCodec::kNo_ZeroInitialized. 166 */ 167 SkCodec::ZeroInitialized fZeroInitialized; 168 169 /** 170 * If not NULL, represents a subset of the original image to decode. 171 * 172 * Must be within the bounds returned by getInfo(). 173 * 174 * If the EncodedFormat is SkEncodedImageFormat::kWEBP, the top and left 175 * values must be even. 176 * 177 * The default is NULL, meaning a decode of the entire image. 178 */ 179 SkIRect* fSubset; 180 181 /** 182 * If the client has requested a decode to kIndex8_SkColorType 183 * (specified in the SkImageInfo), then the caller must provide 184 * storage for up to 256 SkPMColor values in fColorPtr. On success, 185 * the codec must copy N colors into that storage, (where N is the 186 * logical number of table entries) and set fColorCount to N. 187 * 188 * If the client does not request kIndex8_SkColorType, then the last 189 * two parameters may be NULL. If fColorCount is not null, it will be 190 * set to 0. 191 * 192 * The default is NULL for both pointers. 193 */ 194 SkPMColor* fColorPtr; 195 int* fColorCount; 196 197 /** 198 * The client may provide an integer downscale factor for the decode. 199 * The codec may implement this downscaling by sampling or another 200 * method if it is more efficient. 201 * 202 * The default is 1, representing no downscaling. 203 */ 204 int fSampleSize; 205 }; 206 207 /** 208 * Decode into the given pixels, a block of memory of size at 209 * least (info.fHeight - 1) * rowBytes + (info.fWidth * 210 * bytesPerPixel) 211 * 212 * Repeated calls to this function should give the same results, 213 * allowing the PixelRef to be immutable. 214 * 215 * @param info A description of the format (config, size) 216 * expected by the caller. This can simply be identical 217 * to the info returned by getInfo(). 218 * 219 * This contract also allows the caller to specify 220 * different output-configs, which the implementation can 221 * decide to support or not. 222 * 223 * A size that does not match getInfo() implies a request 224 * to scale or subset. If the codec cannot perform this 225 * scaling or subsetting, it will return an error code. 226 * 227 * If info is kIndex8_SkColorType, then the caller must provide storage for up to 256 228 * SkPMColor values in options->fColorPtr. On success the codec must copy N colors into 229 * that storage, (where N is the logical number of table entries) and set 230 * options->fColorCount to N. 231 * 232 * If info is not kIndex8_SkColorType, options->fColorPtr and options->fColorCount may 233 * be nullptr. 234 * 235 * The AndroidOptions object is also used to specify any requested scaling or subsetting 236 * using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above 237 * for AndroidOptions) are used. 238 * 239 * @return Result kSuccess, or another value explaining the type of failure. 240 */ 241 // FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already 242 // called SkAndroidCodec. On the other hand, it's may be a bit confusing to call 243 // this getPixels() when it is a slightly different API than SkCodec's getPixels(). 244 // Maybe this should be decode() or decodeSubset()? 245 SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 246 const AndroidOptions* options); 247 248 /** 249 * Simplified version of getAndroidPixels() where we supply the default AndroidOptions as 250 * specified above for AndroidOptions. 251 * 252 * This will return an error if the info is kIndex_8_SkColorType and also will not perform 253 * any scaling or subsetting. 254 */ 255 SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes); 256 getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes)257 SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 258 return this->getAndroidPixels(info, pixels, rowBytes); 259 } 260 261 protected: 262 263 SkAndroidCodec(SkCodec*); 264 codec()265 SkCodec* codec() const { return fCodec.get(); } 266 267 virtual SkISize onGetSampledDimensions(int sampleSize) const = 0; 268 269 virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0; 270 271 virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels, 272 size_t rowBytes, const AndroidOptions& options) = 0; 273 274 private: 275 276 // This will always be a reference to the info that is contained by the 277 // embedded SkCodec. 278 const SkImageInfo& fInfo; 279 280 std::unique_ptr<SkCodec> fCodec; 281 }; 282 #endif // SkAndroidCodec_DEFINED 283