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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 // If there is a transparent index, we also use this as | 372 // If there is a transparent index, we also use this as |
373 // the fill index. | 373 // the fill index. |
374 fillIndex = transIndex; | 374 fillIndex = transIndex; |
375 } else if (fillIndex >= colorCount) { | 375 } else if (fillIndex >= colorCount) { |
376 // If the fill index is invalid, we default to 0. This | 376 // If the fill index is invalid, we default to 0. This |
377 // behavior is unspecified but matches SkImageDecoder. | 377 // behavior is unspecified but matches SkImageDecoder. |
378 fillIndex = 0; | 378 fillIndex = 0; |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
382 // Check if we can skip filling the background of the image. We | |
383 // may be able to if the memory is zero initialized. | |
384 bool skipBackground = | |
385 ((kN32_SkColorType == dstColorType && colorTable[fillInd
ex] == 0) || | |
386 (kIndex_8_SkColorType == dstColorType && fillIndex == 0)
) && | |
387 kYes_ZeroInitialized == zeroInit; | |
388 | |
389 | |
390 // Fill in the color table for indices greater than color count. | 382 // Fill in the color table for indices greater than color count. |
391 // This allows for predictable, safe behavior. | 383 // This allows for predictable, safe behavior. |
392 for (uint32_t i = colorCount; i < maxColors; i++) { | 384 for (uint32_t i = colorCount; i < maxColors; i++) { |
393 colorTable[i] = colorTable[fillIndex]; | 385 colorTable[i] = colorTable[fillIndex]; |
394 } | 386 } |
395 | 387 |
396 // Check if image is only a subset of the image frame | 388 // Check if image is only a subset of the image frame |
397 SkAutoTDelete<SkSwizzler> swizzler(NULL); | 389 SkAutoTDelete<SkSwizzler> swizzler(NULL); |
398 if (innerWidth < width || innerHeight < height) { | 390 if (innerWidth < width || innerHeight < height) { |
399 | 391 |
400 // Modify the destination info | 392 // Modify the destination info |
401 const SkImageInfo subsetDstInfo = | 393 const SkImageInfo subsetDstInfo = |
402 dstInfo.makeWH(innerWidth, innerHeight); | 394 dstInfo.makeWH(innerWidth, innerHeight); |
403 | 395 |
404 // Fill the destination with the fill color | 396 // Fill the destination with the fill color |
405 // FIXME: This may not be the behavior that we want for | 397 // FIXME: This may not be the behavior that we want for |
406 // animated gifs where we draw on top of the | 398 // animated gifs where we draw on top of the |
407 // previous frame. | 399 // previous frame. |
408 if (!skipBackground) { | 400 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, |
409 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, | 401 fillIndex, colorTable, zeroInit); |
410 fillIndex, colorTable); | |
411 } | |
412 | 402 |
413 // Modify the dst pointer | 403 // Modify the dst pointer |
414 const int32_t dstBytesPerPixel = | 404 const int32_t dstBytesPerPixel = |
415 SkColorTypeBytesPerPixel(dstColorType); | 405 SkColorTypeBytesPerPixel(dstColorType); |
416 dst = SkTAddOffset<void*>(dst, | 406 dst = SkTAddOffset<void*>(dst, |
417 dstRowBytes * imageTop + | 407 dstRowBytes * imageTop + |
418 dstBytesPerPixel * imageLeft); | 408 dstBytesPerPixel * imageLeft); |
419 | 409 |
420 // Create the subset swizzler | 410 // Create the subset swizzler |
421 swizzler.reset(SkSwizzler::CreateSwizzler( | 411 swizzler.reset(SkSwizzler::CreateSwizzler( |
(...skipping 13 matching lines...) Expand all Loading... |
435 // Check the interlace flag and iterate over rows of the input | 425 // Check the interlace flag and iterate over rows of the input |
436 if (fGif->Image.Interlace) { | 426 if (fGif->Image.Interlace) { |
437 // In interlace mode, the rows of input are rearranged in | 427 // In interlace mode, the rows of input are rearranged in |
438 // the output image. We use an iterator to take care of | 428 // the output image. We use an iterator to take care of |
439 // the rearranging. | 429 // the rearranging. |
440 SkGifInterlaceIter iter(innerHeight); | 430 SkGifInterlaceIter iter(innerHeight); |
441 for (int32_t y = 0; y < innerHeight; y++) { | 431 for (int32_t y = 0; y < innerHeight; y++) { |
442 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), | 432 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), |
443 innerWidth)) { | 433 innerWidth)) { |
444 // Recover from error by filling remainder of image | 434 // Recover from error by filling remainder of image |
445 if (!skipBackground) { | 435 memset(buffer.get(), fillIndex, innerWidth); |
446 memset(buffer.get(), fillIndex, innerWidth); | 436 for (; y < innerHeight; y++) { |
447 for (; y < innerHeight; y++) { | 437 void* dstRow = SkTAddOffset<void>(dst, |
448 void* dstRow = SkTAddOffset<void>(dst, | 438 dstRowBytes * iter.nextY()); |
449 dstRowBytes * iter.nextY()); | 439 swizzler->swizzle(dstRow, buffer.get()); |
450 swizzler->swizzle(dstRow, buffer.get()); | |
451 } | |
452 } | 440 } |
453 return gif_error(SkStringPrintf( | 441 return gif_error(SkStringPrintf( |
454 "Could not decode line %d of %d.\n", | 442 "Could not decode line %d of %d.\n", |
455 y, height - 1).c_str(), kIncompleteInput); | 443 y, height - 1).c_str(), kIncompleteInput); |
456 } | 444 } |
457 void* dstRow = SkTAddOffset<void>( | 445 void* dstRow = SkTAddOffset<void>( |
458 dst, dstRowBytes * iter.nextY()); | 446 dst, dstRowBytes * iter.nextY()); |
459 swizzler->swizzle(dstRow, buffer.get()); | 447 swizzler->swizzle(dstRow, buffer.get()); |
460 } | 448 } |
461 } else { | 449 } else { |
462 // Standard mode | 450 // Standard mode |
463 void* dstRow = dst; | 451 void* dstRow = dst; |
464 for (int32_t y = 0; y < innerHeight; y++) { | 452 for (int32_t y = 0; y < innerHeight; y++) { |
465 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), | 453 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), |
466 innerWidth)) { | 454 innerWidth)) { |
467 if (!skipBackground) { | 455 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, |
468 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, | 456 innerHeight - y, fillIndex, colorTable, |
469 innerHeight - y, fillIndex, colorTable); | 457 zeroInit); |
470 } | |
471 return gif_error(SkStringPrintf( | 458 return gif_error(SkStringPrintf( |
472 "Could not decode line %d of %d.\n", | 459 "Could not decode line %d of %d.\n", |
473 y, height - 1).c_str(), kIncompleteInput); | 460 y, height - 1).c_str(), kIncompleteInput); |
474 } | 461 } |
475 swizzler->swizzle(dstRow, buffer.get()); | 462 swizzler->swizzle(dstRow, buffer.get()); |
476 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 463 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
477 } | 464 } |
478 } | 465 } |
479 | 466 |
480 // FIXME: Gif files may have multiple images stored in a single | 467 // FIXME: Gif files may have multiple images stored in a single |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 // giflib returns an error code if the record type is not known. | 537 // giflib returns an error code if the record type is not known. |
551 // We should catch this error immediately. | 538 // We should catch this error immediately. |
552 SkASSERT(false); | 539 SkASSERT(false); |
553 break; | 540 break; |
554 } | 541 } |
555 } while (TERMINATE_RECORD_TYPE != recordType); | 542 } while (TERMINATE_RECORD_TYPE != recordType); |
556 | 543 |
557 return gif_error("Could not find any images to decode in gif file.\n", | 544 return gif_error("Could not find any images to decode in gif file.\n", |
558 kInvalidInput); | 545 kInvalidInput); |
559 } | 546 } |
OLD | NEW |