 Chromium Code Reviews
 Chromium Code Reviews Issue 1055743003:
  Swizzler changes Index8 and 565  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master
    
  
    Issue 1055743003:
  Swizzler changes Index8 and 565  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master| 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_libbmp.h" | 8 #include "SkCodec_libbmp.h" | 
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" | 
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" | 
| 11 #include "SkStream.h" | 11 #include "SkStream.h" | 
| 12 #include "SkUtils.h" | |
| 12 | 13 | 
| 13 /* | 14 /* | 
| 14 * | 15 * | 
| 15 * Checks if the conversion between the input image and the requested output | 16 * Checks if the conversion between the input image and the requested output | 
| 16 * image has been implemented | 17 * image has been implemented | 
| 17 * | 18 * | 
| 18 */ | 19 */ | 
| 19 static bool conversion_possible(const SkImageInfo& dst, | 20 static bool conversion_possible(const SkImageInfo& dst, | 
| 20 const SkImageInfo& src) { | 21 const SkImageInfo& src) { | 
| 21 // Ensure that the profile type is unchanged | 22 // Ensure that the profile type is unchanged | 
| 22 if (dst.profileType() != src.profileType()) { | 23 if (dst.profileType() != src.profileType()) { | 
| 23 return false; | 24 return false; | 
| 24 } | 25 } | 
| 25 | 26 | 
| 26 // Check for supported color and alpha types | 27 // Check for supported alpha types | 
| 28 if (src.alphaType() != dst.alphaType()) { | |
| 29 if (kOpaque_SkAlphaType == src.alphaType()) { | |
| 30 // If the source is opaque, we must decode to opaque | |
| 31 return false; | |
| 32 } | |
| 33 | |
| 34 // The source is not opaque | |
| 35 switch (dst.alphaType()) { | |
| 36 case kPremul_SkAlphaType: | |
| 37 case kUnpremul_SkAlphaType: | |
| 38 // The source is not opaque, so either of these is okay | |
| 39 break; | |
| 40 default: | |
| 41 // We cannot decode a non-opaque image to opaque (or unknown) | |
| 42 return false; | |
| 43 } | |
| 44 } | |
| 45 | |
| 46 // Check for supported color types | |
| 27 switch (dst.colorType()) { | 47 switch (dst.colorType()) { | 
| 48 // Allow output to kN32 from any type of input | |
| 28 case kN32_SkColorType: | 49 case kN32_SkColorType: | 
| 29 return src.alphaType() == dst.alphaType() || | 50 return true; | 
| 30 (kPremul_SkAlphaType == dst.alphaType() && | 51 // Allow output to kIndex_8 from compatible inputs | 
| 31 kUnpremul_SkAlphaType == src.alphaType()); | 52 case kIndex_8_SkColorType: | 
| 53 return kIndex_8_SkColorType == src.colorType(); | |
| 32 default: | 54 default: | 
| 33 return false; | 55 return false; | 
| 34 } | 56 } | 
| 35 } | 57 } | 
| 36 | 58 | 
| 37 /* | 59 /* | 
| 38 * | 60 * | 
| 39 * Defines the version and type of the second bitmap header | 61 * Defines the version and type of the second bitmap header | 
| 40 * | 62 * | 
| 41 */ | 63 */ | 
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 // Header types are matched based on size. If the header is | 435 // Header types are matched based on size. If the header is | 
| 414 // V3+, we are guaranteed to be able to read at least this size. | 436 // V3+, we are guaranteed to be able to read at least this size. | 
| 415 SkASSERT(infoBytesRemaining > 52); | 437 SkASSERT(infoBytesRemaining > 52); | 
| 416 inputMasks.alpha = get_int(iBuffer.get(), 48); | 438 inputMasks.alpha = get_int(iBuffer.get(), 48); | 
| 417 if (inputMasks.alpha != 0) { | 439 if (inputMasks.alpha != 0) { | 
| 418 alphaType = kUnpremul_SkAlphaType; | 440 alphaType = kUnpremul_SkAlphaType; | 
| 419 } | 441 } | 
| 420 } | 442 } | 
| 421 iBuffer.free(); | 443 iBuffer.free(); | 
| 422 | 444 | 
| 423 // Additionally, 32 bit bmp-in-icos use the alpha channel | 445 // Additionally, 32 bit bmp-in-icos use the alpha channel. | 
| 424 if (isIco && 32 == bitsPerPixel) { | 446 // And, RLE inputs may skip pixels, leaving them as transparent. This | 
| 447 // is uncommon, but we cannot be certain that an RLE bmp will be opaque. | |
| 448 if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat) ) { | |
| 425 alphaType = kUnpremul_SkAlphaType; | 449 alphaType = kUnpremul_SkAlphaType; | 
| 426 } | 450 } | 
| 427 | 451 | 
| 428 // Check for valid bits per pixel input | 452 // Check for valid bits per pixel. | 
| 453 // At the same time, use this information to choose a suggested color type | |
| 454 // and to set default masks. | |
| 455 SkColorType colorType = kN32_SkColorType; | |
| 429 switch (bitsPerPixel) { | 456 switch (bitsPerPixel) { | 
| 430 // In addition to more standard pixel compression formats, bmp supports | 457 // In addition to more standard pixel compression formats, bmp supports | 
| 431 // the use of bit masks to determine pixel components. The standard | 458 // the use of bit masks to determine pixel components. The standard | 
| 432 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), | 459 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), | 
| 433 // which does not map well to any Skia color formats. For this reason, | 460 // which does not map well to any Skia color formats. For this reason, | 
| 434 // we will always enable mask mode with 16 bits per pixel. | 461 // we will always enable mask mode with 16 bits per pixel. | 
| 435 case 16: | 462 case 16: | 
| 436 if (kBitMask_BitmapInputFormat != inputFormat) { | 463 if (kBitMask_BitmapInputFormat != inputFormat) { | 
| 437 inputMasks.red = 0x7C00; | 464 inputMasks.red = 0x7C00; | 
| 438 inputMasks.green = 0x03E0; | 465 inputMasks.green = 0x03E0; | 
| 439 inputMasks.blue = 0x001F; | 466 inputMasks.blue = 0x001F; | 
| 440 inputFormat = kBitMask_BitmapInputFormat; | 467 inputFormat = kBitMask_BitmapInputFormat; | 
| 441 } | 468 } | 
| 442 break; | 469 break; | 
| 470 // We want to decode to kIndex_8 for input formats that are already | |
| 471 // designed in index format. | |
| 443 case 1: | 472 case 1: | 
| 444 case 2: | 473 case 2: | 
| 445 case 4: | 474 case 4: | 
| 446 case 8: | 475 case 8: | 
| 476 // However, we cannot in RLE format since we may need to leave some | |
| 477 // pixels as transparent. Similarly, we also cannot for ICO images | |
| 478 // since we may need to apply a transparent mask. | |
| 479 if (kRLE_BitmapInputFormat != inputFormat && !isIco) { | |
| 480 colorType = kIndex_8_SkColorType; | |
| 481 } | |
| 447 case 24: | 482 case 24: | 
| 448 case 32: | 483 case 32: | 
| 449 break; | 484 break; | 
| 450 default: | 485 default: | 
| 451 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); | 486 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); | 
| 452 return false; | 487 return false; | 
| 453 } | 488 } | 
| 454 | 489 | 
| 455 // Check that input bit masks are valid and create the masks object | 490 // Check that input bit masks are valid and create the masks object | 
| 456 SkAutoTDelete<SkMasks> | 491 SkAutoTDelete<SkMasks> | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 469 | 504 | 
| 470 // Calculate the number of bytes read so far | 505 // Calculate the number of bytes read so far | 
| 471 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; | 506 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; | 
| 472 if (!isIco && offset < bytesRead) { | 507 if (!isIco && offset < bytesRead) { | 
| 473 SkCodecPrintf("Error: pixel data offset less than header size.\n"); | 508 SkCodecPrintf("Error: pixel data offset less than header size.\n"); | 
| 474 return false; | 509 return false; | 
| 475 } | 510 } | 
| 476 | 511 | 
| 477 if (codecOut) { | 512 if (codecOut) { | 
| 478 // Return the codec | 513 // Return the codec | 
| 479 // We will use ImageInfo to store width, height, and alpha type. We | 514 // We will use ImageInfo to store width, height, suggested color type, a nd | 
| 480 // will set color type to kN32_SkColorType because that should be the | 515 // suggested alpha type. | 
| 481 // default output. | |
| 482 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, | 516 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, | 
| 483 kN32_SkColorType, alphaType); | 517 colorType, alphaType); | 
| 484 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, | 518 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, | 
| 485 inputFormat, masks.detach(), | 519 inputFormat, masks.detach(), | 
| 486 numColors, bytesPerColor, | 520 numColors, bytesPerColor, | 
| 487 offset - bytesRead, rowOrder, | 521 offset - bytesRead, rowOrder, | 
| 488 RLEBytes, isIco)); | 522 RLEBytes, isIco)); | 
| 489 } | 523 } | 
| 490 return true; | 524 return true; | 
| 491 } | 525 } | 
| 492 | 526 | 
| 493 /* | 527 /* | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 | 568 | 
| 535 {} | 569 {} | 
| 536 | 570 | 
| 537 /* | 571 /* | 
| 538 * | 572 * | 
| 539 * Initiates the bitmap decode | 573 * Initiates the bitmap decode | 
| 540 * | 574 * | 
| 541 */ | 575 */ | 
| 542 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, | 576 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, | 
| 543 void* dst, size_t dstRowBytes, | 577 void* dst, size_t dstRowBytes, | 
| 544 const Options&, | 578 const Options& opts, | 
| 545 SkPMColor*, int*) { | 579 SkPMColor* inputColorPtr, | 
| 580 int* inputColorCount) { | |
| 546 // Check for proper input and output formats | 581 // Check for proper input and output formats | 
| 547 SkCodec::RewindState rewindState = this->rewindIfNeeded(); | 582 SkCodec::RewindState rewindState = this->rewindIfNeeded(); | 
| 548 if (rewindState == kCouldNotRewind_RewindState) { | 583 if (rewindState == kCouldNotRewind_RewindState) { | 
| 549 return kCouldNotRewind; | 584 return kCouldNotRewind; | 
| 550 } else if (rewindState == kRewound_RewindState) { | 585 } else if (rewindState == kRewound_RewindState) { | 
| 551 if (!ReadHeader(this->stream(), fIsIco, NULL)) { | 586 if (!ReadHeader(this->stream(), fIsIco, NULL)) { | 
| 552 return kCouldNotRewind; | 587 return kCouldNotRewind; | 
| 553 } | 588 } | 
| 554 } | 589 } | 
| 555 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 590 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 
| 556 SkCodecPrintf("Error: scaling not supported.\n"); | 591 SkCodecPrintf("Error: scaling not supported.\n"); | 
| 557 return kInvalidScale; | 592 return kInvalidScale; | 
| 558 } | 593 } | 
| 559 if (!conversion_possible(dstInfo, this->getInfo())) { | 594 if (!conversion_possible(dstInfo, this->getInfo())) { | 
| 560 SkCodecPrintf("Error: cannot convert input type to output type.\n"); | 595 SkCodecPrintf("Error: cannot convert input type to output type.\n"); | 
| 561 return kInvalidConversion; | 596 return kInvalidConversion; | 
| 562 } | 597 } | 
| 563 | 598 | 
| 564 // Create the color table if necessary and prepare the stream for decode | 599 // Create the color table if necessary and prepare the stream for decode | 
| 565 if (!createColorTable(dstInfo.alphaType())) { | 600 // Note that if it is non-NULL, inputColorCount will be modified | 
| 601 if (!createColorTable(dstInfo.alphaType(), inputColorCount)) { | |
| 566 SkCodecPrintf("Error: could not create color table.\n"); | 602 SkCodecPrintf("Error: could not create color table.\n"); | 
| 567 return kInvalidInput; | 603 return kInvalidInput; | 
| 568 } | 604 } | 
| 569 | 605 | 
| 606 // Copy the color table to the client if necessary | |
| 607 if (kIndex_8_SkColorType == dstInfo.colorType()) { | |
| 608 SkASSERT(NULL != inputColorPtr); | |
| 609 SkASSERT(NULL != inputColorCount); | |
| 610 SkASSERT(NULL != fColorTable.get()); | |
| 611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount); | |
| 612 } | |
| 613 | |
| 570 // Perform the decode | 614 // Perform the decode | 
| 571 switch (fInputFormat) { | 615 switch (fInputFormat) { | 
| 572 case kBitMask_BitmapInputFormat: | 616 case kBitMask_BitmapInputFormat: | 
| 573 return decodeMask(dstInfo, dst, dstRowBytes); | 617 return decodeMask(dstInfo, dst, dstRowBytes); | 
| 574 case kRLE_BitmapInputFormat: | 618 case kRLE_BitmapInputFormat: | 
| 575 return decodeRLE(dstInfo, dst, dstRowBytes); | 619 return decodeRLE(dstInfo, dst, dstRowBytes, opts); | 
| 576 case kStandard_BitmapInputFormat: | 620 case kStandard_BitmapInputFormat: | 
| 577 return decode(dstInfo, dst, dstRowBytes); | 621 return decode(dstInfo, dst, dstRowBytes); | 
| 578 default: | 622 default: | 
| 579 SkASSERT(false); | 623 SkASSERT(false); | 
| 580 return kInvalidInput; | 624 return kInvalidInput; | 
| 581 } | 625 } | 
| 582 } | 626 } | 
| 583 | 627 | 
| 584 /* | 628 /* | 
| 585 * | 629 * | 
| 586 * Process the color table for the bmp input | 630 * Process the color table for the bmp input | 
| 587 * | 631 * | 
| 588 */ | 632 */ | 
| 589 bool SkBmpCodec::createColorTable(SkAlphaType alphaType) { | 633 bool SkBmpCodec::createColorTable(SkAlphaType alphaType, int* numColors) { | 
| 590 // Allocate memory for color table | 634 // Allocate memory for color table | 
| 591 uint32_t colorBytes = 0; | 635 uint32_t colorBytes = 0; | 
| 592 uint32_t maxColors = 0; | 636 uint32_t maxColors = 0; | 
| 593 SkPMColor colorTable[256]; | 637 SkPMColor colorTable[256]; | 
| 594 if (fBitsPerPixel <= 8) { | 638 if (fBitsPerPixel <= 8) { | 
| 595 // Zero is a default for maxColors | 639 // Zero is a default for maxColors | 
| 596 // Also set fNumColors to maxColors when it is too large | 640 // Also set fNumColors to maxColors when it is too large | 
| 597 maxColors = 1 << fBitsPerPixel; | 641 maxColors = 1 << fBitsPerPixel; | 
| 598 if (fNumColors == 0 || fNumColors >= maxColors) { | 642 if (fNumColors == 0 || fNumColors >= maxColors) { | 
| 599 fNumColors = maxColors; | 643 fNumColors = maxColors; | 
| 600 } | 644 } | 
| 601 | 645 | 
| 646 // Inform the caller of the number of colors | |
| 647 if (NULL != numColors) { | |
| 648 SkASSERT(256 == *numColors); | |
| 649 // We set the number of colors to maxColors in order to ensure | |
| 650 // safe memory accesses. Otherwise, an invalid pixel could | |
| 651 // access memory outside of our color table array. | |
| 652 *numColors = maxColors; | |
| 653 } | |
| 654 | |
| 602 // Read the color table from the stream | 655 // Read the color table from the stream | 
| 603 colorBytes = fNumColors * fBytesPerColor; | 656 colorBytes = fNumColors * fBytesPerColor; | 
| 604 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); | 657 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); | 
| 605 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { | 658 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { | 
| 606 SkCodecPrintf("Error: unable to read color table.\n"); | 659 SkCodecPrintf("Error: unable to read color table.\n"); | 
| 607 return false; | 660 return false; | 
| 608 } | 661 } | 
| 609 | 662 | 
| 610 // Choose the proper packing function | 663 // Choose the proper packing function | 
| 611 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); | 664 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 625 packARGB = NULL; | 678 packARGB = NULL; | 
| 626 break; | 679 break; | 
| 627 } | 680 } | 
| 628 | 681 | 
| 629 // Fill in the color table | 682 // Fill in the color table | 
| 630 uint32_t i = 0; | 683 uint32_t i = 0; | 
| 631 for (; i < fNumColors; i++) { | 684 for (; i < fNumColors; i++) { | 
| 632 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); | 685 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); | 
| 633 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); | 686 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); | 
| 634 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); | 687 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); | 
| 635 uint8_t alpha = kOpaque_SkAlphaType == alphaType ? 0xFF : | 688 uint8_t alpha; | 
| 636 (fMasks->getAlphaMask() >> 24) & | 689 if (kOpaque_SkAlphaType == alphaType || kRLE_BitmapInputFormat == fI nputFormat) { | 
| 
scroggo
2015/04/07 21:15:34
This appears to fix a separate bug?
 
msarett
2015/04/08 13:59:10
Yes it fixes a bug that was almost introduced with
 | |
| 637 get_byte(cBuffer.get(), i*fBytesPerColor + 3); | 690 alpha = 0xFF; | 
| 691 } else { | |
| 692 alpha = (fMasks->getAlphaMask() >> 24) & | |
| 693 get_byte(cBuffer.get(), i*fBytesPerColor + 3); | |
| 694 } | |
| 638 colorTable[i] = packARGB(alpha, red, green, blue); | 695 colorTable[i] = packARGB(alpha, red, green, blue); | 
| 639 } | 696 } | 
| 640 | 697 | 
| 641 // To avoid segmentation faults on bad pixel data, fill the end of the | 698 // To avoid segmentation faults on bad pixel data, fill the end of the | 
| 642 // color table with black. This is the same the behavior as the | 699 // color table with black. This is the same the behavior as the | 
| 643 // chromium decoder. | 700 // chromium decoder. | 
| 644 for (; i < maxColors; i++) { | 701 for (; i < maxColors; i++) { | 
| 645 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); | 702 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); | 
| 646 } | 703 } | 
| 647 } | 704 } | 
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 733 | 790 | 
| 734 // Finished decoding the entire image | 791 // Finished decoding the entire image | 
| 735 return kSuccess; | 792 return kSuccess; | 
| 736 } | 793 } | 
| 737 | 794 | 
| 738 /* | 795 /* | 
| 739 * | 796 * | 
| 740 * Set an RLE pixel using the color table | 797 * Set an RLE pixel using the color table | 
| 741 * | 798 * | 
| 742 */ | 799 */ | 
| 743 void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes, | 800 void SkBmpCodec::setRLEPixel(void* dst, size_t dstRowBytes, | 
| 744 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, | 801 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, | 
| 745 uint8_t index) { | 802 uint8_t index) { | 
| 746 // Set the row | 803 // Set the row | 
| 747 int height = dstInfo.height(); | 804 int height = dstInfo.height(); | 
| 748 int row; | 805 int row; | 
| 749 if (kBottomUp_RowOrder == fRowOrder) { | 806 if (kBottomUp_RowOrder == fRowOrder) { | 
| 750 row = height - y - 1; | 807 row = height - y - 1; | 
| 751 } else { | 808 } else { | 
| 752 row = y; | 809 row = y; | 
| 753 } | 810 } | 
| 754 | 811 | 
| 755 // Set the pixel based on destination color type | 812 // Set the pixel based on destination color type | 
| 756 switch (dstInfo.colorType()) { | 813 switch (dstInfo.colorType()) { | 
| 757 case kN32_SkColorType: { | 814 case kN32_SkColorType: { | 
| 758 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, | 815 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst, | 
| 759 row * (int) dstRowBytes); | 816 row * (int) dstRowBytes); | 
| 760 dstRow[x] = fColorTable->operator[](index); | 817 dstRow[x] = fColorTable->operator[](index); | 
| 761 break; | 818 break; | 
| 762 } | 819 } | 
| 763 case kRGB_565_SkColorType: { | |
| 764 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, | |
| 765 row * (int) dstRowBytes); | |
| 766 dstRow[x] = SkPixel32ToPixel16(fColorTable->operator[](index)); | |
| 767 break; | |
| 768 } | |
| 769 default: | 820 default: | 
| 770 // This case should not be reached. We should catch an invalid | 821 // This case should not be reached. We should catch an invalid | 
| 771 // color type when we check that the conversion is possible. | 822 // color type when we check that the conversion is possible. | 
| 772 SkASSERT(false); | 823 SkASSERT(false); | 
| 773 break; | 824 break; | 
| 774 } | 825 } | 
| 775 } | 826 } | 
| 776 | 827 | 
| 777 /* | 828 /* | 
| 778 * | 829 * | 
| 779 * Set an RLE pixel from R, G, B values | 830 * Set an RLE pixel from R, G, B values | 
| 780 * | 831 * | 
| 781 */ | 832 */ | 
| 782 void SkBmpCodec::setRLE24Pixel(SkPMColor* dst, size_t dstRowBytes, | 833 void SkBmpCodec::setRLE24Pixel(void* dst, size_t dstRowBytes, | 
| 783 const SkImageInfo& dstInfo, uint32_t x, | 834 const SkImageInfo& dstInfo, uint32_t x, | 
| 784 uint32_t y, uint8_t red, uint8_t green, | 835 uint32_t y, uint8_t red, uint8_t green, | 
| 785 uint8_t blue) { | 836 uint8_t blue) { | 
| 786 // Set the row | 837 // Set the row | 
| 787 int height = dstInfo.height(); | 838 int height = dstInfo.height(); | 
| 788 int row; | 839 int row; | 
| 789 if (kBottomUp_RowOrder == fRowOrder) { | 840 if (kBottomUp_RowOrder == fRowOrder) { | 
| 790 row = height - y - 1; | 841 row = height - y - 1; | 
| 791 } else { | 842 } else { | 
| 792 row = y; | 843 row = y; | 
| 793 } | 844 } | 
| 794 | 845 | 
| 795 // Set the pixel based on destination color type | 846 // Set the pixel based on destination color type | 
| 796 switch (dstInfo.colorType()) { | 847 switch (dstInfo.colorType()) { | 
| 797 case kN32_SkColorType: { | 848 case kN32_SkColorType: { | 
| 798 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, | 849 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst, | 
| 799 row * (int) dstRowBytes); | 850 row * (int) dstRowBytes); | 
| 800 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 851 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 
| 801 break; | 852 break; | 
| 802 } | 853 } | 
| 803 case kRGB_565_SkColorType: { | |
| 804 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, | |
| 805 row * (int) dstRowBytes); | |
| 806 dstRow[x] = SkPack888ToRGB16(red, green, blue); | |
| 807 break; | |
| 808 } | |
| 809 default: | 854 default: | 
| 810 // This case should not be reached. We should catch an invalid | 855 // This case should not be reached. We should catch an invalid | 
| 811 // color type when we check that the conversion is possible. | 856 // color type when we check that the conversion is possible. | 
| 812 SkASSERT(false); | 857 SkASSERT(false); | 
| 813 break; | 858 break; | 
| 814 } | 859 } | 
| 815 } | 860 } | 
| 816 | 861 | 
| 817 /* | 862 /* | 
| 818 * | 863 * | 
| 819 * Performs the bitmap decoding for RLE input format | 864 * Performs the bitmap decoding for RLE input format | 
| 820 * RLE decoding is performed all at once, rather than a one row at a time | 865 * RLE decoding is performed all at once, rather than a one row at a time | 
| 821 * | 866 * | 
| 822 */ | 867 */ | 
| 823 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, | 868 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, | 
| 824 void* dst, size_t dstRowBytes) { | 869 void* dst, size_t dstRowBytes, | 
| 870 const Options& opts) { | |
| 825 // Set RLE flags | 871 // Set RLE flags | 
| 826 static const uint8_t RLE_ESCAPE = 0; | 872 static const uint8_t RLE_ESCAPE = 0; | 
| 827 static const uint8_t RLE_EOL = 0; | 873 static const uint8_t RLE_EOL = 0; | 
| 828 static const uint8_t RLE_EOF = 1; | 874 static const uint8_t RLE_EOF = 1; | 
| 829 static const uint8_t RLE_DELTA = 2; | 875 static const uint8_t RLE_DELTA = 2; | 
| 830 | 876 | 
| 831 // Set constant values | 877 // Set constant values | 
| 832 const int width = dstInfo.width(); | 878 const int width = dstInfo.width(); | 
| 833 const int height = dstInfo.height(); | 879 const int height = dstInfo.height(); | 
| 834 | 880 | 
| 835 // Input buffer parameters | 881 // Input buffer parameters | 
| 836 uint32_t currByte = 0; | 882 uint32_t currByte = 0; | 
| 837 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); | 883 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); | 
| 838 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); | 884 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); | 
| 839 if (totalBytes < fRLEBytes) { | 885 if (totalBytes < fRLEBytes) { | 
| 840 SkCodecPrintf("Warning: incomplete RLE file.\n"); | 886 SkCodecPrintf("Warning: incomplete RLE file.\n"); | 
| 841 } else if (totalBytes <= 0) { | 887 } else if (totalBytes <= 0) { | 
| 842 SkCodecPrintf("Error: could not read RLE image data.\n"); | 888 SkCodecPrintf("Error: could not read RLE image data.\n"); | 
| 843 return kInvalidInput; | 889 return kInvalidInput; | 
| 844 } | 890 } | 
| 845 | 891 | 
| 846 // Destination parameters | 892 // Destination parameters | 
| 847 int x = 0; | 893 int x = 0; | 
| 848 int y = 0; | 894 int y = 0; | 
| 849 // If the code skips pixels, remaining pixels are transparent or black | 895 | 
| 850 // TODO: Skip this if memory was already zeroed. | 896 // Set the background as transparent. Then, if the RLE code skips pixels, | 
| 851 memset(dst, 0, dstRowBytes * height); | 897 // the skipped pixels will be transparent. | 
| 852 SkPMColor* dstPtr = (SkPMColor*) dst; | 898 // Because of the need for transparent pixels, kN32 is the only color | 
| 899 // type that makes sense for the destination format. | |
| 900 SkASSERT(kN32_SkColorType == dstInfo.colorType()); | |
| 901 if (kNo_ZeroInitialized == opts.fZeroInitialized) { | |
| 902 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, 0, SK_ColorTRANSPARENT, NULL ); | |
| 903 } | |
| 853 | 904 | 
| 854 while (true) { | 905 while (true) { | 
| 855 // Every entry takes at least two bytes | 906 // Every entry takes at least two bytes | 
| 856 if ((int) totalBytes - currByte < 2) { | 907 if ((int) totalBytes - currByte < 2) { | 
| 857 SkCodecPrintf("Warning: incomplete RLE input.\n"); | 908 SkCodecPrintf("Warning: incomplete RLE input.\n"); | 
| 858 return kIncompleteInput; | 909 return kIncompleteInput; | 
| 859 } | 910 } | 
| 860 | 911 | 
| 861 // Read the next two bytes. These bytes have different meanings | 912 // Read the next two bytes. These bytes have different meanings | 
| 862 // depending on their values. In the first interpretation, the first | 913 // depending on their values. In the first interpretation, the first | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 (int) totalBytes - currByte < SkAlign2(rowBytes)) { | 964 (int) totalBytes - currByte < SkAlign2(rowBytes)) { | 
| 914 SkCodecPrintf("Warning: invalid RLE input.\n"); | 965 SkCodecPrintf("Warning: invalid RLE input.\n"); | 
| 915 return kIncompleteInput; | 966 return kIncompleteInput; | 
| 916 } | 967 } | 
| 917 // Set numPixels number of pixels | 968 // Set numPixels number of pixels | 
| 918 while (numPixels > 0) { | 969 while (numPixels > 0) { | 
| 919 switch(fBitsPerPixel) { | 970 switch(fBitsPerPixel) { | 
| 920 case 4: { | 971 case 4: { | 
| 921 SkASSERT(currByte < totalBytes); | 972 SkASSERT(currByte < totalBytes); | 
| 922 uint8_t val = buffer.get()[currByte++]; | 973 uint8_t val = buffer.get()[currByte++]; | 
| 923 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, | 974 setRLEPixel(dst, dstRowBytes, dstInfo, x++, | 
| 924 y, val >> 4); | 975 y, val >> 4); | 
| 925 numPixels--; | 976 numPixels--; | 
| 926 if (numPixels != 0) { | 977 if (numPixels != 0) { | 
| 927 setRLEPixel(dstPtr, dstRowBytes, dstInfo, | 978 setRLEPixel(dst, dstRowBytes, dstInfo, | 
| 928 x++, y, val & 0xF); | 979 x++, y, val & 0xF); | 
| 929 numPixels--; | 980 numPixels--; | 
| 930 } | 981 } | 
| 931 break; | 982 break; | 
| 932 } | 983 } | 
| 933 case 8: | 984 case 8: | 
| 934 SkASSERT(currByte < totalBytes); | 985 SkASSERT(currByte < totalBytes); | 
| 935 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, | 986 setRLEPixel(dst, dstRowBytes, dstInfo, x++, | 
| 936 y, buffer.get()[currByte++]); | 987 y, buffer.get()[currByte++]); | 
| 937 numPixels--; | 988 numPixels--; | 
| 938 break; | 989 break; | 
| 939 case 24: { | 990 case 24: { | 
| 940 SkASSERT(currByte + 2 < totalBytes); | 991 SkASSERT(currByte + 2 < totalBytes); | 
| 941 uint8_t blue = buffer.get()[currByte++]; | 992 uint8_t blue = buffer.get()[currByte++]; | 
| 942 uint8_t green = buffer.get()[currByte++]; | 993 uint8_t green = buffer.get()[currByte++]; | 
| 943 uint8_t red = buffer.get()[currByte++]; | 994 uint8_t red = buffer.get()[currByte++]; | 
| 944 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, | 995 setRLE24Pixel(dst, dstRowBytes, dstInfo, | 
| 945 x++, y, red, green, blue); | 996 x++, y, red, green, blue); | 
| 946 numPixels--; | 997 numPixels--; | 
| 947 } | 998 } | 
| 948 default: | 999 default: | 
| 949 SkASSERT(false); | 1000 SkASSERT(false); | 
| 950 return kInvalidInput; | 1001 return kInvalidInput; | 
| 951 } | 1002 } | 
| 952 } | 1003 } | 
| 953 // Skip a byte if necessary to maintain alignment | 1004 // Skip a byte if necessary to maintain alignment | 
| 954 if (!SkIsAlign2(rowBytes)) { | 1005 if (!SkIsAlign2(rowBytes)) { | 
| (...skipping 15 matching lines...) Expand all Loading... | |
| 970 if ((int) totalBytes - currByte < 2) { | 1021 if ((int) totalBytes - currByte < 2) { | 
| 971 SkCodecPrintf("Warning: incomplete RLE input\n"); | 1022 SkCodecPrintf("Warning: incomplete RLE input\n"); | 
| 972 return kIncompleteInput; | 1023 return kIncompleteInput; | 
| 973 } | 1024 } | 
| 974 | 1025 | 
| 975 // Fill the pixels up to endX with the specified color | 1026 // Fill the pixels up to endX with the specified color | 
| 976 uint8_t blue = task; | 1027 uint8_t blue = task; | 
| 977 uint8_t green = buffer.get()[currByte++]; | 1028 uint8_t green = buffer.get()[currByte++]; | 
| 978 uint8_t red = buffer.get()[currByte++]; | 1029 uint8_t red = buffer.get()[currByte++]; | 
| 979 while (x < endX) { | 1030 while (x < endX) { | 
| 980 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red, | 1031 setRLE24Pixel(dst, dstRowBytes, dstInfo, x++, y, red, | 
| 981 green, blue); | 1032 green, blue); | 
| 982 } | 1033 } | 
| 983 } else { | 1034 } else { | 
| 984 // In RLE8 or RLE4, the second byte read gives the index in the | 1035 // In RLE8 or RLE4, the second byte read gives the index in the | 
| 985 // color table to look up the pixel color. | 1036 // color table to look up the pixel color. | 
| 986 // RLE8 has one color index that gets repeated | 1037 // RLE8 has one color index that gets repeated | 
| 987 // RLE4 has two color indexes in the upper and lower 4 bits of | 1038 // RLE4 has two color indexes in the upper and lower 4 bits of | 
| 988 // the bytes, which are alternated | 1039 // the bytes, which are alternated | 
| 989 uint8_t indices[2] = { task, task }; | 1040 uint8_t indices[2] = { task, task }; | 
| 990 if (4 == fBitsPerPixel) { | 1041 if (4 == fBitsPerPixel) { | 
| 991 indices[0] >>= 4; | 1042 indices[0] >>= 4; | 
| 992 indices[1] &= 0xf; | 1043 indices[1] &= 0xf; | 
| 993 } | 1044 } | 
| 994 | 1045 | 
| 995 // Set the indicated number of pixels | 1046 // Set the indicated number of pixels | 
| 996 for (int which = 0; x < endX; x++) { | 1047 for (int which = 0; x < endX; x++) { | 
| 997 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x, y, | 1048 setRLEPixel(dst, dstRowBytes, dstInfo, x, y, | 
| 998 indices[which]); | 1049 indices[which]); | 
| 999 which = !which; | 1050 which = !which; | 
| 1000 } | 1051 } | 
| 1001 } | 1052 } | 
| 1002 } | 1053 } | 
| 1003 } | 1054 } | 
| 1004 } | 1055 } | 
| 1005 | 1056 | 
| 1006 /* | 1057 /* | 
| 1007 * | 1058 * | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1077 } | 1128 } | 
| 1078 | 1129 | 
| 1079 // FIXME: This code exists to match the behavior in the chromium decoder | 1130 // FIXME: This code exists to match the behavior in the chromium decoder | 
| 1080 // and to follow the bmp specification as it relates to alpha masks. It is | 1131 // and to follow the bmp specification as it relates to alpha masks. It is | 
| 1081 // commented out because we have yet to discover a test image that provides | 1132 // commented out because we have yet to discover a test image that provides | 
| 1082 // an alpha mask and uses this decode mode. | 1133 // an alpha mask and uses this decode mode. | 
| 1083 | 1134 | 
| 1084 // Now we adjust the output image with some additional behavior that | 1135 // Now we adjust the output image with some additional behavior that | 
| 1085 // SkSwizzler does not support. Firstly, all bmp images that contain | 1136 // SkSwizzler does not support. Firstly, all bmp images that contain | 
| 1086 // alpha are masked by the alpha mask. Secondly, many fully transparent | 1137 // alpha are masked by the alpha mask. Secondly, many fully transparent | 
| 1087 // bmp images are intended to be opaque. Here, we make those corrections. | 1138 // bmp images are intended to be opaque. Here, we make those corrections | 
| 1139 // in the kN32 case. | |
| 1088 /* | 1140 /* | 
| 1089 SkPMColor* dstRow = (SkPMColor*) dst; | 1141 SkPMColor* dstRow = (SkPMColor*) dst; | 
| 1090 if (SkSwizzler::kBGRA == config) { | 1142 if (SkSwizzler::kBGRA == config) { | 
| 1091 for (int y = 0; y < height; y++) { | 1143 for (int y = 0; y < height; y++) { | 
| 1092 for (int x = 0; x < width; x++) { | 1144 for (int x = 0; x < width; x++) { | 
| 1093 if (transparent) { | 1145 if (transparent) { | 
| 1094 dstRow[x] |= 0xFF000000; | 1146 dstRow[x] |= 0xFF000000; | 
| 1095 } else { | 1147 } else { | 
| 1096 dstRow[x] &= alphaMask; | 1148 dstRow[x] &= alphaMask; | 
| 1097 } | 1149 } | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1132 uint32_t alphaBit = | 1184 uint32_t alphaBit = | 
| 1133 (srcBuffer.get()[quotient] >> shift) & 0x1; | 1185 (srcBuffer.get()[quotient] >> shift) & 0x1; | 
| 1134 dstRow[x] &= alphaBit - 1; | 1186 dstRow[x] &= alphaBit - 1; | 
| 1135 } | 1187 } | 
| 1136 } | 1188 } | 
| 1137 } | 1189 } | 
| 1138 | 1190 | 
| 1139 // Finished decoding the entire image | 1191 // Finished decoding the entire image | 
| 1140 return kSuccess; | 1192 return kSuccess; | 
| 1141 } | 1193 } | 
| OLD | NEW |