1/*
2 * Copyright 2006 The Android Open Source Project
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 "SkColor.h"
9#include "SkColorPriv.h"
10#include "SkColorTable.h"
11#include "SkImageDecoder.h"
12#include "SkRTConf.h"
13#include "SkScaledBitmapSampler.h"
14#include "SkStream.h"
15#include "SkTemplates.h"
16#include "SkUtils.h"
17
18#include "gif_lib.h"
19
20class SkGIFImageDecoder : public SkImageDecoder {
21public:
22    virtual Format getFormat() const SK_OVERRIDE {
23        return kGIF_Format;
24    }
25
26protected:
27    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
28
29private:
30    typedef SkImageDecoder INHERITED;
31};
32
33static const uint8_t gStartingIterlaceYValue[] = {
34    0, 4, 2, 1
35};
36static const uint8_t gDeltaIterlaceYValue[] = {
37    8, 8, 4, 2
38};
39
40SK_CONF_DECLARE(bool, c_suppressGIFImageDecoderWarnings,
41                "images.gif.suppressDecoderWarnings", true,
42                "Suppress GIF warnings and errors when calling image decode "
43                "functions.");
44
45
46/*  Implement the GIF interlace algorithm in an iterator.
47    1) grab every 8th line beginning at 0
48    2) grab every 8th line beginning at 4
49    3) grab every 4th line beginning at 2
50    4) grab every 2nd line beginning at 1
51*/
52class GifInterlaceIter {
53public:
54    GifInterlaceIter(int height) : fHeight(height) {
55        fStartYPtr = gStartingIterlaceYValue;
56        fDeltaYPtr = gDeltaIterlaceYValue;
57
58        fCurrY = *fStartYPtr++;
59        fDeltaY = *fDeltaYPtr++;
60    }
61
62    int currY() const {
63        SkASSERT(fStartYPtr);
64        SkASSERT(fDeltaYPtr);
65        return fCurrY;
66    }
67
68    void next() {
69        SkASSERT(fStartYPtr);
70        SkASSERT(fDeltaYPtr);
71
72        int y = fCurrY + fDeltaY;
73        // We went from an if statement to a while loop so that we iterate
74        // through fStartYPtr until a valid row is found. This is so that images
75        // that are smaller than 5x5 will not trash memory.
76        while (y >= fHeight) {
77            if (gStartingIterlaceYValue +
78                    SK_ARRAY_COUNT(gStartingIterlaceYValue) == fStartYPtr) {
79                // we done
80                SkDEBUGCODE(fStartYPtr = NULL;)
81                SkDEBUGCODE(fDeltaYPtr = NULL;)
82                y = 0;
83            } else {
84                y = *fStartYPtr++;
85                fDeltaY = *fDeltaYPtr++;
86            }
87        }
88        fCurrY = y;
89    }
90
91private:
92    const int fHeight;
93    int fCurrY;
94    int fDeltaY;
95    const uint8_t* fStartYPtr;
96    const uint8_t* fDeltaYPtr;
97};
98
99///////////////////////////////////////////////////////////////////////////////
100
101static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out,
102                              int size) {
103    SkStream* stream = (SkStream*) fileType->UserData;
104    return (int) stream->read(out, size);
105}
106
107void CheckFreeExtension(SavedImage* Image) {
108    if (Image->ExtensionBlocks) {
109#if GIFLIB_MAJOR < 5
110        FreeExtension(Image);
111#else
112        GifFreeExtensions(&Image->ExtensionBlockCount, &Image->ExtensionBlocks);
113#endif
114    }
115}
116
117// return NULL on failure
118static const ColorMapObject* find_colormap(const GifFileType* gif) {
119    const ColorMapObject* cmap = gif->Image.ColorMap;
120    if (NULL == cmap) {
121        cmap = gif->SColorMap;
122    }
123
124    if (NULL == cmap) {
125        // no colormap found
126        return NULL;
127    }
128    // some sanity checks
129    if (cmap && ((unsigned)cmap->ColorCount > 256 ||
130                 cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
131        cmap = NULL;
132    }
133    return cmap;
134}
135
136// return -1 if not found (i.e. we're completely opaque)
137static int find_transpIndex(const SavedImage& image, int colorCount) {
138    int transpIndex = -1;
139    for (int i = 0; i < image.ExtensionBlockCount; ++i) {
140        const ExtensionBlock* eb = image.ExtensionBlocks + i;
141        if (eb->Function == 0xF9 && eb->ByteCount == 4) {
142            if (eb->Bytes[0] & 1) {
143                transpIndex = (unsigned char)eb->Bytes[3];
144                // check for valid transpIndex
145                if (transpIndex >= colorCount) {
146                    transpIndex = -1;
147                }
148                break;
149            }
150        }
151    }
152    return transpIndex;
153}
154
155static bool error_return(const SkBitmap& bm, const char msg[]) {
156    if (!c_suppressGIFImageDecoderWarnings) {
157        SkDebugf("libgif error [%s] bitmap [%d %d] pixels %p colortable %p\n",
158                 msg, bm.width(), bm.height(), bm.getPixels(),
159                 bm.getColorTable());
160    }
161    return false;
162}
163static void gif_warning(const SkBitmap& bm, const char msg[]) {
164    if (!c_suppressGIFImageDecoderWarnings) {
165        SkDebugf("libgif warning [%s] bitmap [%d %d] pixels %p colortable %p\n",
166                 msg, bm.width(), bm.height(), bm.getPixels(),
167                 bm.getColorTable());
168    }
169}
170
171/**
172 *  Skip rows in the source gif image.
173 *  @param gif Source image.
174 *  @param dst Scratch output needed by gif library call. Must be >= width bytes.
175 *  @param width Bytes per row in the source image.
176 *  @param rowsToSkip Number of rows to skip.
177 *  @return True on success, false on GIF_ERROR.
178 */
179static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToSkip) {
180    for (int i = 0; i < rowsToSkip; i++) {
181        if (DGifGetLine(gif, dst, width) == GIF_ERROR) {
182            return false;
183        }
184    }
185    return true;
186}
187
188/**
189 *  GIFs with fewer then 256 color entries will sometimes index out of
190 *  bounds of the color table (this is malformed, but libgif does not
191 *  check sicne it is rare).  This function checks for this error and
192 *  fixes it.  This makes the output image consistantly deterministic.
193 */
194static void sanitize_indexed_bitmap(SkBitmap* bm) {
195    if ((kIndex_8_SkColorType == bm->colorType()) && !(bm->empty())) {
196        SkAutoLockPixels alp(*bm);
197        if (bm->getPixels()) {
198            SkColorTable* ct = bm->getColorTable();  // Index8 must have it.
199            SkASSERT(ct != NULL);
200            uint32_t count = ct->count();
201            SkASSERT(count > 0);
202            SkASSERT(count <= 0x100);
203            if (count != 0x100) {  // Full colortables can't go wrong.
204                // Count is a power of 2; asserted elsewhere.
205                uint8_t byteMask = (~(count - 1));
206                bool warning = false;
207                uint8_t* addr = static_cast<uint8_t*>(bm->getPixels());
208                int height = bm->height();
209                int width = bm->width();
210                size_t rowBytes = bm->rowBytes();
211                while (--height >= 0) {
212                    uint8_t* ptr = addr;
213                    int x = width;
214                    while (--x >= 0) {
215                        if (0 != ((*ptr) & byteMask)) {
216                            warning = true;
217                            *ptr = 0;
218                        }
219                        ++ptr;
220                    }
221                    addr += rowBytes;
222                }
223                if (warning) {
224                    gif_warning(*bm, "Index out of bounds.");
225                }
226            }
227        }
228    }
229}
230
231bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
232#if GIFLIB_MAJOR < 5
233    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
234#else
235    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL);
236#endif
237    if (NULL == gif) {
238        return error_return(*bm, "DGifOpen");
239    }
240
241    SkAutoTCallIProc<GifFileType, DGifCloseFile> acp(gif);
242
243    SavedImage temp_save;
244    temp_save.ExtensionBlocks=NULL;
245    temp_save.ExtensionBlockCount=0;
246    SkAutoTCallVProc<SavedImage, CheckFreeExtension> acp2(&temp_save);
247
248    int width, height;
249    GifRecordType recType;
250    GifByteType *extData;
251#if GIFLIB_MAJOR >= 5
252    int extFunction;
253#endif
254    int transpIndex = -1;   // -1 means we don't have it (yet)
255    int fillIndex = gif->SBackGroundColor;
256
257    do {
258        if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
259            return error_return(*bm, "DGifGetRecordType");
260        }
261
262        switch (recType) {
263        case IMAGE_DESC_RECORD_TYPE: {
264            if (DGifGetImageDesc(gif) == GIF_ERROR) {
265                return error_return(*bm, "IMAGE_DESC_RECORD_TYPE");
266            }
267
268            if (gif->ImageCount < 1) {    // sanity check
269                return error_return(*bm, "ImageCount < 1");
270            }
271
272            width = gif->SWidth;
273            height = gif->SHeight;
274
275            SavedImage* image = &gif->SavedImages[gif->ImageCount-1];
276            const GifImageDesc& desc = image->ImageDesc;
277
278            int imageLeft = desc.Left;
279            int imageTop = desc.Top;
280            const int innerWidth = desc.Width;
281            const int innerHeight = desc.Height;
282            if (innerWidth <= 0 || innerHeight <= 0) {
283                return error_return(*bm, "invalid dimensions");
284            }
285
286            // check for valid descriptor
287            if (innerWidth > width) {
288                gif_warning(*bm, "image too wide, expanding output to size");
289                width = innerWidth;
290                imageLeft = 0;
291            } else if (imageLeft + innerWidth > width) {
292                gif_warning(*bm, "shifting image left to fit");
293                imageLeft = width - innerWidth;
294            } else if (imageLeft < 0) {
295                gif_warning(*bm, "shifting image right to fit");
296                imageLeft = 0;
297            }
298
299
300            if (innerHeight > height) {
301                gif_warning(*bm, "image too tall,  expanding output to size");
302                height = innerHeight;
303                imageTop = 0;
304            } else if (imageTop + innerHeight > height) {
305                gif_warning(*bm, "shifting image up to fit");
306                imageTop = height - innerHeight;
307            } else if (imageTop < 0) {
308                gif_warning(*bm, "shifting image down to fit");
309                imageTop = 0;
310            }
311
312#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER
313            // FIXME: We could give the caller a choice of images or configs.
314            if (!this->chooseFromOneChoice(kIndex_8_SkColorType, width, height)) {
315                return error_return(*bm, "chooseFromOneChoice");
316            }
317#endif
318
319            SkScaledBitmapSampler sampler(width, height, this->getSampleSize());
320
321            bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(),
322                                          kIndex_8_SkColorType, kPremul_SkAlphaType));
323
324            if (SkImageDecoder::kDecodeBounds_Mode == mode) {
325                return true;
326            }
327
328
329            // now we decode the colortable
330            int colorCount = 0;
331            {
332                // Declare colorPtr here for scope.
333                SkPMColor colorPtr[256]; // storage for worst-case
334                const ColorMapObject* cmap = find_colormap(gif);
335                SkAlphaType alphaType = kOpaque_SkAlphaType;
336                if (cmap != NULL) {
337                    SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel)));
338                    colorCount = cmap->ColorCount;
339                    if (colorCount > 256) {
340                        colorCount = 256;  // our kIndex8 can't support more
341                    }
342                    for (int index = 0; index < colorCount; index++) {
343                        colorPtr[index] = SkPackARGB32(0xFF,
344                                                       cmap->Colors[index].Red,
345                                                       cmap->Colors[index].Green,
346                                                       cmap->Colors[index].Blue);
347                    }
348                } else {
349                    // find_colormap() returned NULL.  Some (rare, broken)
350                    // GIFs don't have a color table, so we force one.
351                    gif_warning(*bm, "missing colormap");
352                    colorCount = 256;
353                    sk_memset32(colorPtr, SK_ColorWHITE, colorCount);
354                }
355                transpIndex = find_transpIndex(temp_save, colorCount);
356                if (transpIndex >= 0) {
357                    colorPtr[transpIndex] = SK_ColorTRANSPARENT; // ram in a transparent SkPMColor
358                    alphaType = kPremul_SkAlphaType;
359                    fillIndex = transpIndex;
360                } else if (fillIndex >= colorCount) {
361                    // gif->SBackGroundColor should be less than colorCount.
362                    fillIndex = 0;  // If not, fix it.
363                }
364
365                SkAutoTUnref<SkColorTable> ctable(SkNEW_ARGS(SkColorTable,
366                                                  (colorPtr, colorCount,
367                                                   alphaType)));
368                if (!this->allocPixelRef(bm, ctable)) {
369                    return error_return(*bm, "allocPixelRef");
370                }
371            }
372
373            // abort if either inner dimension is <= 0
374            if (innerWidth <= 0 || innerHeight <= 0) {
375                return error_return(*bm, "non-pos inner width/height");
376            }
377
378            SkAutoLockPixels alp(*bm);
379
380            SkAutoMalloc storage(innerWidth);
381            uint8_t* scanline = (uint8_t*) storage.get();
382
383            // GIF has an option to store the scanlines of an image, plus a larger background,
384            // filled by a fill color. In this case, we will use a subset of the larger bitmap
385            // for sampling.
386            SkBitmap subset;
387            SkBitmap* workingBitmap;
388            // are we only a subset of the total bounds?
389            if ((imageTop | imageLeft) > 0 ||
390                 innerWidth < width || innerHeight < height) {
391                // Fill the background.
392                memset(bm->getPixels(), fillIndex, bm->getSize());
393
394                // Create a subset of the bitmap.
395                SkIRect subsetRect(SkIRect::MakeXYWH(imageLeft / sampler.srcDX(),
396                                                     imageTop / sampler.srcDY(),
397                                                     innerWidth / sampler.srcDX(),
398                                                     innerHeight / sampler.srcDY()));
399                if (!bm->extractSubset(&subset, subsetRect)) {
400                    return error_return(*bm, "Extract failed.");
401                }
402                // Update the sampler. We'll now be only sampling into the subset.
403                sampler = SkScaledBitmapSampler(innerWidth, innerHeight, this->getSampleSize());
404                workingBitmap = &subset;
405            } else {
406                workingBitmap = bm;
407            }
408
409            // bm is already locked, but if we had to take a subset, it must be locked also,
410            // so that getPixels() will point to its pixels.
411            SkAutoLockPixels alpWorking(*workingBitmap);
412
413            if (!sampler.begin(workingBitmap, SkScaledBitmapSampler::kIndex, *this)) {
414                return error_return(*bm, "Sampler failed to begin.");
415            }
416
417            // now decode each scanline
418            if (gif->Image.Interlace) {
419                // Iterate over the height of the source data. The sampler will
420                // take care of skipping unneeded rows.
421                GifInterlaceIter iter(innerHeight);
422                for (int y = 0; y < innerHeight; y++) {
423                    if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
424                        gif_warning(*bm, "interlace DGifGetLine");
425                        memset(scanline, fillIndex, innerWidth);
426                        for (; y < innerHeight; y++) {
427                            sampler.sampleInterlaced(scanline, iter.currY());
428                            iter.next();
429                        }
430                        return true;
431                    }
432                    sampler.sampleInterlaced(scanline, iter.currY());
433                    iter.next();
434                }
435            } else {
436                // easy, non-interlace case
437                const int outHeight = workingBitmap->height();
438                skip_src_rows(gif, scanline, innerWidth, sampler.srcY0());
439                for (int y = 0; y < outHeight; y++) {
440                    if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
441                        gif_warning(*bm, "DGifGetLine");
442                        memset(scanline, fillIndex, innerWidth);
443                        for (; y < outHeight; y++) {
444                            sampler.next(scanline);
445                        }
446                        return true;
447                    }
448                    // scanline now contains the raw data. Sample it.
449                    sampler.next(scanline);
450                    if (y < outHeight - 1) {
451                        skip_src_rows(gif, scanline, innerWidth, sampler.srcDY() - 1);
452                    }
453                }
454                // skip the rest of the rows (if any)
455                int read = (outHeight - 1) * sampler.srcDY() + sampler.srcY0() + 1;
456                SkASSERT(read <= innerHeight);
457                skip_src_rows(gif, scanline, innerWidth, innerHeight - read);
458            }
459            sanitize_indexed_bitmap(bm);
460            return true;
461            } break;
462
463        case EXTENSION_RECORD_TYPE:
464#if GIFLIB_MAJOR < 5
465            if (DGifGetExtension(gif, &temp_save.Function,
466                                 &extData) == GIF_ERROR) {
467#else
468            if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) {
469#endif
470                return error_return(*bm, "DGifGetExtension");
471            }
472
473            while (extData != NULL) {
474                /* Create an extension block with our data */
475#if GIFLIB_MAJOR < 5
476                if (AddExtensionBlock(&temp_save, extData[0],
477                                      &extData[1]) == GIF_ERROR) {
478#else
479                if (GifAddExtensionBlock(&gif->ExtensionBlockCount,
480                                         &gif->ExtensionBlocks,
481                                         extFunction,
482                                         extData[0],
483                                         &extData[1]) == GIF_ERROR) {
484#endif
485                    return error_return(*bm, "AddExtensionBlock");
486                }
487                if (DGifGetExtensionNext(gif, &extData) == GIF_ERROR) {
488                    return error_return(*bm, "DGifGetExtensionNext");
489                }
490#if GIFLIB_MAJOR < 5
491                temp_save.Function = 0;
492#endif
493            }
494            break;
495
496        case TERMINATE_RECORD_TYPE:
497            break;
498
499        default:    /* Should be trapped by DGifGetRecordType */
500            break;
501        }
502    } while (recType != TERMINATE_RECORD_TYPE);
503
504    sanitize_indexed_bitmap(bm);
505    return true;
506}
507
508///////////////////////////////////////////////////////////////////////////////
509DEFINE_DECODER_CREATOR(GIFImageDecoder);
510///////////////////////////////////////////////////////////////////////////////
511
512static bool is_gif(SkStreamRewindable* stream) {
513    char buf[GIF_STAMP_LEN];
514    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
515        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
516                memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
517                memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
518            return true;
519        }
520    }
521    return false;
522}
523
524static SkImageDecoder* sk_libgif_dfactory(SkStreamRewindable* stream) {
525    if (is_gif(stream)) {
526        return SkNEW(SkGIFImageDecoder);
527    }
528    return NULL;
529}
530
531static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory);
532
533static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) {
534    if (is_gif(stream)) {
535        return SkImageDecoder::kGIF_Format;
536    }
537    return SkImageDecoder::kUnknown_Format;
538}
539
540static SkImageDecoder_FormatReg gFormatReg(get_format_gif);
541