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 uint8_t bitsPerComponent = SkTMin((uint16_t) 8, bitsPerPixel); | |
scroggo
2016/03/23 14:48:50
It seems odd that you set bitsPerComponent to min(
msarett
2016/03/24 16:20:43
Agreed. I think maybe it's clearer to handle it i
| |
427 SkEncodedInfo::Color color; | |
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; | |
436 } | 441 } |
437 break; | 442 break; |
438 case 24: | 443 case 24: |
444 color = SkEncodedInfo::kBGR_Color; | |
445 break; | |
439 case 32: | 446 case 32: |
440 // 32-bit BMP-in-ICOs actually use the alpha channel in plac e of a | 447 // 32-bit BMP-in-ICOs actually use the alpha channel in plac e of a |
441 // transparency mask. | 448 // transparency mask. |
442 if (inIco) { | 449 if (inIco) { |
443 isOpaque = false; | 450 isOpaque = false; |
451 alpha = SkEncodedInfo::kUnpremul_Alpha; | |
452 color = SkEncodedInfo::kBGRA_Color; | |
453 } else { | |
454 color = SkEncodedInfo::kBGRX_Color; | |
444 } | 455 } |
445 break; | 456 break; |
446 default: | 457 default: |
447 SkCodecPrintf("Error: invalid input value for bits per pixel .\n"); | 458 SkCodecPrintf("Error: invalid input value for bits per pixel .\n"); |
448 return false; | 459 return false; |
449 } | 460 } |
450 | 461 |
451 if (codecOut) { | 462 if (codecOut) { |
452 // We require streams to have a memory base for Bmp-in-Ico decod es. | 463 // We require streams to have a memory base for Bmp-in-Ico decod es. |
453 SkASSERT(!inIco || nullptr != stream->getMemoryBase()); | 464 SkASSERT(!inIco || nullptr != stream->getMemoryBase()); |
454 | 465 |
455 // Set the image info and create a codec. | 466 // Set the image info and create a codec. |
456 const SkImageInfo imageInfo = SkImageInfo::Make(width, height, c olorType, | 467 const SkEncodedInfo info = SkEncodedInfo::Make(width, height, co lor, alpha, |
457 alphaType); | 468 bitsPerComponent); |
458 *codecOut = new SkBmpStandardCodec(imageInfo, stream, bitsPerPix el, numColors, | 469 *codecOut = new SkBmpStandardCodec(info, stream, bitsPerPixel, n umColors, |
459 bytesPerColor, offset - bytesRead, rowOrder, isOpaque, i nIco); | 470 bytesPerColor, offset - bytesRead, rowOrder, isOpaque, i nIco); |
460 | 471 |
461 } | 472 } |
462 return true; | 473 return true; |
463 } | 474 } |
464 | 475 |
465 case kBitMask_BmpInputFormat: { | 476 case kBitMask_BmpInputFormat: { |
466 // Bmp-in-Ico must be standard mode | 477 // Bmp-in-Ico must be standard mode |
467 if (inIco) { | 478 if (inIco) { |
468 SkCodecPrintf("Error: Icos may not use bit mask format.\n"); | 479 SkCodecPrintf("Error: Icos may not use bit mask format.\n"); |
(...skipping 19 matching lines...) Expand all Loading... | |
488 } | 499 } |
489 | 500 |
490 if (codecOut) { | 501 if (codecOut) { |
491 // Check that input bit masks are valid and create the masks obj ect | 502 // Check that input bit masks are valid and create the masks obj ect |
492 SkAutoTDelete<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bi tsPerPixel)); | 503 SkAutoTDelete<SkMasks> masks(SkMasks::CreateMasks(inputMasks, bi tsPerPixel)); |
493 if (nullptr == masks) { | 504 if (nullptr == masks) { |
494 SkCodecPrintf("Error: invalid input masks.\n"); | 505 SkCodecPrintf("Error: invalid input masks.\n"); |
495 return false; | 506 return false; |
496 } | 507 } |
497 | 508 |
498 // Set the image info | 509 // Masked bmps are not a great fit for SkEncodedInfo, since they have |
scroggo
2016/03/23 14:48:50
Should SkEncodedInfo adapt to support masked bmps?
msarett
2016/03/24 16:20:44
I thought about 3 options:
(1) Create all of the m
scroggo
2016/03/24 20:51:03
I'm also fine with Mask BMP being a weird special
| |
499 SkAlphaType alphaType = masks->getAlphaMask() ? kUnpremul_SkAlph aType : | 510 // arbitrary component orderings and bits per component. Here w e choose |
500 kOpaque_SkAlphaType; | 511 // somewhat reasonable values - it's ok that we don't match exac tly |
501 const SkImageInfo imageInfo = SkImageInfo::Make(width, height, k N32_SkColorType, | 512 // because SkBmpMaskCodec has its own mask swizzler anyway. |
502 alphaType); | 513 SkEncodedInfo::Color color; |
503 *codecOut = new SkBmpMaskCodec(imageInfo, stream, bitsPerPixel, masks.release(), | 514 SkEncodedInfo::Alpha alpha; |
515 if (masks->getAlphaMask()) { | |
516 color = SkEncodedInfo::kBGRA_Color; | |
517 alpha = SkEncodedInfo::kUnpremul_Alpha; | |
518 } else { | |
519 color = SkEncodedInfo::kBGR_Color; | |
520 alpha = SkEncodedInfo::kOpaque_Alpha; | |
521 } | |
522 const SkEncodedInfo info = SkEncodedInfo::Make(width, height, co lor, alpha, 8); | |
523 *codecOut = new SkBmpMaskCodec(info, stream, bitsPerPixel, masks .release(), | |
504 rowOrder); | 524 rowOrder); |
505 } | 525 } |
506 return true; | 526 return true; |
507 } | 527 } |
508 | 528 |
509 case kRLE_BmpInputFormat: { | 529 case kRLE_BmpInputFormat: { |
510 // We should not reach this point without a valid value of bitsPerPi xel. | 530 // We should not reach this point without a valid value of bitsPerPi xel. |
511 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixe l); | 531 SkASSERT(4 == bitsPerPixel || 8 == bitsPerPixel || 24 == bitsPerPixe l); |
512 | 532 |
513 // Check for a valid number of total bytes when in RLE mode | 533 // Check for a valid number of total bytes when in RLE mode |
514 if (totalBytes <= offset) { | 534 if (totalBytes <= offset) { |
515 SkCodecPrintf("Error: RLE requires valid input size.\n"); | 535 SkCodecPrintf("Error: RLE requires valid input size.\n"); |
516 return false; | 536 return false; |
517 } | 537 } |
518 const size_t RLEBytes = totalBytes - offset; | 538 const size_t RLEBytes = totalBytes - offset; |
519 | 539 |
520 // Bmp-in-Ico must be standard mode | 540 // Bmp-in-Ico must be standard mode |
521 // When inIco is true, this line cannot be reached, since we | 541 // When inIco is true, this line cannot be reached, since we |
522 // require that RLE Bmps have a valid number of totalBytes, and | 542 // require that RLE Bmps have a valid number of totalBytes, and |
523 // Icos skip the header that contains totalBytes. | 543 // Icos skip the header that contains totalBytes. |
524 SkASSERT(!inIco); | 544 SkASSERT(!inIco); |
525 | 545 |
526 if (codecOut) { | 546 if (codecOut) { |
527 // RLE inputs may skip pixels, leaving them as transparent. Thi s | 547 // 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 | 548 // is uncommon, but we cannot be certain that an RLE bmp will be |
529 // opaque. | 549 // opaque or that we will be able to represent it with a palette . |
530 const SkImageInfo imageInfo = SkImageInfo::Make(width, height, k N32_SkColorType, | 550 // For that reason, we always indicate that we are kBGRA. |
531 kUnpremul_SkAlphaType); | 551 const SkEncodedInfo info = SkEncodedInfo::Make(width, height, |
532 *codecOut = new SkBmpRLECodec(imageInfo, stream, bitsPerPixel, n umColors, | 552 SkEncodedInfo::kBGRA_Color, SkEncodedInfo::kBinary_Alpha , 8); |
553 *codecOut = new SkBmpRLECodec(info, stream, bitsPerPixel, numCol ors, | |
533 bytesPerColor, offset - bytesRead, rowOrder, RLEBytes); | 554 bytesPerColor, offset - bytesRead, rowOrder, RLEBytes); |
534 } | 555 } |
535 return true; | 556 return true; |
536 } | 557 } |
537 default: | 558 default: |
538 SkASSERT(false); | 559 SkASSERT(false); |
539 return false; | 560 return false; |
540 } | 561 } |
541 } | 562 } |
542 | 563 |
543 /* | 564 /* |
544 * Creates a bmp decoder | 565 * Creates a bmp decoder |
545 * Reads enough of the stream to determine the image format | 566 * Reads enough of the stream to determine the image format |
546 */ | 567 */ |
547 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) { | 568 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool inIco) { |
548 SkAutoTDelete<SkStream> streamDeleter(stream); | 569 SkAutoTDelete<SkStream> streamDeleter(stream); |
549 SkCodec* codec = nullptr; | 570 SkCodec* codec = nullptr; |
550 if (ReadHeader(stream, inIco, &codec)) { | 571 if (ReadHeader(stream, inIco, &codec)) { |
551 // codec has taken ownership of stream, so we do not need to | 572 // codec has taken ownership of stream, so we do not need to |
552 // delete it. | 573 // delete it. |
553 SkASSERT(codec); | 574 SkASSERT(codec); |
554 streamDeleter.release(); | 575 streamDeleter.release(); |
555 return codec; | 576 return codec; |
556 } | 577 } |
557 return nullptr; | 578 return nullptr; |
558 } | 579 } |
559 | 580 |
560 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, | 581 SkBmpCodec::SkBmpCodec(const SkEncodedInfo& info, SkStream* stream, |
561 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder) | 582 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder) |
562 : INHERITED(info, stream) | 583 : INHERITED(info, stream) |
563 , fBitsPerPixel(bitsPerPixel) | 584 , fBitsPerPixel(bitsPerPixel) |
564 , fRowOrder(rowOrder) | 585 , fRowOrder(rowOrder) |
565 , fSrcRowBytes(SkAlign4(compute_row_bytes(info.width(), fBitsPerPixel))) | 586 , fSrcRowBytes(SkAlign4(compute_row_bytes(info.width(), fBitsPerPixel))) |
566 {} | 587 {} |
567 | 588 |
568 bool SkBmpCodec::onRewind() { | 589 bool SkBmpCodec::onRewind() { |
569 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr); | 590 return SkBmpCodec::ReadHeader(this->stream(), this->inIco(), nullptr); |
570 } | 591 } |
(...skipping 25 matching lines...) Expand all Loading... | |
596 } | 617 } |
597 | 618 |
598 bool SkBmpCodec::skipRows(int count) { | 619 bool SkBmpCodec::skipRows(int count) { |
599 const size_t bytesToSkip = count * fSrcRowBytes; | 620 const size_t bytesToSkip = count * fSrcRowBytes; |
600 return this->stream()->skip(bytesToSkip) == bytesToSkip; | 621 return this->stream()->skip(bytesToSkip) == bytesToSkip; |
601 } | 622 } |
602 | 623 |
603 bool SkBmpCodec::onSkipScanlines(int count) { | 624 bool SkBmpCodec::onSkipScanlines(int count) { |
604 return this->skipRows(count); | 625 return this->skipRows(count); |
605 } | 626 } |
OLD | NEW |