Home | History | Annotate | Download | only in images
      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 
     20 class SkGIFImageDecoder : public SkImageDecoder {
     21 public:
     22     virtual Format getFormat() const SK_OVERRIDE {
     23         return kGIF_Format;
     24     }
     25 
     26 protected:
     27     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode) SK_OVERRIDE;
     28 
     29 private:
     30     typedef SkImageDecoder INHERITED;
     31 };
     32 
     33 static const uint8_t gStartingIterlaceYValue[] = {
     34     0, 4, 2, 1
     35 };
     36 static const uint8_t gDeltaIterlaceYValue[] = {
     37     8, 8, 4, 2
     38 };
     39 
     40 SK_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 */
     52 class GifInterlaceIter {
     53 public:
     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 
     91 private:
     92     const int fHeight;
     93     int fCurrY;
     94     int fDeltaY;
     95     const uint8_t* fStartYPtr;
     96     const uint8_t* fDeltaYPtr;
     97 };
     98 
     99 ///////////////////////////////////////////////////////////////////////////////
    100 
    101 static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out,
    102                               int size) {
    103     SkStream* stream = (SkStream*) fileType->UserData;
    104     return (int) stream->read(out, size);
    105 }
    106 
    107 void 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
    118 static 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)
    137 static 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 
    155 static 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 }
    163 static 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  */
    179 static 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  */
    194 static 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 
    231 bool 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 ///////////////////////////////////////////////////////////////////////////////
    509 DEFINE_DECODER_CREATOR(GIFImageDecoder);
    510 ///////////////////////////////////////////////////////////////////////////////
    511 
    512 static 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 
    524 static SkImageDecoder* sk_libgif_dfactory(SkStreamRewindable* stream) {
    525     if (is_gif(stream)) {
    526         return SkNEW(SkGIFImageDecoder);
    527     }
    528     return NULL;
    529 }
    530 
    531 static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory);
    532 
    533 static 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 
    540 static SkImageDecoder_FormatReg gFormatReg(get_format_gif);
    541