OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCodec_libgif.h" | 8 #include "SkCodec_libgif.h" |
9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
118 } | 118 } |
119 // Fourth pass | 119 // Fourth pass |
120 return 1 + 2 * (encodedRow - ceil_div(height, 2)); | 120 return 1 + 2 * (encodedRow - ceil_div(height, 2)); |
121 } | 121 } |
122 | 122 |
123 /* | 123 /* |
124 * This function cleans up the gif object after the decode completes | 124 * This function cleans up the gif object after the decode completes |
125 * It is used in a SkAutoTCallIProc template | 125 * It is used in a SkAutoTCallIProc template |
126 */ | 126 */ |
127 void SkGifCodec::CloseGif(GifFileType* gif) { | 127 void SkGifCodec::CloseGif(GifFileType* gif) { |
128 DGifCloseFile(gif, NULL); | 128 DGifCloseFile(gif, nullptr); |
scroggo
2015/10/08 20:16:07
This change deserves to be a separate CL. It makes
msarett
2015/10/09 20:03:44
Removing.
| |
129 } | 129 } |
130 | 130 |
131 /* | 131 /* |
132 * This function free extension data that has been saved to assist the image | 132 * This function free extension data that has been saved to assist the image |
133 * decoder | 133 * decoder |
134 */ | 134 */ |
135 void SkGifCodec::FreeExtension(SavedImage* image) { | 135 void SkGifCodec::FreeExtension(SavedImage* image) { |
136 if (NULL != image->ExtensionBlocks) { | 136 if (nullptr != image->ExtensionBlocks) { |
137 GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks); | 137 GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks); |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 /* | 141 /* |
142 * Read enough of the stream to initialize the SkGifCodec. | 142 * Read enough of the stream to initialize the SkGifCodec. |
143 * Returns a bool representing success or failure. | 143 * Returns a bool representing success or failure. |
144 * | 144 * |
145 * @param codecOut | 145 * @param codecOut |
146 * If it returned true, and codecOut was not nullptr, | 146 * If it returned true, and codecOut was not nullptr, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 , fSrcBuffer(new uint8_t[this->getInfo().width()]) | 239 , fSrcBuffer(new uint8_t[this->getInfo().width()]) |
240 // If it is valid, fTransIndex will be used to set fFillIndex. We don't kno w if | 240 // If it is valid, fTransIndex will be used to set fFillIndex. We don't kno w if |
241 // fTransIndex is valid until we process the color table, since fTransIndex may | 241 // fTransIndex is valid until we process the color table, since fTransIndex may |
242 // be greater than the size of the color table. | 242 // be greater than the size of the color table. |
243 , fTransIndex(transIndex) | 243 , fTransIndex(transIndex) |
244 // Default fFillIndex is 0. We will overwrite this if fTransIndex is valid, or if | 244 // Default fFillIndex is 0. We will overwrite this if fTransIndex is valid, or if |
245 // there is a valid background color. | 245 // there is a valid background color. |
246 , fFillIndex(0) | 246 , fFillIndex(0) |
247 , fFrameRect(frameRect) | 247 , fFrameRect(frameRect) |
248 , fFrameIsSubset(frameIsSubset) | 248 , fFrameIsSubset(frameIsSubset) |
249 , fColorTable(NULL) | 249 , fColorTable(nullptr) |
250 , fSwizzler(NULL) | 250 , fSwizzler(nullptr) |
251 {} | 251 {} |
252 | 252 |
253 bool SkGifCodec::onRewind() { | 253 bool SkGifCodec::onRewind() { |
254 GifFileType* gifOut = nullptr; | 254 GifFileType* gifOut = nullptr; |
255 if (!ReadHeader(this->stream(), nullptr, &gifOut)) { | 255 if (!ReadHeader(this->stream(), nullptr, &gifOut)) { |
256 return false; | 256 return false; |
257 } | 257 } |
258 | 258 |
259 SkASSERT(nullptr != gifOut); | 259 SkASSERT(nullptr != gifOut); |
260 fGif.reset(gifOut); | 260 fGif.reset(gifOut); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 frameRect->setXYWH(frameLeft, frameTop, frameWidth, frameHeight); | 373 frameRect->setXYWH(frameLeft, frameTop, frameWidth, frameHeight); |
374 size->set(width, height); | 374 size->set(width, height); |
375 return true; | 375 return true; |
376 } | 376 } |
377 | 377 |
378 void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inp utColorPtr, | 378 void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inp utColorPtr, |
379 int* inputColorCount) { | 379 int* inputColorCount) { |
380 // Set up our own color table | 380 // Set up our own color table |
381 const uint32_t maxColors = 256; | 381 const uint32_t maxColors = 256; |
382 SkPMColor colorPtr[256]; | 382 SkPMColor colorPtr[256]; |
383 if (NULL != inputColorCount) { | 383 if (nullptr != inputColorCount) { |
384 // We set the number of colors to maxColors in order to ensure | 384 // We set the number of colors to maxColors in order to ensure |
385 // safe memory accesses. Otherwise, an invalid pixel could | 385 // safe memory accesses. Otherwise, an invalid pixel could |
386 // access memory outside of our color table array. | 386 // access memory outside of our color table array. |
387 *inputColorCount = maxColors; | 387 *inputColorCount = maxColors; |
388 } | 388 } |
389 | 389 |
390 // Get local color table | 390 // Get local color table |
391 ColorMapObject* colorMap = fGif->Image.ColorMap; | 391 ColorMapObject* colorMap = fGif->Image.ColorMap; |
392 // If there is no local color table, use the global color table | 392 // If there is no local color table, use the global color table |
393 if (NULL == colorMap) { | 393 if (nullptr == colorMap) { |
394 colorMap = fGif->SColorMap; | 394 colorMap = fGif->SColorMap; |
395 } | 395 } |
396 | 396 |
397 uint32_t colorCount = 0; | 397 uint32_t colorCount = 0; |
398 if (NULL != colorMap) { | 398 if (nullptr != colorMap) { |
399 colorCount = colorMap->ColorCount; | 399 colorCount = colorMap->ColorCount; |
400 // giflib guarantees these properties | 400 // giflib guarantees these properties |
401 SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel))); | 401 SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel))); |
402 SkASSERT(colorCount <= 256); | 402 SkASSERT(colorCount <= 256); |
403 for (uint32_t i = 0; i < colorCount; i++) { | 403 for (uint32_t i = 0; i < colorCount; i++) { |
404 colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red, | 404 colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red, |
405 colorMap->Colors[i].Green, colorMap->Colors[i].Blue); | 405 colorMap->Colors[i].Green, colorMap->Colors[i].Blue); |
406 } | 406 } |
407 } | 407 } |
408 | 408 |
(...skipping 19 matching lines...) Expand all Loading... | |
428 colorPtr[i] = colorPtr[fFillIndex]; | 428 colorPtr[i] = colorPtr[fFillIndex]; |
429 } | 429 } |
430 | 430 |
431 fColorTable.reset(new SkColorTable(colorPtr, maxColors)); | 431 fColorTable.reset(new SkColorTable(colorPtr, maxColors)); |
432 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount) ; | 432 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount) ; |
433 } | 433 } |
434 | 434 |
435 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo r* inputColorPtr, | 435 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo r* inputColorPtr, |
436 int* inputColorCount, const Options& opts) { | 436 int* inputColorCount, const Options& opts) { |
437 // Check for valid input parameters | 437 // Check for valid input parameters |
438 if (opts.fSubset) { | |
439 // Subsets are not supported. | |
440 return kUnimplemented; | |
441 } | |
442 if (!conversion_possible(dstInfo, this->getInfo())) { | 438 if (!conversion_possible(dstInfo, this->getInfo())) { |
443 return gif_error("Cannot convert input type to output type.\n", | 439 return gif_error("Cannot convert input type to output type.\n", |
444 kInvalidConversion); | 440 kInvalidConversion); |
445 } | 441 } |
446 | 442 |
447 // Initialize color table and copy to the client if necessary | 443 // Initialize color table and copy to the client if necessary |
448 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); | 444 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); |
449 return kSuccess; | 445 return kSuccess; |
450 } | 446 } |
451 | 447 |
452 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, | 448 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& opts) { |
453 ZeroInitialized zeroInit) { | |
454 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 449 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
455 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, | 450 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dst Info, opts)); |
456 colorPtr, dstInfo, zeroInit)); | |
457 if (nullptr != fSwizzler.get()) { | 451 if (nullptr != fSwizzler.get()) { |
458 return kSuccess; | 452 return kSuccess; |
459 } | 453 } |
460 return kUnimplemented; | 454 return kUnimplemented; |
461 } | 455 } |
462 | 456 |
463 bool SkGifCodec::readRow() { | 457 bool SkGifCodec::readRow() { |
464 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); | 458 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); |
465 } | 459 } |
466 | 460 |
(...skipping 11 matching lines...) Expand all Loading... | |
478 return result; | 472 return result; |
479 } | 473 } |
480 | 474 |
481 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 475 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
482 return gif_error("Scaling not supported.\n", kInvalidScale); | 476 return gif_error("Scaling not supported.\n", kInvalidScale); |
483 } | 477 } |
484 | 478 |
485 // Initialize the swizzler | 479 // Initialize the swizzler |
486 if (fFrameIsSubset) { | 480 if (fFrameIsSubset) { |
487 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); | 481 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); |
488 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { | 482 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) { |
489 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; | 483 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; |
490 } | 484 } |
491 | 485 |
492 // Fill the background | 486 // Fill the background |
493 SkSampler::Fill(dstInfo, dst, dstRowBytes, | 487 SkSampler::Fill(dstInfo, dst, dstRowBytes, |
494 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), | 488 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), |
495 opts.fZeroInitialized); | 489 opts.fZeroInitialized); |
496 | 490 |
497 // Modify the dst pointer | 491 // Modify the dst pointer |
498 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); | 492 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); |
499 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + | 493 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + |
500 dstBytesPerPixel * fFrameRect.left()); | 494 dstBytesPerPixel * fFrameRect.left()); |
501 } else { | 495 } else { |
502 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { | 496 if (kSuccess != this->initializeSwizzler(dstInfo, opts)) { |
503 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; | 497 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; |
504 } | 498 } |
505 } | 499 } |
506 | 500 |
507 // Iterate over rows of the input | 501 // Iterate over rows of the input |
508 uint32_t width = fFrameRect.width(); | 502 uint32_t width = fFrameRect.width(); |
509 uint32_t height = fFrameRect.height(); | 503 uint32_t height = fFrameRect.height(); |
510 for (uint32_t y = 0; y < height; y++) { | 504 for (uint32_t y = 0; y < height; y++) { |
511 if (!this->readRow()) { | 505 if (!this->readRow()) { |
512 *rowsDecoded = y; | 506 *rowsDecoded = y; |
(...skipping 16 matching lines...) Expand all Loading... | |
529 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { | 523 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { |
530 | 524 |
531 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options()); | 525 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options()); |
532 if (kSuccess != result) { | 526 if (kSuccess != result) { |
533 return result; | 527 return result; |
534 } | 528 } |
535 | 529 |
536 // Initialize the swizzler | 530 // Initialize the swizzler |
537 if (fFrameIsSubset) { | 531 if (fFrameIsSubset) { |
538 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); | 532 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); |
539 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { | 533 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) { |
540 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; | 534 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; |
541 } | 535 } |
542 } else { | 536 } else { |
543 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { | 537 if (kSuccess != this->initializeSwizzler(dstInfo, opts)) { |
544 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; | 538 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; |
545 } | 539 } |
546 } | 540 } |
547 | 541 |
548 return kSuccess; | 542 return kSuccess; |
549 } | 543 } |
550 | 544 |
551 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { | 545 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |
552 int rowsBeforeFrame = 0; | 546 int rowsBeforeFrame = 0; |
553 int rowsAfterFrame = 0; | 547 int rowsAfterFrame = 0; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
594 | 588 |
595 int SkGifCodec::onOutputScanline(int inputScanline) const { | 589 int SkGifCodec::onOutputScanline(int inputScanline) const { |
596 if (fGif->Image.Interlace) { | 590 if (fGif->Image.Interlace) { |
597 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) { | 591 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) { |
598 return inputScanline; | 592 return inputScanline; |
599 } | 593 } |
600 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height()); | 594 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height()); |
601 } | 595 } |
602 return inputScanline; | 596 return inputScanline; |
603 } | 597 } |
OLD | NEW |