| 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 "SkBmpCodec.h" | 8 #include "SkBmpCodec.h" |
| 9 #include "SkBmpMaskCodec.h" | 9 #include "SkBmpMaskCodec.h" |
| 10 #include "SkBmpRLECodec.h" | 10 #include "SkBmpRLECodec.h" |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 // Seems like we can just assume that the offset is zero
and try to decode? | 408 // Seems like we can just assume that the offset is zero
and try to decode? |
| 409 // Maybe we don't want to try to decode corrupt images? | 409 // Maybe we don't want to try to decode corrupt images? |
| 410 SkCodecPrintf("Error: pixel data offset less than header size.\n"); | 410 SkCodecPrintf("Error: pixel data offset less than header size.\n"); |
| 411 return false; | 411 return false; |
| 412 } | 412 } |
| 413 | 413 |
| 414 | 414 |
| 415 | 415 |
| 416 switch (inputFormat) { | 416 switch (inputFormat) { |
| 417 case kStandard_BmpInputFormat: { | 417 case kStandard_BmpInputFormat: { |
| 418 // BMPs-in-ICOs often contain an alpha mask after the image, which | 418 // BMPs are generally opaque, however BMPs-in-ICOs may contain |
| 419 // means we cannot guarantee that an image is opaque, even if the | 419 // a transparency mask after the image. Therefore, we mark the |
| 420 // embedded bmp is opaque. | 420 // alpha as kBinary if the BMP is contained in an ICO. |
| 421 // We use |isOpaque| to indicate if the BMP itself is opaque, but | 421 // We use |isOpaque| to indicate if the BMP itself is opaque. |
| 422 // still need to recommend kUnpremul when it is contained in an ICO. | 422 SkEncodedInfo::Alpha alpha = inIco ? SkEncodedInfo::kBinary_Alpha : |
| 423 SkColorType colorType = kN32_SkColorType; | 423 SkEncodedInfo::kOpaque_Alpha; |
| 424 SkAlphaType alphaType = inIco ? kUnpremul_SkAlphaType : kOpaque_SkAl
phaType; | |
| 425 bool isOpaque = true; | 424 bool isOpaque = true; |
| 425 |
| 426 SkEncodedInfo::Color color; |
| 427 uint8_t bitsPerComponent; |
| 426 switch (bitsPerPixel) { | 428 switch (bitsPerPixel) { |
| 427 // Palette formats | 429 // Palette formats |
| 428 case 1: | 430 case 1: |
| 429 case 2: | 431 case 2: |
| 430 case 4: | 432 case 4: |
| 431 case 8: | 433 case 8: |
| 432 // We cannot recommend a palette color type for ICOs because
they | 434 // In the case of ICO, kBGRA is actually the closest match, |
| 433 // may contain a transparency mask. | 435 // since we will need to apply a transparency mask. |
| 434 if (!inIco) { | 436 if (inIco) { |
| 435 colorType = kIndex_8_SkColorType; | 437 color = SkEncodedInfo::kBGRA_Color; |
| 438 bitsPerComponent = 8; |
| 439 } else { |
| 440 color = SkEncodedInfo::kPalette_Color; |
| 441 bitsPerComponent = bitsPerPixel; |
| 436 } | 442 } |
| 437 break; | 443 break; |
| 438 case 24: | 444 case 24: |
| 445 color = SkEncodedInfo::kBGR_Color; |
| 446 bitsPerComponent = 8; |
| 447 break; |
| 439 case 32: | 448 case 32: |
| 440 // 32-bit BMP-in-ICOs actually use the alpha channel in plac
e of a | 449 // 32-bit BMP-in-ICOs actually use the alpha channel in plac
e of a |
| 441 // transparency mask. | 450 // transparency mask. |
| 442 if (inIco) { | 451 if (inIco) { |
| 443 isOpaque = false; | 452 isOpaque = false; |
| 453 alpha = SkEncodedInfo::kUnpremul_Alpha; |
| 454 color = SkEncodedInfo::kBGRA_Color; |
| 455 } else { |
| 456 color = SkEncodedInfo::kBGRX_Color; |
| 444 } | 457 } |
| 458 bitsPerComponent = 8; |
| 445 break; | 459 break; |
| 446 default: | 460 default: |
| 447 SkCodecPrintf("Error: invalid input value for bits per pixel
.\n"); | 461 SkCodecPrintf("Error: invalid input value for bits per pixel
.\n"); |
| 448 return false; | 462 return false; |
| 449 } | 463 } |
| 450 | 464 |
| 451 if (codecOut) { | 465 if (codecOut) { |
| 452 // We require streams to have a memory base for Bmp-in-Ico decod
es. | 466 // We require streams to have a memory base for Bmp-in-Ico decod
es. |
| 453 SkASSERT(!inIco || nullptr != stream->getMemoryBase()); | 467 SkASSERT(!inIco || nullptr != stream->getMemoryBase()); |
| 454 | 468 |
| 455 // Set the image info and create a codec. | 469 // Set the image info and create a codec. |
| 456 const SkImageInfo imageInfo = SkImageInfo::Make(width, height, c
olorType, | 470 const SkEncodedInfo info = SkEncodedInfo::Make(width, height, co
lor, alpha, |
| 457 alphaType); | 471 bitsPerComponent); |
| 458 *codecOut = new SkBmpStandardCodec(imageInfo, stream, bitsPerPix
el, numColors, | 472 *codecOut = new SkBmpStandardCodec(info, stream, bitsPerPixel, n
umColors, |
| 459 bytesPerColor, offset - bytesRead, rowOrder, isOpaque, i
nIco); | 473 bytesPerColor, offset - bytesRead, rowOrder, isOpaque, i
nIco); |
| 460 | 474 |
| 461 } | 475 } |
| 462 return true; | 476 return true; |
| 463 } | 477 } |
| 464 | 478 |
| 465 case kBitMask_BmpInputFormat: { | 479 case kBitMask_BmpInputFormat: { |
| 466 // Bmp-in-Ico must be standard mode | 480 // Bmp-in-Ico must be standard mode |
| 467 if (inIco) { | 481 if (inIco) { |
| 468 SkCodecPrintf("Error: Icos may not use bit mask format.\n"); | 482 SkCodecPrintf("Error: Icos may not use bit mask format.\n"); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 488 } | 502 } |
| 489 | 503 |
| 490 if (codecOut) { | 504 if (codecOut) { |
| 491 // Check that input bit masks are valid and create the masks obj
ect | 505 // Check that input bit masks are valid and create the masks obj
ect |
| 492 SkAutoTDelete<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bi
tsPerPixel)); | 506 SkAutoTDelete<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bi
tsPerPixel)); |
| 493 if (nullptr == masks) { | 507 if (nullptr == masks) { |
| 494 SkCodecPrintf("Error: invalid input masks.\n"); | 508 SkCodecPrintf("Error: invalid input masks.\n"); |
| 495 return false; | 509 return false; |
| 496 } | 510 } |
| 497 | 511 |
| 498 // Set the image info | 512 // Masked bmps are not a great fit for SkEncodedInfo, since they
have |
| 499 SkAlphaType alphaType = masks->getAlphaMask() ? kUnpremul_SkAlph
aType : | 513 // arbitrary component orderings and bits per component. Here w
e choose |
| 500 kOpaque_SkAlphaType; | 514 // somewhat reasonable values - it's ok that we don't match exac
tly |
| 501 const SkImageInfo imageInfo = SkImageInfo::Make(width, height, k
N32_SkColorType, | 515 // because SkBmpMaskCodec has its own mask swizzler anyway. |
| 502 alphaType); | 516 SkEncodedInfo::Color color; |
| 503 *codecOut = new SkBmpMaskCodec(imageInfo, stream, bitsPerPixel,
masks.release(), | 517 SkEncodedInfo::Alpha alpha; |
| 518 if (masks->getAlphaMask()) { |
| 519 color = SkEncodedInfo::kBGRA_Color; |
| 520 alpha = SkEncodedInfo::kUnpremul_Alpha; |
| 521 } else { |
| 522 color = SkEncodedInfo::kBGR_Color; |
| 523 alpha = SkEncodedInfo::kOpaque_Alpha; |
| 524 } |
| 525 const SkEncodedInfo info = SkEncodedInfo::Make(width, height, co
lor, alpha, 8); |
| 526 *codecOut = new SkBmpMaskCodec(info, stream, bitsPerPixel, masks
.release(), |
| 504 rowOrder); | 527 rowOrder); |
| 505 } | 528 } |
| 506 return true; | 529 return true; |
| 507 } | 530 } |
| 508 | 531 |
| 509 case kRLE_BmpInputFormat: { | 532 case kRLE_BmpInputFormat: { |
| 510 // We should not reach this point without a valid value of bitsPerPi
xel. | 533 // We should not reach this point without a valid value of bitsPerPi
xel. |
| 511 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixe
l); | 534 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixe
l); |
| 512 | 535 |
| 513 // Check for a valid number of total bytes when in RLE mode | 536 // Check for a valid number of total bytes when in RLE mode |
| 514 if (totalBytes <= offset) { | 537 if (totalBytes <= offset) { |
| 515 SkCodecPrintf("Error: RLE requires valid input size.\n"); | 538 SkCodecPrintf("Error: RLE requires valid input size.\n"); |
| 516 return false; | 539 return false; |
| 517 } | 540 } |
| 518 const size_t RLEBytes = totalBytes - offset; | 541 const size_t RLEBytes = totalBytes - offset; |
| 519 | 542 |
| 520 // Bmp-in-Ico must be standard mode | 543 // Bmp-in-Ico must be standard mode |
| 521 // When inIco is true, this line cannot be reached, since we | 544 // When inIco is true, this line cannot be reached, since we |
| 522 // require that RLE Bmps have a valid number of totalBytes, and | 545 // require that RLE Bmps have a valid number of totalBytes, and |
| 523 // Icos skip the header that contains totalBytes. | 546 // Icos skip the header that contains totalBytes. |
| 524 SkASSERT(!inIco); | 547 SkASSERT(!inIco); |
| 525 | 548 |
| 526 if (codecOut) { | 549 if (codecOut) { |
| 527 // RLE inputs may skip pixels, leaving them as transparent. Thi
s | 550 // RLE inputs may skip pixels, leaving them as transparent. Thi
s |
| 528 // is uncommon, but we cannot be certain that an RLE bmp will be | 551 // is uncommon, but we cannot be certain that an RLE bmp will be |
| 529 // opaque. | 552 // opaque or that we will be able to represent it with a palette
. |
| 530 const SkImageInfo imageInfo = SkImageInfo::Make(width, height, k
N32_SkColorType, | 553 // For that reason, we always indicate that we are kBGRA. |
| 531 kUnpremul_SkAlphaType); | 554 const SkEncodedInfo info = SkEncodedInfo::Make(width, height, |
| 532 *codecOut = new SkBmpRLECodec(imageInfo, stream, bitsPerPixel, n
umColors, | 555 SkEncodedInfo::kBGRA_Color, SkEncodedInfo::kBinary_Alpha
, 8); |
| 556 *codecOut = new SkBmpRLECodec(info, stream, bitsPerPixel, numCol
ors, |
| 533 bytesPerColor, offset - bytesRead, rowOrder, RLEBytes); | 557 bytesPerColor, offset - bytesRead, rowOrder, RLEBytes); |
| 534 } | 558 } |
| 535 return true; | 559 return true; |
| 536 } | 560 } |
| 537 default: | 561 default: |
| 538 SkASSERT(false); | 562 SkASSERT(false); |
| 539 return false; | 563 return false; |
| 540 } | 564 } |
| 541 } | 565 } |
| 542 | 566 |
| 543 /* | 567 /* |
| 544 * Creates a bmp decoder | 568 * Creates a bmp decoder |
| 545 * Reads enough of the stream to determine the image format | 569 * Reads enough of the stream to determine the image format |
| 546 */ | 570 */ |
| 547 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) { | 571 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) { |
| 548 SkAutoTDelete<SkStream> streamDeleter(stream); | 572 SkAutoTDelete<SkStream> streamDeleter(stream); |
| 549 SkCodec* codec = nullptr; | 573 SkCodec* codec = nullptr; |
| 550 if (ReadHeader(stream, inIco, &codec)) { | 574 if (ReadHeader(stream, inIco, &codec)) { |
| 551 // codec has taken ownership of stream, so we do not need to | 575 // codec has taken ownership of stream, so we do not need to |
| 552 // delete it. | 576 // delete it. |
| 553 SkASSERT(codec); | 577 SkASSERT(codec); |
| 554 streamDeleter.release(); | 578 streamDeleter.release(); |
| 555 return codec; | 579 return codec; |
| 556 } | 580 } |
| 557 return nullptr; | 581 return nullptr; |
| 558 } | 582 } |
| 559 | 583 |
| 560 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, | 584 SkBmpCodec::SkBmpCodec(const SkEncodedInfo& info, SkStream* stream, |
| 561 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder) | 585 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder) |
| 562 : INHERITED(info, stream) | 586 : INHERITED(info, stream) |
| 563 , fBitsPerPixel(bitsPerPixel) | 587 , fBitsPerPixel(bitsPerPixel) |
| 564 , fRowOrder(rowOrder) | 588 , fRowOrder(rowOrder) |
| 565 , fSrcRowBytes(SkAlign4(compute_row_bytes(info.width(), fBitsPerPixel))) | 589 , fSrcRowBytes(SkAlign4(compute_row_bytes(info.width(), fBitsPerPixel))) |
| 566 {} | 590 {} |
| 567 | 591 |
| 568 bool SkBmpCodec::onRewind() { | 592 bool SkBmpCodec::onRewind() { |
| 569 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr); | 593 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr); |
| 570 } | 594 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 596 } | 620 } |
| 597 | 621 |
| 598 bool SkBmpCodec::skipRows(int count) { | 622 bool SkBmpCodec::skipRows(int count) { |
| 599 const size_t bytesToSkip = count * fSrcRowBytes; | 623 const size_t bytesToSkip = count * fSrcRowBytes; |
| 600 return this->stream()->skip(bytesToSkip) == bytesToSkip; | 624 return this->stream()->skip(bytesToSkip) == bytesToSkip; |
| 601 } | 625 } |
| 602 | 626 |
| 603 bool SkBmpCodec::onSkipScanlines(int count) { | 627 bool SkBmpCodec::onSkipScanlines(int count) { |
| 604 return this->skipRows(count); | 628 return this->skipRows(count); |
| 605 } | 629 } |
| OLD | NEW |