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