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 SkCodec_DEFINED 9 #define SkCodec_DEFINED 10 11 #include "SkEncodedFormat.h" 12 #include "SkImageGenerator.h" 13 #include "SkImageInfo.h" 14 #include "SkScanlineDecoder.h" 15 #include "SkSize.h" 16 #include "SkStream.h" 17 #include "SkTemplates.h" 18 #include "SkTypes.h" 19 20 class SkData; 21 22 /** 23 * Abstraction layer directly on top of an image codec. 24 */ 25 class SkCodec : public SkImageGenerator { 26 public: 27 /** 28 * If this stream represents an encoded image that we know how to decode, 29 * return an SkCodec that can decode it. Otherwise return NULL. 30 * 31 * If NULL is returned, the stream is deleted immediately. Otherwise, the 32 * SkCodec takes ownership of it, and will delete it when done with it. 33 */ 34 static SkCodec* NewFromStream(SkStream*); 35 36 /** 37 * If this data represents an encoded image that we know how to decode, 38 * return an SkCodec that can decode it. Otherwise return NULL. 39 * 40 * Will take a ref if it returns a codec, else will not affect the data. 41 */ 42 static SkCodec* NewFromData(SkData*); 43 44 /** 45 * Return a size that approximately supports the desired scale factor. 46 * The codec may not be able to scale efficiently to the exact scale 47 * factor requested, so return a size that approximates that scale. 48 * 49 * FIXME: Move to SkImageGenerator? 50 */ 51 SkISize getScaledDimensions(float desiredScale) const { 52 return this->onGetScaledDimensions(desiredScale); 53 } 54 55 /** 56 * Format of the encoded data. 57 */ 58 SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); } 59 60 /** 61 * Return an object which can be used to decode individual scanlines. 62 * 63 * This object is owned by the SkCodec, which will handle its lifetime. The 64 * returned object is only valid until the SkCodec is deleted or the next 65 * call to getScanlineDecoder, whichever comes first. 66 * 67 * Calling a second time will rewind and replace the existing one with a 68 * new one. If the stream cannot be rewound, this will delete the existing 69 * one and return NULL. 70 * 71 * @param dstInfo Info of the destination. If the dimensions do not match 72 * those of getInfo, this implies a scale. 73 * @param options Contains decoding options, including if memory is zero 74 * initialized. 75 * @param ctable A pointer to a color table. When dstInfo.colorType() is 76 * kIndex8, this should be non-NULL and have enough storage for 256 77 * colors. The color table will be populated after decoding the palette. 78 * @param ctableCount A pointer to the size of the color table. When 79 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will 80 * be modified to the true size of the color table (<= 256) after 81 * decoding the palette. 82 * @return New SkScanlineDecoder, or NULL on failure. 83 * 84 * NOTE: If any rows were previously decoded, this requires rewinding the 85 * SkStream. 86 * 87 * NOTE: The scanline decoder is owned by the SkCodec and will delete it 88 * when the SkCodec is deleted. 89 */ 90 SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options, 91 SkPMColor ctable[], int* ctableCount); 92 93 /** 94 * Simplified version of getScanlineDecoder() that asserts that info is NOT 95 * kIndex8_SkColorType and uses the default Options. 96 */ 97 SkScanlineDecoder* getScanlineDecoder(const SkImageInfo& dstInfo); 98 99 /** 100 * Some images may initially report that they have alpha due to the format 101 * of the encoded data, but then never use any colors which have alpha 102 * less than 100%. This function can be called *after* decoding to 103 * determine if such an image truly had alpha. Calling it before decoding 104 * is undefined. 105 * FIXME: see skbug.com/3582. 106 */ 107 bool reallyHasAlpha() const { 108 return this->onReallyHasAlpha(); 109 } 110 111 protected: 112 SkCodec(const SkImageInfo&, SkStream*); 113 114 virtual SkISize onGetScaledDimensions(float /* desiredScale */) const { 115 // By default, scaling is not supported. 116 return this->getInfo().dimensions(); 117 } 118 119 virtual SkEncodedFormat onGetEncodedFormat() const = 0; 120 121 /** 122 * Override if your codec supports scanline decoding. 123 * 124 * As in onGetPixels(), the implementation must call rewindIfNeeded() and 125 * handle as appropriate. 126 * 127 * @param dstInfo Info of the destination. If the dimensions do not match 128 * those of getInfo, this implies a scale. 129 * @param options Contains decoding options, including if memory is zero 130 * initialized. 131 * @param ctable A pointer to a color table. When dstInfo.colorType() is 132 * kIndex8, this should be non-NULL and have enough storage for 256 133 * colors. The color table will be populated after decoding the palette. 134 * @param ctableCount A pointer to the size of the color table. When 135 * dstInfo.colorType() is kIndex8, this should be non-NULL. It will 136 * be modified to the true size of the color table (<= 256) after 137 * decoding the palette. 138 * @return New SkScanlineDecoder on success, NULL otherwise. The SkCodec 139 * will take ownership of the returned scanline decoder. 140 */ 141 virtual SkScanlineDecoder* onGetScanlineDecoder(const SkImageInfo& dstInfo, 142 const Options& options, 143 SkPMColor ctable[], 144 int* ctableCount) { 145 return NULL; 146 } 147 148 virtual bool onReallyHasAlpha() const { return false; } 149 150 enum RewindState { 151 kRewound_RewindState, 152 kNoRewindNecessary_RewindState, 153 kCouldNotRewind_RewindState 154 }; 155 /** 156 * If the stream was previously read, attempt to rewind. 157 * @returns: 158 * kRewound if the stream needed to be rewound, and the 159 * rewind succeeded. 160 * kNoRewindNecessary if the stream did not need to be 161 * rewound. 162 * kCouldNotRewind if the stream needed to be rewound, and 163 * rewind failed. 164 * 165 * Subclasses MUST call this function before reading the stream (e.g. in 166 * onGetPixels). If it returns false, onGetPixels should return 167 * kCouldNotRewind. 168 */ 169 RewindState SK_WARN_UNUSED_RESULT rewindIfNeeded(); 170 171 /* 172 * 173 * Get method for the input stream 174 * 175 */ 176 SkStream* stream() { 177 return fStream.get(); 178 } 179 180 private: 181 SkAutoTDelete<SkStream> fStream; 182 bool fNeedsRewind; 183 SkAutoTDelete<SkScanlineDecoder> fScanlineDecoder; 184 185 typedef SkImageGenerator INHERITED; 186 }; 187 #endif // SkCodec_DEFINED 188