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 | ad8bcfe | 2016-03-07 07:09:03 -0800 | [diff] [blame] | 9 | #include "SkColorSpace.h" |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 10 | #include "SkColorTable.h" |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 11 | #include "SkImageInfo.h" |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 12 | #include "SkSwizzler.h" |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 13 | |
msarett | 39b2d5a | 2016-02-17 08:26:31 -0800 | [diff] [blame] | 14 | struct GifFileType; |
| 15 | struct SavedImage; |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 16 | |
| 17 | /* |
| 18 | * |
| 19 | * This class implements the decoding for gif images |
| 20 | * |
| 21 | */ |
| 22 | class SkGifCodec : public SkCodec { |
| 23 | public: |
scroggo | db30be2 | 2015-12-08 18:54:13 -0800 | [diff] [blame] | 24 | static bool IsGif(const void*, size_t); |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 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*); |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 32 | |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 33 | protected: |
| 34 | |
| 35 | /* |
msarett | 438b2ad | 2015-04-09 12:43:10 -0700 | [diff] [blame] | 36 | * Read enough of the stream to initialize the SkGifCodec. |
| 37 | * Returns a bool representing success or failure. |
| 38 | * |
| 39 | * @param codecOut |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 40 | * If it returned true, and codecOut was not nullptr, |
msarett | 438b2ad | 2015-04-09 12:43:10 -0700 | [diff] [blame] | 41 | * codecOut will be set to a new SkGifCodec. |
| 42 | * |
| 43 | * @param gifOut |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 44 | * If it returned true, and codecOut was nullptr, |
| 45 | * gifOut must be non-nullptr and gifOut will be set to a new |
msarett | 438b2ad | 2015-04-09 12:43:10 -0700 | [diff] [blame] | 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 | */ |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 54 | static bool ReadHeader(SkStream* stream, SkCodec** codecOut, |
| 55 | GifFileType** gifOut); |
msarett | 438b2ad | 2015-04-09 12:43:10 -0700 | [diff] [blame] | 56 | |
| 57 | /* |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 58 | * Performs the full gif decode |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 59 | */ |
| 60 | Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 61 | SkPMColor*, int*, int*) override; |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 62 | |
| 63 | SkEncodedFormat onGetEncodedFormat() const override { |
| 64 | return kGIF_SkEncodedFormat; |
| 65 | } |
| 66 | |
scroggo | b427db1 | 2015-08-12 07:24:13 -0700 | [diff] [blame] | 67 | bool onRewind() override; |
| 68 | |
msarett | f7eb6fc | 2016-09-13 09:04:11 -0700 | [diff] [blame] | 69 | uint64_t onGetFillValue(const SkImageInfo&) const override; |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 70 | |
mtklein | e975928 | 2015-10-15 08:55:33 -0700 | [diff] [blame] | 71 | int onOutputScanline(int inputScanline) const override; |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 72 | |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 73 | private: |
| 74 | |
| 75 | /* |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 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 | */ |
scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 85 | static Result ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex); |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 86 | |
| 87 | /* |
| 88 | * A gif may contain many image frames, all of different sizes. |
msarett | 4aa02d8 | 2015-10-06 07:46:02 -0700 | [diff] [blame] | 89 | * This function checks if the gif dimensions are valid, based on the frame |
| 90 | * dimensions, and corrects the gif dimensions if necessary. |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 91 | * |
msarett | 4aa02d8 | 2015-10-06 07:46:02 -0700 | [diff] [blame] | 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 |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 99 | */ |
msarett | 4aa02d8 | 2015-10-06 07:46:02 -0700 | [diff] [blame] | 100 | static bool GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect); |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 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 | /* |
scroggo | 3a7701c | 2015-09-30 09:15:14 -0700 | [diff] [blame] | 118 | * Checks for invalid inputs and calls setFrameDimensions(), and |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 119 | * initializeColorTable() in the proper sequence. |
| 120 | */ |
scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 121 | Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 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. |
msarett | fdb4757 | 2015-10-13 12:50:14 -0700 | [diff] [blame] | 130 | * @param options Informs the swizzler if destination memory is zero initialized. |
| 131 | * Contains subset information. |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 132 | */ |
msarett | b30d698 | 2016-02-15 10:18:45 -0800 | [diff] [blame] | 133 | void initializeSwizzler(const SkImageInfo& dstInfo, |
msarett | fdb4757 | 2015-10-13 12:50:14 -0700 | [diff] [blame] | 134 | const Options& options); |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 135 | |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 136 | SkSampler* getSampler(bool createIfNecessary) override { |
| 137 | SkASSERT(fSwizzler); |
| 138 | return fSwizzler; |
| 139 | } |
scroggo | e7fc14b | 2015-10-02 13:14:46 -0700 | [diff] [blame] | 140 | |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 141 | /* |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 142 | * @return true if the read is successful and false if the read fails. |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 143 | */ |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 144 | bool readRow(); |
scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 145 | |
| 146 | Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opts, |
| 147 | SkPMColor inputColorPtr[], int* inputColorCount) override; |
| 148 | |
msarett | e6dd004 | 2015-10-09 11:07:34 -0700 | [diff] [blame] | 149 | int onGetScanlines(void* dst, int count, size_t rowBytes) override; |
scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 150 | |
msarett | 72261c0 | 2015-11-19 15:29:26 -0800 | [diff] [blame] | 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 | |
scroggo | 46c5747 | 2015-09-30 08:57:13 -0700 | [diff] [blame] | 167 | SkScanlineOrder onGetScanlineOrder() const override; |
| 168 | |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 169 | /* |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 170 | * This function cleans up the gif object after the decode completes |
| 171 | * It is used in a SkAutoTCallIProc template |
| 172 | */ |
msarett | 438b2ad | 2015-04-09 12:43:10 -0700 | [diff] [blame] | 173 | static void CloseGif(GifFileType* gif); |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 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 | * |
msarett | c30c418 | 2016-04-20 11:53:35 -0700 | [diff] [blame] | 185 | * @param info contains properties of the encoded data |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 186 | * @param stream the stream of image data |
| 187 | * @param gif pointer to library type that manages gif decode |
| 188 | * takes ownership |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 189 | * @param transIndex The transparent index. An invalid value |
| 190 | * indicates that there is no transparent index. |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 191 | */ |
msarett | c30c418 | 2016-04-20 11:53:35 -0700 | [diff] [blame] | 192 | SkGifCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream, |
| 193 | GifFileType* gif, uint32_t transIndex, const SkIRect& frameRect, bool frameIsSubset); |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 194 | |
msarett | 438b2ad | 2015-04-09 12:43:10 -0700 | [diff] [blame] | 195 | SkAutoTCallVProc<GifFileType, CloseGif> fGif; // owned |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 196 | SkAutoTDeleteArray<uint8_t> fSrcBuffer; |
msarett | 4aa02d8 | 2015-10-06 07:46:02 -0700 | [diff] [blame] | 197 | const SkIRect fFrameRect; |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 198 | const uint32_t fTransIndex; |
| 199 | uint32_t fFillIndex; |
msarett | 4aa02d8 | 2015-10-06 07:46:02 -0700 | [diff] [blame] | 200 | const bool fFrameIsSubset; |
msarett | 10522ff | 2015-09-07 08:54:01 -0700 | [diff] [blame] | 201 | SkAutoTDelete<SkSwizzler> fSwizzler; |
| 202 | SkAutoTUnref<SkColorTable> fColorTable; |
| 203 | |
msarett | 8c8f22a | 2015-04-01 06:58:48 -0700 | [diff] [blame] | 204 | typedef SkCodec INHERITED; |
| 205 | }; |