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