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 "SkCodecPriv.h" 9#include "SkColorPriv.h" 10#include "SkColorTable.h" 11#include "SkGifCodec.h" 12#include "SkStream.h" 13#include "SkSwizzler.h" 14#include "SkUtils.h" 15 16#include "gif_lib.h" 17 18/* 19 * Checks the start of the stream to see if the image is a gif 20 */ 21bool SkGifCodec::IsGif(const void* buf, size_t bytesRead) { 22 if (bytesRead >= 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 { 27 return true; 28 } 29 } 30 return false; 31} 32 33/* 34 * Error function 35 */ 36static SkCodec::Result gif_error(const char* msg, SkCodec::Result result = SkCodec::kInvalidInput) { 37 SkCodecPrintf("Gif Error: %s\n", msg); 38 return result; 39} 40 41 42/* 43 * Read function that will be passed to gif_lib 44 */ 45static int32_t read_bytes_callback(GifFileType* fileType, GifByteType* out, int32_t size) { 46 SkStream* stream = (SkStream*) fileType->UserData; 47 return (int32_t) stream->read(out, size); 48} 49 50/* 51 * Open the gif file 52 */ 53static GifFileType* open_gif(SkStream* stream) { 54#if GIFLIB_MAJOR < 5 55 return DGifOpen(stream, read_bytes_callback); 56#else 57 return DGifOpen(stream, read_bytes_callback, nullptr); 58#endif 59} 60 61/* 62 * Check if a there is an index of the color table for a transparent pixel 63 */ 64static uint32_t find_trans_index(const SavedImage& image) { 65 // If there is a transparent index specified, it will be contained in an 66 // extension block. We will loop through extension blocks in reverse order 67 // to check the most recent extension blocks first. 68 for (int32_t i = image.ExtensionBlockCount - 1; i >= 0; i--) { 69 // Get an extension block 70 const ExtensionBlock& extBlock = image.ExtensionBlocks[i]; 71 72 // Specifically, we need to check for a graphics control extension, 73 // which may contain transparency information. Also, note that a valid 74 // graphics control extension is always four bytes. The fourth byte 75 // is the transparent index (if it exists), so we need at least four 76 // bytes. 77 if (GRAPHICS_EXT_FUNC_CODE == extBlock.Function && extBlock.ByteCount >= 4) { 78 // Check the transparent color flag which indicates whether a 79 // transparent index exists. It is the least significant bit of 80 // the first byte of the extension block. 81 if (1 == (extBlock.Bytes[0] & 1)) { 82 // Use uint32_t to prevent sign extending 83 return extBlock.Bytes[3]; 84 } 85 86 // There should only be one graphics control extension for the image frame 87 break; 88 } 89 } 90 91 // Use maximum unsigned int (surely an invalid index) to indicate that a valid 92 // index was not found. 93 return SK_MaxU32; 94} 95 96inline uint32_t ceil_div(uint32_t a, uint32_t b) { 97 return (a + b - 1) / b; 98} 99 100/* 101 * Gets the output row corresponding to the encoded row for interlaced gifs 102 */ 103inline uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) { 104 SkASSERT(encodedRow < height); 105 // First pass 106 if (encodedRow * 8 < height) { 107 return encodedRow * 8; 108 } 109 // Second pass 110 if (encodedRow * 4 < height) { 111 return 4 + 8 * (encodedRow - ceil_div(height, 8)); 112 } 113 // Third pass 114 if (encodedRow * 2 < height) { 115 return 2 + 4 * (encodedRow - ceil_div(height, 4)); 116 } 117 // Fourth pass 118 return 1 + 2 * (encodedRow - ceil_div(height, 2)); 119} 120 121/* 122 * This function cleans up the gif object after the decode completes 123 * It is used in a SkAutoTCallIProc template 124 */ 125void SkGifCodec::CloseGif(GifFileType* gif) { 126#if GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0) 127 DGifCloseFile(gif); 128#else 129 DGifCloseFile(gif, nullptr); 130#endif 131} 132 133/* 134 * This function free extension data that has been saved to assist the image 135 * decoder 136 */ 137void SkGifCodec::FreeExtension(SavedImage* image) { 138 if (NULL != image->ExtensionBlocks) { 139#if GIFLIB_MAJOR < 5 140 FreeExtension(image); 141#else 142 GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks); 143#endif 144 } 145} 146 147/* 148 * Read enough of the stream to initialize the SkGifCodec. 149 * Returns a bool representing success or failure. 150 * 151 * @param codecOut 152 * If it returned true, and codecOut was not nullptr, 153 * codecOut will be set to a new SkGifCodec. 154 * 155 * @param gifOut 156 * If it returned true, and codecOut was nullptr, 157 * gifOut must be non-nullptr and gifOut will be set to a new 158 * GifFileType pointer. 159 * 160 * @param stream 161 * Deleted on failure. 162 * codecOut will take ownership of it in the case where we created a codec. 163 * Ownership is unchanged when we returned a gifOut. 164 * 165 */ 166bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) { 167 SkAutoTDelete<SkStream> streamDeleter(stream); 168 169 // Read gif header, logical screen descriptor, and global color table 170 SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream)); 171 172 if (nullptr == gif) { 173 gif_error("DGifOpen failed.\n"); 174 return false; 175 } 176 177 // Read through gif extensions to get to the image data. Set the 178 // transparent index based on the extension data. 179 uint32_t transIndex; 180 SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex); 181 if (kSuccess != result){ 182 return false; 183 } 184 185 // Read the image descriptor 186 if (GIF_ERROR == DGifGetImageDesc(gif)) { 187 return false; 188 } 189 // If reading the image descriptor is successful, the image count will be 190 // incremented. 191 SkASSERT(gif->ImageCount >= 1); 192 193 if (nullptr != codecOut) { 194 SkISize size; 195 SkIRect frameRect; 196 if (!GetDimensions(gif, &size, &frameRect)) { 197 gif_error("Invalid gif size.\n"); 198 return false; 199 } 200 bool frameIsSubset = (size != frameRect.size()); 201 202 // Determine the recommended alpha type. The transIndex might be valid if it less 203 // than 256. We are not certain that the index is valid until we process the color 204 // table, since some gifs have color tables with less than 256 colors. If 205 // there might be a valid transparent index, we must indicate that the image has 206 // alpha. 207 // In the case where we must support alpha, we have the option to set the 208 // suggested alpha type to kPremul or kUnpremul. Both are valid since the alpha 209 // component will always be 0xFF or the entire 32-bit pixel will be set to zero. 210 // We prefer kPremul because we support kPremul, and it is more efficient to use 211 // kPremul directly even when kUnpremul is supported. 212 SkAlphaType alphaType = (transIndex < 256) ? kPremul_SkAlphaType : kOpaque_SkAlphaType; 213 214 // Return the codec 215 // kIndex is the most natural color type for gifs, so we set this as 216 // the default. 217 SkImageInfo imageInfo = SkImageInfo::Make(size.width(), size.height(), kIndex_8_SkColorType, 218 alphaType); 219 *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach(), transIndex, 220 frameRect, frameIsSubset); 221 } else { 222 SkASSERT(nullptr != gifOut); 223 streamDeleter.detach(); 224 *gifOut = gif.detach(); 225 } 226 return true; 227} 228 229/* 230 * Assumes IsGif was called and returned true 231 * Creates a gif decoder 232 * Reads enough of the stream to determine the image format 233 */ 234SkCodec* SkGifCodec::NewFromStream(SkStream* stream) { 235 SkCodec* codec = nullptr; 236 if (ReadHeader(stream, &codec, nullptr)) { 237 return codec; 238 } 239 return nullptr; 240} 241 242SkGifCodec::SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType* gif, 243 uint32_t transIndex, const SkIRect& frameRect, bool frameIsSubset) 244 : INHERITED(srcInfo, stream) 245 , fGif(gif) 246 , fSrcBuffer(new uint8_t[this->getInfo().width()]) 247 , fFrameRect(frameRect) 248 // If it is valid, fTransIndex will be used to set fFillIndex. We don't know if 249 // fTransIndex is valid until we process the color table, since fTransIndex may 250 // be greater than the size of the color table. 251 , fTransIndex(transIndex) 252 // Default fFillIndex is 0. We will overwrite this if fTransIndex is valid, or if 253 // there is a valid background color. 254 , fFillIndex(0) 255 , fFrameIsSubset(frameIsSubset) 256 , fSwizzler(NULL) 257 , fColorTable(NULL) 258{} 259 260bool SkGifCodec::onRewind() { 261 GifFileType* gifOut = nullptr; 262 if (!ReadHeader(this->stream(), nullptr, &gifOut)) { 263 return false; 264 } 265 266 SkASSERT(nullptr != gifOut); 267 fGif.reset(gifOut); 268 return true; 269} 270 271SkCodec::Result SkGifCodec::ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex) { 272 // Use this as a container to hold information about any gif extension 273 // blocks. This generally stores transparency and animation instructions. 274 SavedImage saveExt; 275 SkAutoTCallVProc<SavedImage, FreeExtension> autoFreeExt(&saveExt); 276 saveExt.ExtensionBlocks = nullptr; 277 saveExt.ExtensionBlockCount = 0; 278 GifByteType* extData; 279 int32_t extFunction; 280 281 // We will loop over components of gif images until we find an image. Once 282 // we find an image, we will decode and return it. While many gif files 283 // contain more than one image, we will simply decode the first image. 284 GifRecordType recordType; 285 do { 286 // Get the current record type 287 if (GIF_ERROR == DGifGetRecordType(gif, &recordType)) { 288 return gif_error("DGifGetRecordType failed.\n", kInvalidInput); 289 } 290 switch (recordType) { 291 case IMAGE_DESC_RECORD_TYPE: { 292 *transIndex = find_trans_index(saveExt); 293 294 // FIXME: Gif files may have multiple images stored in a single 295 // file. This is most commonly used to enable 296 // animations. Since we are leaving animated gifs as a 297 // TODO, we will return kSuccess after decoding the 298 // first image in the file. This is the same behavior 299 // as SkImageDecoder_libgif. 300 // 301 // Most times this works pretty well, but sometimes it 302 // doesn't. For example, I have an animated test image 303 // where the first image in the file is 1x1, but the 304 // subsequent images are meaningful. This currently 305 // displays the 1x1 image, which is not ideal. Right 306 // now I am leaving this as an issue that will be 307 // addressed when we implement animated gifs. 308 // 309 // It is also possible (not explicitly disallowed in the 310 // specification) that gif files provide multiple 311 // images in a single file that are all meant to be 312 // displayed in the same frame together. I will 313 // currently leave this unimplemented until I find a 314 // test case that expects this behavior. 315 return kSuccess; 316 } 317 // Extensions are used to specify special properties of the image 318 // such as transparency or animation. 319 case EXTENSION_RECORD_TYPE: 320 // Read extension data 321 if (GIF_ERROR == DGifGetExtension(gif, &extFunction, &extData)) { 322 return gif_error("Could not get extension.\n", kIncompleteInput); 323 } 324 325 // Create an extension block with our data 326 while (nullptr != extData) { 327 // Add a single block 328 329#if GIFLIB_MAJOR < 5 330 if (AddExtensionBlock(&saveExt, extData[0], 331 &extData[1]) == GIF_ERROR) { 332#else 333 if (GIF_ERROR == GifAddExtensionBlock(&saveExt.ExtensionBlockCount, 334 &saveExt.ExtensionBlocks, 335 extFunction, extData[0], &extData[1])) { 336#endif 337 return gif_error("Could not add extension block.\n", kIncompleteInput); 338 } 339 // Move to the next block 340 if (GIF_ERROR == DGifGetExtensionNext(gif, &extData)) { 341 return gif_error("Could not get next extension.\n", kIncompleteInput); 342 } 343 } 344 break; 345 346 // Signals the end of the gif file 347 case TERMINATE_RECORD_TYPE: 348 break; 349 350 default: 351 // DGifGetRecordType returns an error if the record type does 352 // not match one of the above cases. This should not be 353 // reached. 354 SkASSERT(false); 355 break; 356 } 357 } while (TERMINATE_RECORD_TYPE != recordType); 358 359 return gif_error("Could not find any images to decode in gif file.\n", kInvalidInput); 360} 361 362bool SkGifCodec::GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect) { 363 // Get the encoded dimension values 364 SavedImage* image = &gif->SavedImages[gif->ImageCount - 1]; 365 const GifImageDesc& desc = image->ImageDesc; 366 int frameLeft = desc.Left; 367 int frameTop = desc.Top; 368 int frameWidth = desc.Width; 369 int frameHeight = desc.Height; 370 int width = gif->SWidth; 371 int height = gif->SHeight; 372 373 // Ensure that the decode dimensions are large enough to contain the frame 374 width = SkTMax(width, frameWidth + frameLeft); 375 height = SkTMax(height, frameHeight + frameTop); 376 377 // All of these dimensions should be positive, as they are encoded as unsigned 16-bit integers. 378 // It is unclear why giflib casts them to ints. We will go ahead and check that they are 379 // in fact positive. 380 if (frameLeft < 0 || frameTop < 0 || frameWidth < 0 || frameHeight < 0 || width <= 0 || 381 height <= 0) { 382 return false; 383 } 384 385 frameRect->setXYWH(frameLeft, frameTop, frameWidth, frameHeight); 386 size->set(width, height); 387 return true; 388} 389 390void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, 391 int* inputColorCount) { 392 // Set up our own color table 393 const uint32_t maxColors = 256; 394 SkPMColor colorPtr[256]; 395 if (NULL != inputColorCount) { 396 // We set the number of colors to maxColors in order to ensure 397 // safe memory accesses. Otherwise, an invalid pixel could 398 // access memory outside of our color table array. 399 *inputColorCount = maxColors; 400 } 401 402 // Get local color table 403 ColorMapObject* colorMap = fGif->Image.ColorMap; 404 // If there is no local color table, use the global color table 405 if (NULL == colorMap) { 406 colorMap = fGif->SColorMap; 407 } 408 409 uint32_t colorCount = 0; 410 if (NULL != colorMap) { 411 colorCount = colorMap->ColorCount; 412 // giflib guarantees these properties 413 SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel))); 414 SkASSERT(colorCount <= 256); 415 for (uint32_t i = 0; i < colorCount; i++) { 416 colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red, 417 colorMap->Colors[i].Green, colorMap->Colors[i].Blue); 418 } 419 } 420 421 // Fill in the color table for indices greater than color count. 422 // This allows for predictable, safe behavior. 423 if (colorCount > 0) { 424 // Gifs have the option to specify the color at a single index of the color 425 // table as transparent. If the transparent index is greater than the 426 // colorCount, we know that there is no valid transparent color in the color 427 // table. If there is not valid transparent index, we will try to use the 428 // backgroundIndex as the fill index. If the backgroundIndex is also not 429 // valid, we will let fFillIndex default to 0 (it is set to zero in the 430 // constructor). This behavior is not specified but matches 431 // SkImageDecoder_libgif. 432 uint32_t backgroundIndex = fGif->SBackGroundColor; 433 if (fTransIndex < colorCount) { 434 colorPtr[fTransIndex] = SK_ColorTRANSPARENT; 435 fFillIndex = fTransIndex; 436 } else if (backgroundIndex < colorCount) { 437 fFillIndex = backgroundIndex; 438 } 439 440 for (uint32_t i = colorCount; i < maxColors; i++) { 441 colorPtr[i] = colorPtr[fFillIndex]; 442 } 443 } else { 444 sk_memset32(colorPtr, 0xFF000000, maxColors); 445 } 446 447 fColorTable.reset(new SkColorTable(colorPtr, maxColors)); 448 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount); 449} 450 451SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr, 452 int* inputColorCount, const Options& opts) { 453 // Check for valid input parameters 454 if (!conversion_possible(dstInfo, this->getInfo())) { 455 return gif_error("Cannot convert input type to output type.\n", 456 kInvalidConversion); 457 } 458 459 // Initialize color table and copy to the client if necessary 460 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); 461 462 this->initializeSwizzler(dstInfo, opts); 463 return kSuccess; 464} 465 466void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& opts) { 467 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 468 const SkIRect* frameRect = fFrameIsSubset ? &fFrameRect : nullptr; 469 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dstInfo, opts, 470 frameRect)); 471 SkASSERT(fSwizzler); 472} 473 474bool SkGifCodec::readRow() { 475 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); 476} 477 478/* 479 * Initiates the gif decode 480 */ 481SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, 482 void* dst, size_t dstRowBytes, 483 const Options& opts, 484 SkPMColor* inputColorPtr, 485 int* inputColorCount, 486 int* rowsDecoded) { 487 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, opts); 488 if (kSuccess != result) { 489 return result; 490 } 491 492 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 493 return gif_error("Scaling not supported.\n", kInvalidScale); 494 } 495 496 // Initialize the swizzler 497 if (fFrameIsSubset) { 498 // Fill the background 499 SkSampler::Fill(dstInfo, dst, dstRowBytes, this->getFillValue(dstInfo.colorType()), 500 opts.fZeroInitialized); 501 } 502 503 // Iterate over rows of the input 504 for (int y = fFrameRect.top(); y < fFrameRect.bottom(); y++) { 505 if (!this->readRow()) { 506 *rowsDecoded = y; 507 return gif_error("Could not decode line.\n", kIncompleteInput); 508 } 509 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanline(y)); 510 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 511 } 512 return kSuccess; 513} 514 515// FIXME: This is similar to the implementation for bmp and png. Can we share more code or 516// possibly make this non-virtual? 517uint32_t SkGifCodec::onGetFillValue(SkColorType colorType) const { 518 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 519 return get_color_table_fill_value(colorType, colorPtr, fFillIndex); 520} 521 522SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 523 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColorCount) { 524 return this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, this->options()); 525} 526 527void SkGifCodec::handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame) { 528 if (fFrameIsSubset) { 529 const int currRow = this->currScanline(); 530 531 // The number of rows that remain to be skipped before reaching rows that we 532 // actually must decode into. 533 // This must be at least zero. We also make sure that it is less than or 534 // equal to count, since we will skip at most count rows. 535 *rowsBeforeFrame = SkTMin(count, SkTMax(0, fFrameRect.top() - currRow)); 536 537 // Rows left to decode once we reach the start of the frame. 538 const int rowsLeft = count - *rowsBeforeFrame; 539 540 // Count the number of that extend beyond the bottom of the frame. We do not 541 // need to decode into these rows. 542 const int rowsAfterFrame = SkTMax(0, currRow + rowsLeft - fFrameRect.bottom()); 543 544 // Set the actual number of source rows that we need to decode. 545 *rowsInFrame = rowsLeft - rowsAfterFrame; 546 } else { 547 *rowsBeforeFrame = 0; 548 *rowsInFrame = count; 549 } 550} 551 552int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { 553 int rowsBeforeFrame; 554 int rowsInFrame; 555 this->handleScanlineFrame(count, &rowsBeforeFrame, &rowsInFrame); 556 557 if (fFrameIsSubset) { 558 // Fill the requested rows 559 SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), count); 560 uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType()); 561 fSwizzler->fill(fillInfo, dst, rowBytes, fillValue, this->options().fZeroInitialized); 562 563 // Start to write pixels at the start of the image frame 564 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); 565 } 566 567 for (int i = 0; i < rowsInFrame; i++) { 568 if (!this->readRow()) { 569 return i + rowsBeforeFrame; 570 } 571 fSwizzler->swizzle(dst, fSrcBuffer.get()); 572 dst = SkTAddOffset<void>(dst, rowBytes); 573 } 574 575 return count; 576} 577 578bool SkGifCodec::onSkipScanlines(int count) { 579 int rowsBeforeFrame; 580 int rowsInFrame; 581 this->handleScanlineFrame(count, &rowsBeforeFrame, &rowsInFrame); 582 583 for (int i = 0; i < rowsInFrame; i++) { 584 if (!this->readRow()) { 585 return false; 586 } 587 } 588 589 return true; 590} 591 592SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { 593 if (fGif->Image.Interlace) { 594 return kOutOfOrder_SkScanlineOrder; 595 } 596 return kTopDown_SkScanlineOrder; 597} 598 599int SkGifCodec::onOutputScanline(int inputScanline) const { 600 if (fGif->Image.Interlace) { 601 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bottom()) { 602 return inputScanline; 603 } 604 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFrameRect.height()) + 605 fFrameRect.top(); 606 } 607 return inputScanline; 608} 609