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