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