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

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

Issue 1321433002: Add subsetting to SkScaledCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@gif-scan
Patch Set: Rebase - it compiles but I'm sure everything is broken 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
« no previous file with comments | « src/codec/SkCodec_libgif.h ('k') | src/codec/SkCodec_libpng.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 , fGif(gif) 213 , fGif(gif)
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(false)
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 return gif_error("Cannot convert input type to output type.\n", 418 return gif_error("Cannot convert input type to output type.\n",
419 kInvalidConversion); 419 kInvalidConversion);
420 } 420 }
421 421
422 // Initialize color table and copy to the client if necessary 422 // Initialize color table and copy to the client if necessary
423 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); 423 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount);
424 return kSuccess; 424 return kSuccess;
425 } 425 }
426 426
427 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, 427 SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo,
428 ZeroInitialized zeroInit) { 428 ZeroInitialized zeroInit, int subsetLeft, int subsetWidth) {
429 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 429 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
430 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, 430 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dst Info, zeroInit,
431 colorPtr, dstInfo, zeroInit)); 431 subsetLeft, subsetWidth));
432 if (nullptr != fSwizzler.get()) { 432 if (nullptr != fSwizzler.get()) {
433 return kSuccess; 433 return kSuccess;
434 } 434 }
435 return kUnimplemented; 435 return kUnimplemented;
436 } 436 }
437 437
438 bool SkGifCodec::readRow() { 438 bool SkGifCodec::readRow() {
439 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width()); 439 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width());
440 } 440 }
441 441
(...skipping 11 matching lines...) Expand all
453 return result; 453 return result;
454 } 454 }
455 455
456 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 456 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
457 return gif_error("Scaling not supported.\n", kInvalidScale); 457 return gif_error("Scaling not supported.\n", kInvalidScale);
458 } 458 }
459 459
460 // Initialize the swizzler 460 // Initialize the swizzler
461 if (fFrameIsSubset) { 461 if (fFrameIsSubset) {
462 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 462 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
463 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 463 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized, 0,
464 fFrameRect.width())) {
464 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 465 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
465 } 466 }
466 467
467 // Fill the background 468 // Fill the background
468 fSwizzler->fill(dst, dstInfo.colorType(), dstInfo.height(), dstRowBytes, 469 fSwizzler->fill(dst, dstInfo.colorType(), dstInfo.height(), dstRowBytes,
469 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()), 470 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()),
470 opts.fZeroInitialized); 471 opts.fZeroInitialized);
471 472
472 // Modify the dst pointer 473 // Modify the dst pointer
473 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); 474 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype());
474 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + 475 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() +
475 dstBytesPerPixel * fFrameRect.left()); 476 dstBytesPerPixel * fFrameRect.left());
476 } else { 477 } else {
477 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 478 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized, 0,
479 dstInfo.width())) {
478 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 480 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
479 } 481 }
480 } 482 }
481 483
482 // Iterate over rows of the input 484 // Iterate over rows of the input
483 uint32_t width = fFrameRect.width(); 485 uint32_t width = fFrameRect.width();
484 uint32_t height = fFrameRect.height(); 486 uint32_t height = fFrameRect.height();
485 for (uint32_t y = 0; y < height; y++) { 487 for (uint32_t y = 0; y < height; y++) {
486 if (!this->readRow()) { 488 if (!this->readRow()) {
487 *rowsDecoded = y; 489 *rowsDecoded = y;
488 return gif_error("Could not decode line.\n", kIncompleteInput); 490 return gif_error("Could not decode line.\n", kIncompleteInput);
489 } 491 }
490 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanlin e(y)); 492 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanlin e(y));
491 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 493 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
492 } 494 }
493 return kSuccess; 495 return kSuccess;
494 } 496 }
495 497
496 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType ) const { 498 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType ) const {
497 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 499 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
498 return get_color_table_fill_value(colorType, colorPtr, fFillIndex); 500 return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
499 } 501 }
500 502
501 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 503 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
502 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { 504 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count,
505 int subsetLeft, int subsetWidth) {
503 506
504 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options()); 507 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options());
505 if (kSuccess != result) { 508 if (kSuccess != result) {
506 return result; 509 return result;
507 } 510 }
508 511
509 // Initialize the swizzler 512 // Initialize the swizzler
510 if (fFrameIsSubset) { 513 if (fFrameIsSubset) {
511 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 514 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
512 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 515 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized, subsetLeft,
516 subsetWidth)) {
513 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 517 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
514 } 518 }
515 } else { 519 } else {
516 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 520 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized, subsetLeft,
521 subsetWidth)) {
517 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 522 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
518 } 523 }
519 } 524 }
520 525
521 return kSuccess; 526 return kSuccess;
522 } 527 }
523 528
524 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { 529 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
525 int rowsBeforeFrame = 0; 530 int rowsBeforeFrame = 0;
526 int rowsAfterFrame = 0; 531 int rowsAfterFrame = 0;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 571
567 int SkGifCodec::onOutputScanline(int inputScanline) const { 572 int SkGifCodec::onOutputScanline(int inputScanline) const {
568 if (fGif->Image.Interlace) { 573 if (fGif->Image.Interlace) {
569 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) { 574 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) {
570 return inputScanline; 575 return inputScanline;
571 } 576 }
572 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height()); 577 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height());
573 } 578 }
574 return inputScanline; 579 return inputScanline;
575 } 580 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libgif.h ('k') | src/codec/SkCodec_libpng.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698