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