Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: src/codec/SkCodec_libgif.cpp

Issue 1390213002: Add subsetting to SkScanlineDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@fill-refactor
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 // Use maximum unsigned int (surely an invalid index) to indicate that a val id 93 // Use maximum unsigned int (surely an invalid index) to indicate that a val id
94 // index was not found. 94 // index was not found.
95 return SK_MaxU32; 95 return SK_MaxU32;
96 } 96 }
97 97
98 /* 98 /*
99 * This function cleans up the gif object after the decode completes 99 * This function cleans up the gif object after the decode completes
100 * It is used in a SkAutoTCallIProc template 100 * It is used in a SkAutoTCallIProc template
101 */ 101 */
102 void SkGifCodec::CloseGif(GifFileType* gif) { 102 void SkGifCodec::CloseGif(GifFileType* gif) {
103 DGifCloseFile(gif, NULL); 103 DGifCloseFile(gif, nullptr);
104 } 104 }
105 105
106 /* 106 /*
107 * This function free extension data that has been saved to assist the image 107 * This function free extension data that has been saved to assist the image
108 * decoder 108 * decoder
109 */ 109 */
110 void SkGifCodec::FreeExtension(SavedImage* image) { 110 void SkGifCodec::FreeExtension(SavedImage* image) {
111 if (NULL != image->ExtensionBlocks) { 111 if (nullptr != image->ExtensionBlocks) {
112 GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks); 112 GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks);
113 } 113 }
114 } 114 }
115 115
116 /* 116 /*
117 * Read enough of the stream to initialize the SkGifCodec. 117 * Read enough of the stream to initialize the SkGifCodec.
118 * Returns a bool representing success or failure. 118 * Returns a bool representing success or failure.
119 * 119 *
120 * @param codecOut 120 * @param codecOut
121 * If it returned true, and codecOut was not nullptr, 121 * If it returned true, and codecOut was not nullptr,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 , fSrcBuffer(new uint8_t[this->getInfo().width()]) 214 , fSrcBuffer(new uint8_t[this->getInfo().width()])
215 // If it is valid, fTransIndex will be used to set fFillIndex. We don't kno w if 215 // If it is valid, fTransIndex will be used to set fFillIndex. We don't kno w if
216 // fTransIndex is valid until we process the color table, since fTransIndex may 216 // fTransIndex is valid until we process the color table, since fTransIndex may
217 // be greater than the size of the color table. 217 // be greater than the size of the color table.
218 , fTransIndex(transIndex) 218 , fTransIndex(transIndex)
219 // Default fFillIndex is 0. We will overwrite this if fTransIndex is valid, or if 219 // Default fFillIndex is 0. We will overwrite this if fTransIndex is valid, or if
220 // there is a valid background color. 220 // there is a valid background color.
221 , fFillIndex(0) 221 , fFillIndex(0)
222 , fFrameRect(frameRect) 222 , fFrameRect(frameRect)
223 , fFrameIsSubset(frameIsSubset) 223 , fFrameIsSubset(frameIsSubset)
224 , fColorTable(NULL) 224 , fColorTable(nullptr)
225 , fSwizzler(NULL) 225 , fSwizzler(nullptr)
226 {} 226 {}
227 227
228 bool SkGifCodec::onRewind() { 228 bool SkGifCodec::onRewind() {
229 GifFileType* gifOut = nullptr; 229 GifFileType* gifOut = nullptr;
230 if (!ReadHeader(this->stream(), nullptr, &gifOut)) { 230 if (!ReadHeader(this->stream(), nullptr, &gifOut)) {
231 return false; 231 return false;
232 } 232 }
233 233
234 SkASSERT(nullptr != gifOut); 234 SkASSERT(nullptr != gifOut);
235 fGif.reset(gifOut); 235 fGif.reset(gifOut);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 frameRect->setXYWH(frameLeft, frameTop, frameWidth, frameHeight); 348 frameRect->setXYWH(frameLeft, frameTop, frameWidth, frameHeight);
349 size->set(width, height); 349 size->set(width, height);
350 return true; 350 return true;
351 } 351 }
352 352
353 void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inp utColorPtr, 353 void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inp utColorPtr,
354 int* inputColorCount) { 354 int* inputColorCount) {
355 // Set up our own color table 355 // Set up our own color table
356 const uint32_t maxColors = 256; 356 const uint32_t maxColors = 256;
357 SkPMColor colorPtr[256]; 357 SkPMColor colorPtr[256];
358 if (NULL != inputColorCount) { 358 if (nullptr != inputColorCount) {
359 // We set the number of colors to maxColors in order to ensure 359 // We set the number of colors to maxColors in order to ensure
360 // safe memory accesses. Otherwise, an invalid pixel could 360 // safe memory accesses. Otherwise, an invalid pixel could
361 // access memory outside of our color table array. 361 // access memory outside of our color table array.
362 *inputColorCount = maxColors; 362 *inputColorCount = maxColors;
363 } 363 }
364 364
365 // Get local color table 365 // Get local color table
366 ColorMapObject* colorMap = fGif->Image.ColorMap; 366 ColorMapObject* colorMap = fGif->Image.ColorMap;
367 // If there is no local color table, use the global color table 367 // If there is no local color table, use the global color table
368 if (NULL == colorMap) { 368 if (nullptr == colorMap) {
369 colorMap = fGif->SColorMap; 369 colorMap = fGif->SColorMap;
370 } 370 }
371 371
372 uint32_t colorCount = 0; 372 uint32_t colorCount = 0;
373 if (NULL != colorMap) { 373 if (nullptr != colorMap) {
374 colorCount = colorMap->ColorCount; 374 colorCount = colorMap->ColorCount;
375 // giflib guarantees these properties 375 // giflib guarantees these properties
376 SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel))); 376 SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel)));
377 SkASSERT(colorCount <= 256); 377 SkASSERT(colorCount <= 256);
378 for (uint32_t i = 0; i < colorCount; i++) { 378 for (uint32_t i = 0; i < colorCount; i++) {
379 colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red, 379 colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red,
380 colorMap->Colors[i].Green, colorMap->Colors[i].Blue); 380 colorMap->Colors[i].Green, colorMap->Colors[i].Blue);
381 } 381 }
382 } 382 }
383 383
(...skipping 19 matching lines...) Expand all
403 colorPtr[i] = colorPtr[fFillIndex]; 403 colorPtr[i] = colorPtr[fFillIndex];
404 } 404 }
405 405
406 fColorTable.reset(new SkColorTable(colorPtr, maxColors)); 406 fColorTable.reset(new SkColorTable(colorPtr, maxColors));
407 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount) ; 407 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount) ;
408 } 408 }
409 409
410 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo r* inputColorPtr, 410 SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColo r* inputColorPtr,
411 int* inputColorCount, const Options& opts) { 411 int* inputColorCount, const Options& opts) {
412 // Check for valid input parameters 412 // Check for valid input parameters
413 if (opts.fSubset) {
414 // Subsets are not supported.
415 return kUnimplemented;
416 }
417 if (!conversion_possible(dstInfo, this->getInfo())) { 413 if (!conversion_possible(dstInfo, this->getInfo())) {
418 return gif_error("Cannot convert input type to output type.\n", 414 return gif_error("Cannot convert input type to output type.\n",
419 kInvalidConversion); 415 kInvalidConversion);
420 } 416 }
421 417
422 // Initialize color table and copy to the client if necessary 418 // Initialize color table and copy to the client if necessary
423 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); 419 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount);
424 return kSuccess; 420 return kSuccess;
425 } 421 }
426 422
427 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, 423 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& opts) {
428 ZeroInitialized zeroInit) {
429 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 424 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
430 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, 425 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dst Info, opts));
431 colorPtr, dstInfo, zeroInit));
432 if (nullptr != fSwizzler.get()) { 426 if (nullptr != fSwizzler.get()) {
433 return kSuccess; 427 return kSuccess;
434 } 428 }
435 return kUnimplemented; 429 return kUnimplemented;
436 } 430 }
437 431
438 bool SkGifCodec::readRow() { 432 bool SkGifCodec::readRow() {
439 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); 433 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width());
440 } 434 }
441 435
(...skipping 11 matching lines...) Expand all
453 return result; 447 return result;
454 } 448 }
455 449
456 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 450 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
457 return gif_error("Scaling not supported.\n", kInvalidScale); 451 return gif_error("Scaling not supported.\n", kInvalidScale);
458 } 452 }
459 453
460 // Initialize the swizzler 454 // Initialize the swizzler
461 if (fFrameIsSubset) { 455 if (fFrameIsSubset) {
462 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 456 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
463 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 457 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) {
464 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 458 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
465 } 459 }
466 460
467 // Fill the background 461 // Fill the background
468 SkSampler::Fill(dst, dstInfo, dstRowBytes, 462 SkSampler::Fill(dst, dstInfo, dstRowBytes,
469 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), 463 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()),
470 opts.fZeroInitialized); 464 opts.fZeroInitialized);
471 465
472 // Modify the dst pointer 466 // Modify the dst pointer
473 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); 467 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype());
474 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + 468 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() +
475 dstBytesPerPixel * fFrameRect.left()); 469 dstBytesPerPixel * fFrameRect.left());
476 } else { 470 } else {
477 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 471 if (kSuccess != this->initializeSwizzler(dstInfo, opts)) {
478 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 472 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
479 } 473 }
480 } 474 }
481 475
482 // Iterate over rows of the input 476 // Iterate over rows of the input
483 uint32_t width = fFrameRect.width(); 477 uint32_t width = fFrameRect.width();
484 uint32_t height = fFrameRect.height(); 478 uint32_t height = fFrameRect.height();
485 for (uint32_t y = 0; y < height; y++) { 479 for (uint32_t y = 0; y < height; y++) {
486 if (!this->readRow()) { 480 if (!this->readRow()) {
487 *rowsDecoded = y; 481 *rowsDecoded = y;
(...skipping 14 matching lines...) Expand all
502 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { 496 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) {
503 497
504 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options()); 498 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options());
505 if (kSuccess != result) { 499 if (kSuccess != result) {
506 return result; 500 return result;
507 } 501 }
508 502
509 // Initialize the swizzler 503 // Initialize the swizzler
510 if (fFrameIsSubset) { 504 if (fFrameIsSubset) {
511 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 505 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
512 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 506 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) {
513 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 507 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
514 } 508 }
515 } else { 509 } else {
516 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 510 if (kSuccess != this->initializeSwizzler(dstInfo, opts)) {
517 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 511 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
518 } 512 }
519 } 513 }
520 514
521 return kSuccess; 515 return kSuccess;
522 } 516 }
523 517
524 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { 518 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
525 int rowsBeforeFrame = 0; 519 int rowsBeforeFrame = 0;
526 int rowsAfterFrame = 0; 520 int rowsAfterFrame = 0;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 560
567 int SkGifCodec::onOutputScanline(int inputScanline) const { 561 int SkGifCodec::onOutputScanline(int inputScanline) const {
568 if (fGif->Image.Interlace) { 562 if (fGif->Image.Interlace) {
569 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) { 563 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) {
570 return inputScanline; 564 return inputScanline;
571 } 565 }
572 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height()); 566 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height());
573 } 567 }
574 return inputScanline; 568 return inputScanline;
575 } 569 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698