Home | History | Annotate | Download | only in codec
      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_libgif.h"
      9 #include "SkCodecPriv.h"
     10 #include "SkColorPriv.h"
     11 #include "SkColorTable.h"
     12 #include "SkGifInterlaceIter.h"
     13 #include "SkStream.h"
     14 #include "SkSwizzler.h"
     15 #include "SkUtils.h"
     16 
     17 /*
     18  * Checks the start of the stream to see if the image is a gif
     19  */
     20 bool SkGifCodec::IsGif(SkStream* stream) {
     21     char buf[GIF_STAMP_LEN];
     22     if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
     23         if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
     24                 memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
     25                 memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
     26             return true;
     27         }
     28     }
     29     return false;
     30 }
     31 
     32 /*
     33  * Warning reporting function
     34  */
     35 static void gif_warning(const char* msg) {
     36     SkCodecPrintf("Gif Warning: %s\n", msg);
     37 }
     38 
     39 /*
     40  * Error function
     41  */
     42 static SkCodec::Result gif_error(const char* msg,
     43         SkCodec::Result result = SkCodec::kInvalidInput) {
     44     SkCodecPrintf("Gif Error: %s\n", msg);
     45     return result;
     46 }
     47 
     48 
     49 /*
     50  * Read function that will be passed to gif_lib
     51  */
     52 static int32_t read_bytes_callback(GifFileType* fileType, GifByteType* out,
     53         int32_t size) {
     54     SkStream* stream = (SkStream*) fileType->UserData;
     55     return (int32_t) stream->read(out, size);
     56 }
     57 
     58 /*
     59  * Open the gif file
     60  */
     61 static GifFileType* open_gif(SkStream* stream) {
     62 #if GIFLIB_MAJOR < 5
     63     return DGifOpen(stream, read_bytes_callback);
     64 #else
     65     return DGifOpen(stream, read_bytes_callback, NULL);
     66 #endif
     67 }
     68 
     69  /*
     70  * This function cleans up the gif object after the decode completes
     71  * It is used in a SkAutoTCallIProc template
     72  */
     73 void SkGifCodec::CloseGif(GifFileType* gif) {
     74 #if GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)
     75     DGifCloseFile(gif);
     76 #else
     77     DGifCloseFile(gif, NULL);
     78 #endif
     79 }
     80 
     81 /*
     82  * This function free extension data that has been saved to assist the image
     83  * decoder
     84  */
     85 void SkGifCodec::FreeExtension(SavedImage* image) {
     86     if (NULL != image->ExtensionBlocks) {
     87 #if GIFLIB_MAJOR < 5
     88         FreeExtension(image);
     89 #else
     90         GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks);
     91 #endif
     92     }
     93 }
     94 
     95 /*
     96  * Check if a there is an index of the color table for a transparent pixel
     97  */
     98 static uint32_t find_trans_index(const SavedImage& image) {
     99     // If there is a transparent index specified, it will be contained in an
    100     // extension block.  We will loop through extension blocks in reverse order
    101     // to check the most recent extension blocks first.
    102     for (int32_t i = image.ExtensionBlockCount - 1; i >= 0; i--) {
    103         // Get an extension block
    104         const ExtensionBlock& extBlock = image.ExtensionBlocks[i];
    105 
    106         // Specifically, we need to check for a graphics control extension,
    107         // which may contain transparency information.  Also, note that a valid
    108         // graphics control extension is always four bytes.  The fourth byte
    109         // is the transparent index (if it exists), so we need at least four
    110         // bytes.
    111         if (GRAPHICS_EXT_FUNC_CODE == extBlock.Function &&
    112                 extBlock.ByteCount >= 4) {
    113 
    114             // Check the transparent color flag which indicates whether a
    115             // transparent index exists.  It is the least significant bit of
    116             // the first byte of the extension block.
    117             if (1 == (extBlock.Bytes[0] & 1)) {
    118 
    119                 // Use uint32_t to prevent sign extending
    120                 return extBlock.Bytes[3];
    121             }
    122 
    123             // There should only be one graphics control extension for the image frame
    124             break;
    125         }
    126     }
    127 
    128     // Use maximum unsigned int (surely an invalid index) to indicate that a valid
    129     // index was not found.
    130     return SK_MaxU32;
    131 }
    132 
    133 /*
    134  * Read enough of the stream to initialize the SkGifCodec.
    135  * Returns a bool representing success or failure.
    136  *
    137  * @param codecOut
    138  * If it returned true, and codecOut was not NULL,
    139  * codecOut will be set to a new SkGifCodec.
    140  *
    141  * @param gifOut
    142  * If it returned true, and codecOut was NULL,
    143  * gifOut must be non-NULL and gifOut will be set to a new
    144  * GifFileType pointer.
    145  *
    146  * @param stream
    147  * Deleted on failure.
    148  * codecOut will take ownership of it in the case where we created a codec.
    149  * Ownership is unchanged when we returned a gifOut.
    150  *
    151  */
    152 bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) {
    153     SkAutoTDelete<SkStream> streamDeleter(stream);
    154 
    155     // Read gif header, logical screen descriptor, and global color table
    156     SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream));
    157 
    158     if (NULL == gif) {
    159         gif_error("DGifOpen failed.\n");
    160         return false;
    161     }
    162 
    163     if (NULL != codecOut) {
    164         // Get fields from header
    165         const int32_t width = gif->SWidth;
    166         const int32_t height = gif->SHeight;
    167         if (width <= 0 || height <= 0) {
    168             gif_error("Invalid dimensions.\n");
    169             return false;
    170         }
    171 
    172         // Return the codec
    173         // kIndex is the most natural color type for gifs, so we set this as
    174         // the default.
    175         // Many gifs specify a color table index for transparent pixels.  Every
    176         // other pixel is guaranteed to be opaque.  Despite this, because of the
    177         // possiblity of transparent pixels, we cannot assume that the image is
    178         // opaque.  We have the option to set the alpha type as kPremul or
    179         // kUnpremul.  Both are valid since the alpha component will always be
    180         // 0xFF or the entire 32-bit pixel will be set to zero.  We prefer
    181         // kPremul because we support kPremul, and it is more efficient to
    182         // use kPremul directly even when kUnpremul is supported.
    183         const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
    184                 kIndex_8_SkColorType, kPremul_SkAlphaType);
    185         *codecOut = SkNEW_ARGS(SkGifCodec, (imageInfo, streamDeleter.detach(), gif.detach()));
    186     } else {
    187         SkASSERT(NULL != gifOut);
    188         streamDeleter.detach();
    189         *gifOut = gif.detach();
    190     }
    191     return true;
    192 }
    193 
    194 /*
    195  * Assumes IsGif was called and returned true
    196  * Creates a gif decoder
    197  * Reads enough of the stream to determine the image format
    198  */
    199 SkCodec* SkGifCodec::NewFromStream(SkStream* stream) {
    200     SkCodec* codec = NULL;
    201     if (ReadHeader(stream, &codec, NULL)) {
    202         return codec;
    203     }
    204     return NULL;
    205 }
    206 
    207 SkGifCodec::SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream,
    208                        GifFileType* gif)
    209     : INHERITED(srcInfo, stream)
    210     , fGif(gif)
    211 {}
    212 
    213 /*
    214  * Checks if the conversion between the input image and the requested output
    215  * image has been implemented
    216  */
    217 static bool conversion_possible(const SkImageInfo& dst,
    218                                 const SkImageInfo& src) {
    219     // Ensure that the profile type is unchanged
    220     if (dst.profileType() != src.profileType()) {
    221         return false;
    222     }
    223 
    224     // Check for supported color and alpha types
    225     switch (dst.colorType()) {
    226         case kN32_SkColorType:
    227             return kPremul_SkAlphaType == dst.alphaType() ||
    228                     kUnpremul_SkAlphaType == dst.alphaType();
    229         case kIndex_8_SkColorType:
    230             return kPremul_SkAlphaType == dst.alphaType() ||
    231                     kUnpremul_SkAlphaType == dst.alphaType();
    232         default:
    233             return false;
    234     }
    235 }
    236 
    237 /*
    238  * Initiates the gif decode
    239  */
    240 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
    241                                         void* dst, size_t dstRowBytes,
    242                                         const Options& opts,
    243                                         SkPMColor* inputColorPtr,
    244                                         int* inputColorCount) {
    245     // Rewind if necessary
    246     SkCodec::RewindState rewindState = this->rewindIfNeeded();
    247     if (rewindState == kCouldNotRewind_RewindState) {
    248         return kCouldNotRewind;
    249     } else if (rewindState == kRewound_RewindState) {
    250         GifFileType* gifOut = NULL;
    251         if (!ReadHeader(this->stream(), NULL, &gifOut)) {
    252             return kCouldNotRewind;
    253         } else {
    254             SkASSERT(NULL != gifOut);
    255             fGif.reset(gifOut);
    256         }
    257     }
    258 
    259     // Check for valid input parameters
    260     if (dstInfo.dimensions() != this->getInfo().dimensions()) {
    261         return gif_error("Scaling not supported.\n", kInvalidScale);
    262     }
    263     if (!conversion_possible(dstInfo, this->getInfo())) {
    264         return gif_error("Cannot convert input type to output type.\n",
    265                 kInvalidConversion);
    266     }
    267 
    268     // Use this as a container to hold information about any gif extension
    269     // blocks.  This generally stores transparency and animation instructions.
    270     SavedImage saveExt;
    271     SkAutoTCallVProc<SavedImage, FreeExtension> autoFreeExt(&saveExt);
    272     saveExt.ExtensionBlocks = NULL;
    273     saveExt.ExtensionBlockCount = 0;
    274     GifByteType* extData;
    275 #if GIFLIB_MAJOR >= 5
    276     int32_t extFunction;
    277 #endif
    278 
    279     // We will loop over components of gif images until we find an image.  Once
    280     // we find an image, we will decode and return it.  While many gif files
    281     // contain more than one image, we will simply decode the first image.
    282     const int32_t width = dstInfo.width();
    283     const int32_t height = dstInfo.height();
    284     GifRecordType recordType;
    285     do {
    286         // Get the current record type
    287         if (GIF_ERROR == DGifGetRecordType(fGif, &recordType)) {
    288             return gif_error("DGifGetRecordType failed.\n", kInvalidInput);
    289         }
    290 
    291         switch (recordType) {
    292             case IMAGE_DESC_RECORD_TYPE: {
    293                 // Read the image descriptor
    294                 if (GIF_ERROR == DGifGetImageDesc(fGif)) {
    295                     return gif_error("DGifGetImageDesc failed.\n",
    296                             kInvalidInput);
    297                 }
    298 
    299                 // If reading the image descriptor is successful, the image
    300                 // count will be incremented
    301                 SkASSERT(fGif->ImageCount >= 1);
    302                 SavedImage* image = &fGif->SavedImages[fGif->ImageCount - 1];
    303 
    304                 // Process the descriptor
    305                 const GifImageDesc& desc = image->ImageDesc;
    306                 int32_t imageLeft = desc.Left;
    307                 int32_t imageTop = desc.Top;
    308                 int32_t innerWidth = desc.Width;
    309                 int32_t innerHeight = desc.Height;
    310                 // Fail on non-positive dimensions
    311                 if (innerWidth <= 0 || innerHeight <= 0) {
    312                     return gif_error("Invalid dimensions for inner image.\n",
    313                             kInvalidInput);
    314                 }
    315                 // Treat the following cases as warnings and try to fix
    316                 if (innerWidth > width) {
    317                     gif_warning("Inner image too wide, shrinking.\n");
    318                     innerWidth = width;
    319                     imageLeft = 0;
    320                 } else if (imageLeft + innerWidth > width) {
    321                     gif_warning("Shifting inner image to left to fit.\n");
    322                     imageLeft = width - innerWidth;
    323                 } else if (imageLeft < 0) {
    324                     gif_warning("Shifting image to right to fit\n");
    325                     imageLeft = 0;
    326                 }
    327                 if (innerHeight > height) {
    328                     gif_warning("Inner image too tall, shrinking.\n");
    329                     innerHeight = height;
    330                     imageTop = 0;
    331                 } else if (imageTop + innerHeight > height) {
    332                     gif_warning("Shifting inner image up to fit.\n");
    333                     imageTop = height - innerHeight;
    334                 } else if (imageTop < 0) {
    335                     gif_warning("Shifting image down to fit\n");
    336                     imageTop = 0;
    337                 }
    338 
    339                 // Create a color table to store colors the giflib colorMap
    340                 SkPMColor alternateColorPtr[256];
    341                 SkPMColor* colorTable;
    342                 SkColorType dstColorType = dstInfo.colorType();
    343                 if (kIndex_8_SkColorType == dstColorType) {
    344                     SkASSERT(NULL != inputColorPtr);
    345                     SkASSERT(NULL != inputColorCount);
    346                     colorTable = inputColorPtr;
    347                 } else {
    348                     colorTable = alternateColorPtr;
    349                 }
    350 
    351                 // Set up the color table
    352                 uint32_t colorCount = 0;
    353                 // Allocate maximum storage to deal with invalid indices safely
    354                 const uint32_t maxColors = 256;
    355                 ColorMapObject* colorMap = fGif->Image.ColorMap;
    356                 // If there is no local color table, use the global color table
    357                 if (NULL == colorMap) {
    358                     colorMap = fGif->SColorMap;
    359                 }
    360                 if (NULL != colorMap) {
    361                     colorCount = colorMap->ColorCount;
    362                     SkASSERT(colorCount ==
    363                             (unsigned) (1 << (colorMap->BitsPerPixel)));
    364                     SkASSERT(colorCount <= 256);
    365                     for (uint32_t i = 0; i < colorCount; i++) {
    366                         colorTable[i] = SkPackARGB32(0xFF,
    367                                                      colorMap->Colors[i].Red,
    368                                                      colorMap->Colors[i].Green,
    369                                                      colorMap->Colors[i].Blue);
    370                     }
    371                 }
    372 
    373                 // This is used to fill unspecified pixels in the image data.
    374                 uint32_t fillIndex = fGif->SBackGroundColor;
    375                 ZeroInitialized zeroInit = opts.fZeroInitialized;
    376 
    377                 // Gifs have the option to specify the color at a single
    378                 // index of the color table as transparent.
    379                 {
    380                     // Get the transparent index.  If the return value of this
    381                     // function is greater than the colorCount, we know that
    382                     // there is no valid transparent color in the color table.
    383                     // This occurs if there is no graphics control extension or
    384                     // if the index specified by the graphics control extension
    385                     // is out of range.
    386                     uint32_t transIndex = find_trans_index(saveExt);
    387 
    388                     if (transIndex < colorCount) {
    389                         colorTable[transIndex] = SK_ColorTRANSPARENT;
    390                         // If there is a transparent index, we also use this as
    391                         // the fill index.
    392                         fillIndex = transIndex;
    393                     } else if (fillIndex >= colorCount) {
    394                         // If the fill index is invalid, we default to 0.  This
    395                         // behavior is unspecified but matches SkImageDecoder.
    396                         fillIndex = 0;
    397                     }
    398                 }
    399 
    400                 // Check if we can skip filling the background of the image.  We
    401                 // may be able to if the memory is zero initialized.
    402                 bool skipBackground =
    403                         ((kN32_SkColorType == dstColorType && colorTable[fillIndex] == 0) ||
    404                         (kIndex_8_SkColorType == dstColorType && fillIndex == 0)) &&
    405                         kYes_ZeroInitialized == zeroInit;
    406 
    407 
    408                 // Fill in the color table for indices greater than color count.
    409                 // This allows for predictable, safe behavior.
    410                 for (uint32_t i = colorCount; i < maxColors; i++) {
    411                     colorTable[i] = colorTable[fillIndex];
    412                 }
    413 
    414                 // Check if image is only a subset of the image frame
    415                 SkAutoTDelete<SkSwizzler> swizzler(NULL);
    416                 if (innerWidth < width || innerHeight < height) {
    417 
    418                     // Modify the destination info
    419                     const SkImageInfo subsetDstInfo =
    420                             dstInfo.makeWH(innerWidth, innerHeight);
    421 
    422                     // Fill the destination with the fill color
    423                     // FIXME: This may not be the behavior that we want for
    424                     //        animated gifs where we draw on top of the
    425                     //        previous frame.
    426                     if (!skipBackground) {
    427                         SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fillIndex, colorTable);
    428                     }
    429 
    430                     // Modify the dst pointer
    431                     const int32_t dstBytesPerPixel =
    432                             SkColorTypeBytesPerPixel(dstColorType);
    433                     void* subsetDst = SkTAddOffset<void*>(dst,
    434                             dstRowBytes * imageTop +
    435                             dstBytesPerPixel * imageLeft);
    436 
    437                     // Create the subset swizzler
    438                     swizzler.reset(SkSwizzler::CreateSwizzler(
    439                             SkSwizzler::kIndex, colorTable, subsetDstInfo,
    440                             subsetDst, dstRowBytes, zeroInit));
    441                 } else {
    442                     // Create the fully dimensional swizzler
    443                     swizzler.reset(SkSwizzler::CreateSwizzler(
    444                             SkSwizzler::kIndex, colorTable, dstInfo, dst,
    445                             dstRowBytes, zeroInit));
    446                 }
    447 
    448                 // Stores output from dgiflib and input to the swizzler
    449                 SkAutoTDeleteArray<uint8_t>
    450                         buffer(SkNEW_ARRAY(uint8_t, innerWidth));
    451 
    452                 // Check the interlace flag and iterate over rows of the input
    453                 if (fGif->Image.Interlace) {
    454                     // In interlace mode, the rows of input are rearranged in
    455                     // the output image.  We use an iterator to take care of
    456                     // the rearranging.
    457                     SkGifInterlaceIter iter(innerHeight);
    458                     for (int32_t y = 0; y < innerHeight; y++) {
    459                         if (GIF_ERROR == DGifGetLine(fGif, buffer.get(),
    460                                 innerWidth)) {
    461                             // Recover from error by filling remainder of image
    462                             if (!skipBackground) {
    463                                 memset(buffer.get(), fillIndex, innerWidth);
    464                                 for (; y < innerHeight; y++) {
    465                                     swizzler->next(buffer.get(), iter.nextY());
    466                                 }
    467                             }
    468                             return gif_error(SkStringPrintf(
    469                                     "Could not decode line %d of %d.\n",
    470                                     y, height - 1).c_str(), kIncompleteInput);
    471                         }
    472                         swizzler->next(buffer.get(), iter.nextY());
    473                     }
    474                 } else {
    475                     // Standard mode
    476                     for (int32_t y = 0; y < innerHeight; y++) {
    477                         if (GIF_ERROR == DGifGetLine(fGif, buffer.get(),
    478                                 innerWidth)) {
    479                             if (!skipBackground) {
    480                                 SkSwizzler::Fill(swizzler->getDstRow(), dstInfo, dstRowBytes,
    481                                         innerHeight - y, fillIndex, colorTable);
    482                             }
    483                             return gif_error(SkStringPrintf(
    484                                     "Could not decode line %d of %d.\n",
    485                                     y, height - 1).c_str(), kIncompleteInput);
    486                         }
    487                         swizzler->next(buffer.get());
    488                     }
    489                 }
    490 
    491                 // FIXME: Gif files may have multiple images stored in a single
    492                 //        file.  This is most commonly used to enable
    493                 //        animations.  Since we are leaving animated gifs as a
    494                 //        TODO, we will return kSuccess after decoding the
    495                 //        first image in the file.  This is the same behavior
    496                 //        as SkImageDecoder_libgif.
    497                 //
    498                 //        Most times this works pretty well, but sometimes it
    499                 //        doesn't.  For example, I have an animated test image
    500                 //        where the first image in the file is 1x1, but the
    501                 //        subsequent images are meaningful.  This currently
    502                 //        displays the 1x1 image, which is not ideal.  Right
    503                 //        now I am leaving this as an issue that will be
    504                 //        addressed when we implement animated gifs.
    505                 //
    506                 //        It is also possible (not explicitly disallowed in the
    507                 //        specification) that gif files provide multiple
    508                 //        images in a single file that are all meant to be
    509                 //        displayed in the same frame together.  I will
    510                 //        currently leave this unimplemented until I find a
    511                 //        test case that expects this behavior.
    512                 return kSuccess;
    513             }
    514 
    515             // Extensions are used to specify special properties of the image
    516             // such as transparency or animation.
    517             case EXTENSION_RECORD_TYPE:
    518                 // Read extension data
    519 #if GIFLIB_MAJOR < 5
    520                 if (GIF_ERROR ==
    521                         DGifGetExtension(fGif, &saveExt.Function, &extData)) {
    522 #else
    523                 if (GIF_ERROR ==
    524                         DGifGetExtension(fGif, &extFunction, &extData)) {
    525 #endif
    526                     return gif_error("Could not get extension.\n",
    527                             kIncompleteInput);
    528                 }
    529 
    530                 // Create an extension block with our data
    531                 while (NULL != extData) {
    532                     // Add a single block
    533 #if GIFLIB_MAJOR < 5
    534                     if (GIF_ERROR == AddExtensionBlock(&saveExt, extData[0],
    535                             &extData[1])) {
    536 #else
    537                     if (GIF_ERROR ==
    538                             GifAddExtensionBlock(&saveExt.ExtensionBlockCount,
    539                             &saveExt.ExtensionBlocks, extFunction, extData[0],
    540                             &extData[1])) {
    541 #endif
    542                         return gif_error("Could not add extension block.\n",
    543                                 kIncompleteInput);
    544                     }
    545                     // Move to the next block
    546                     if (GIF_ERROR == DGifGetExtensionNext(fGif, &extData)) {
    547                         return gif_error("Could not get next extension.\n",
    548                                 kIncompleteInput);
    549                     }
    550 #if GIFLIB_MAJOR < 5
    551                     saveExt.Function = 0;
    552 #endif
    553                 }
    554                 break;
    555 
    556             // Signals the end of the gif file
    557             case TERMINATE_RECORD_TYPE:
    558                 break;
    559 
    560             default:
    561                 // giflib returns an error code if the record type is not known.
    562                 // We should catch this error immediately.
    563                 SkASSERT(false);
    564                 break;
    565         }
    566     } while (TERMINATE_RECORD_TYPE != recordType);
    567 
    568     return gif_error("Could not find any images to decode in gif file.\n",
    569             kInvalidInput);
    570 }
    571