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