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