SkGifCodec.h revision ad8bcfeac4a684a64db3a7447aeea5bc35155f16
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#include "SkCodec.h" 9#include "SkColorSpace.h" 10#include "SkColorTable.h" 11#include "SkImageInfo.h" 12#include "SkSwizzler.h" 13 14struct GifFileType; 15struct SavedImage; 16 17/* 18 * 19 * This class implements the decoding for gif images 20 * 21 */ 22class SkGifCodec : public SkCodec { 23public: 24 static bool IsGif(const void*, size_t); 25 26 /* 27 * Assumes IsGif was called and returned true 28 * Creates a gif decoder 29 * Reads enough of the stream to determine the image format 30 */ 31 static SkCodec* NewFromStream(SkStream*); 32 33protected: 34 35 /* 36 * Read enough of the stream to initialize the SkGifCodec. 37 * Returns a bool representing success or failure. 38 * 39 * @param codecOut 40 * If it returned true, and codecOut was not nullptr, 41 * codecOut will be set to a new SkGifCodec. 42 * 43 * @param gifOut 44 * If it returned true, and codecOut was nullptr, 45 * gifOut must be non-nullptr and gifOut will be set to a new 46 * GifFileType pointer. 47 * 48 * @param stream 49 * Deleted on failure. 50 * codecOut will take ownership of it in the case where we created a codec. 51 * Ownership is unchanged when we returned a gifOut. 52 * 53 */ 54 static bool ReadHeader(SkStream* stream, SkCodec** codecOut, 55 GifFileType** gifOut); 56 57 /* 58 * Performs the full gif decode 59 */ 60 Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, 61 SkPMColor*, int*, int*) override; 62 63 SkEncodedFormat onGetEncodedFormat() const override { 64 return kGIF_SkEncodedFormat; 65 } 66 67 bool onRewind() override; 68 69 uint32_t onGetFillValue(SkColorType) const override; 70 71 int onOutputScanline(int inputScanline) const override; 72 73private: 74 75 /* 76 * A gif can contain multiple image frames. We will only decode the first 77 * frame. This function reads up to the first image frame, processing 78 * transparency and/or animation information that comes before the image 79 * data. 80 * 81 * @param gif Pointer to the library type that manages the gif decode 82 * @param transIndex This call will set the transparent index based on the 83 * extension data. 84 */ 85 static Result ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex); 86 87 /* 88 * A gif may contain many image frames, all of different sizes. 89 * This function checks if the gif dimensions are valid, based on the frame 90 * dimensions, and corrects the gif dimensions if necessary. 91 * 92 * @param gif Pointer to the library type that manages the gif decode 93 * @param size Size of the image that we will decode. 94 * Will be set by this function if the return value is true. 95 * @param frameRect Contains the dimenions and offset of the first image frame. 96 * Will be set by this function if the return value is true. 97 * 98 * @return true on success, false otherwise 99 */ 100 static bool GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect); 101 102 /* 103 * Initializes the color table that we will use for decoding. 104 * 105 * @param dstInfo Contains the requested dst color type. 106 * @param inputColorPtr Copies the encoded color table to the client's 107 * input color table if the client requests kIndex8. 108 * @param inputColorCount If the client requests kIndex8, sets 109 * inputColorCount to 256. Since gifs always 110 * contain 8-bit indices, we need a 256 entry color 111 * table to ensure that indexing is always in 112 * bounds. 113 */ 114 void initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* colorPtr, 115 int* inputColorCount); 116 117 /* 118 * Checks for invalid inputs and calls setFrameDimensions(), and 119 * initializeColorTable() in the proper sequence. 120 */ 121 Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, 122 int* inputColorCount, const Options& opts); 123 124 /* 125 * Initializes the swizzler. 126 * 127 * @param dstInfo Output image information. Dimensions may have been 128 * adjusted if the image frame size does not match the size 129 * indicated in the header. 130 * @param options Informs the swizzler if destination memory is zero initialized. 131 * Contains subset information. 132 */ 133 void initializeSwizzler(const SkImageInfo& dstInfo, 134 const Options& options); 135 136 SkSampler* getSampler(bool createIfNecessary) override { 137 SkASSERT(fSwizzler); 138 return fSwizzler; 139 } 140 141 /* 142 * @return true if the read is successful and false if the read fails. 143 */ 144 bool readRow(); 145 146 Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opts, 147 SkPMColor inputColorPtr[], int* inputColorCount) override; 148 149 int onGetScanlines(void* dst, int count, size_t rowBytes) override; 150 151 bool onSkipScanlines(int count) override; 152 153 /* 154 * For a scanline decode of "count" lines, this function indicates how 155 * many of the "count" lines should be skipped until we reach the top of 156 * the image frame and how many of the "count" lines are actually inside 157 * the image frame. 158 * 159 * @param count The number of scanlines requested. 160 * @param rowsBeforeFrame Output variable. The number of lines before 161 * we reach the top of the image frame. 162 * @param rowsInFrame Output variable. The number of lines to decode 163 * inside the image frame. 164 */ 165 void handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame); 166 167 SkScanlineOrder onGetScanlineOrder() const override; 168 169 /* 170 * This function cleans up the gif object after the decode completes 171 * It is used in a SkAutoTCallIProc template 172 */ 173 static void CloseGif(GifFileType* gif); 174 175 /* 176 * Frees any extension data used in the decode 177 * Used in a SkAutoTCallVProc 178 */ 179 static void FreeExtension(SavedImage* image); 180 181 /* 182 * Creates an instance of the decoder 183 * Called only by NewFromStream 184 * 185 * @param srcInfo contains the source width and height 186 * @param stream the stream of image data 187 * @param gif pointer to library type that manages gif decode 188 * takes ownership 189 * @param transIndex The transparent index. An invalid value 190 * indicates that there is no transparent index. 191 */ 192 SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType* gif, uint32_t transIndex, 193 const SkIRect& frameRect, bool frameIsSubset); 194 195 SkAutoTCallVProc<GifFileType, CloseGif> fGif; // owned 196 SkAutoTDeleteArray<uint8_t> fSrcBuffer; 197 const SkIRect fFrameRect; 198 const uint32_t fTransIndex; 199 uint32_t fFillIndex; 200 const bool fFrameIsSubset; 201 SkAutoTDelete<SkSwizzler> fSwizzler; 202 SkAutoTUnref<SkColorTable> fColorTable; 203 204 typedef SkCodec INHERITED; 205}; 206