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