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