OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. | 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 2 55, | 62 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 2 55, |
63 }; | 63 }; |
64 | 64 |
65 } | 65 } |
66 | 66 |
67 namespace blink { | 67 namespace blink { |
68 | 68 |
69 BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffs et, size_t imgDataOffset, bool isInICO) | 69 BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffs et, size_t imgDataOffset, bool isInICO) |
70 : m_parent(parent) | 70 : m_parent(parent) |
71 , m_buffer(0) | 71 , m_buffer(0) |
72 , m_fastReader(nullptr) | |
72 , m_decodedOffset(decodedAndHeaderOffset) | 73 , m_decodedOffset(decodedAndHeaderOffset) |
73 , m_headerOffset(decodedAndHeaderOffset) | 74 , m_headerOffset(decodedAndHeaderOffset) |
74 , m_imgDataOffset(imgDataOffset) | 75 , m_imgDataOffset(imgDataOffset) |
75 , m_isOS21x(false) | 76 , m_isOS21x(false) |
76 , m_isOS22x(false) | 77 , m_isOS22x(false) |
77 , m_isTopDown(false) | 78 , m_isTopDown(false) |
78 , m_needToProcessBitmasks(false) | 79 , m_needToProcessBitmasks(false) |
79 , m_needToProcessColorTable(false) | 80 , m_needToProcessColorTable(false) |
80 , m_seenNonZeroAlphaPixel(false) | 81 , m_seenNonZeroAlphaPixel(false) |
81 , m_seenZeroAlphaPixel(false) | 82 , m_seenZeroAlphaPixel(false) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 m_buffer->setPixelsChanged(true); | 160 m_buffer->setPixelsChanged(true); |
160 return (result == Failure) ? m_parent->setFailed() : (result == Success); | 161 return (result == Failure) ? m_parent->setFailed() : (result == Success); |
161 } | 162 } |
162 | 163 |
163 bool BMPImageReader::readInfoHeaderSize() | 164 bool BMPImageReader::readInfoHeaderSize() |
164 { | 165 { |
165 // Get size of info header. | 166 // Get size of info header. |
166 ASSERT(m_decodedOffset == m_headerOffset); | 167 ASSERT(m_decodedOffset == m_headerOffset); |
167 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < 4)) | 168 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < 4)) |
168 return false; | 169 return false; |
170 | |
169 m_infoHeader.biSize = readUint32(0); | 171 m_infoHeader.biSize = readUint32(0); |
170 // Don't increment m_decodedOffset here, it just makes the code in | 172 // Don't increment m_decodedOffset here, it just makes the code in |
171 // processInfoHeader() more confusing. | 173 // processInfoHeader() more confusing. |
172 | 174 |
173 // Don't allow the header to overflow (which would be harmless here, but | 175 // Don't allow the header to overflow (which would be harmless here, but |
174 // problematic or at least confusing in other places), or to overrun the | 176 // problematic or at least confusing in other places), or to overrun the |
175 // image data. | 177 // image data. |
176 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; | 178 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; |
177 if ((headerEnd < m_headerOffset) || (m_imgDataOffset && (m_imgDataOffset < h eaderEnd))) | 179 if ((headerEnd < m_headerOffset) || (m_imgDataOffset && (m_imgDataOffset < h eaderEnd))) |
178 return m_parent->setFailed(); | 180 return m_parent->setFailed(); |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 // Fail if we don't have enough file space for the bitmasks. | 425 // Fail if we don't have enough file space for the bitmasks. |
424 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; | 426 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; |
425 const size_t bitmasksSize = 12; | 427 const size_t bitmasksSize = 12; |
426 const size_t bitmasksEnd = headerEnd + bitmasksSize; | 428 const size_t bitmasksEnd = headerEnd + bitmasksSize; |
427 if ((bitmasksEnd < headerEnd) || (m_imgDataOffset && (m_imgDataOffset < bitmasksEnd))) | 429 if ((bitmasksEnd < headerEnd) || (m_imgDataOffset && (m_imgDataOffset < bitmasksEnd))) |
428 return m_parent->setFailed(); | 430 return m_parent->setFailed(); |
429 | 431 |
430 // Read bitmasks. | 432 // Read bitmasks. |
431 if ((m_data->size() - m_decodedOffset) < bitmasksSize) | 433 if ((m_data->size() - m_decodedOffset) < bitmasksSize) |
432 return false; | 434 return false; |
435 | |
Peter Kasting
2015/09/02 22:08:54
Nit: I wouldn't add this blank line
scroggo_chromium
2015/09/02 23:01:07
Done.
| |
433 m_bitMasks[0] = readUint32(0); | 436 m_bitMasks[0] = readUint32(0); |
434 m_bitMasks[1] = readUint32(4); | 437 m_bitMasks[1] = readUint32(4); |
435 m_bitMasks[2] = readUint32(8); | 438 m_bitMasks[2] = readUint32(8); |
436 | 439 |
437 m_decodedOffset += bitmasksSize; | 440 m_decodedOffset += bitmasksSize; |
438 } | 441 } |
439 | 442 |
440 // Alpha is a poorly-documented and inconsistently-used feature. | 443 // Alpha is a poorly-documented and inconsistently-used feature. |
441 // | 444 // |
442 // Windows V4+ has an alpha bitmask in the info header. Unlike the R/G/B | 445 // Windows V4+ has an alpha bitmask in the info header. Unlike the R/G/B |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
535 const size_t tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4) ; | 538 const size_t tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4) ; |
536 const size_t tableEnd = headerEnd + tableSizeInBytes; | 539 const size_t tableEnd = headerEnd + tableSizeInBytes; |
537 if ((tableEnd < headerEnd) || (m_imgDataOffset && (m_imgDataOffset < tableEn d))) | 540 if ((tableEnd < headerEnd) || (m_imgDataOffset && (m_imgDataOffset < tableEn d))) |
538 return m_parent->setFailed(); | 541 return m_parent->setFailed(); |
539 | 542 |
540 // Read color table. | 543 // Read color table. |
541 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < tableSizeInBytes)) | 544 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < tableSizeInBytes)) |
542 return false; | 545 return false; |
543 m_colorTable.resize(m_infoHeader.biClrUsed); | 546 m_colorTable.resize(m_infoHeader.biClrUsed); |
544 for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) { | 547 for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) { |
545 m_colorTable[i].rgbBlue = m_data->data()[m_decodedOffset++]; | 548 m_colorTable[i].rgbBlue = getByte(m_decodedOffset++); |
546 m_colorTable[i].rgbGreen = m_data->data()[m_decodedOffset++]; | 549 m_colorTable[i].rgbGreen = getByte(m_decodedOffset++); |
547 m_colorTable[i].rgbRed = m_data->data()[m_decodedOffset++]; | 550 m_colorTable[i].rgbRed = getByte(m_decodedOffset++); |
548 // Skip padding byte (not present on OS/2 1.x). | 551 // Skip padding byte (not present on OS/2 1.x). |
549 if (!m_isOS21x) | 552 if (!m_isOS21x) |
550 ++m_decodedOffset; | 553 ++m_decodedOffset; |
551 } | 554 } |
552 | 555 |
553 // We've now decoded all the non-image data we care about. Skip anything | 556 // We've now decoded all the non-image data we care about. Skip anything |
554 // else before the actual raster data. | 557 // else before the actual raster data. |
555 if (m_imgDataOffset) | 558 if (m_imgDataOffset) |
556 m_decodedOffset = m_imgDataOffset; | 559 m_decodedOffset = m_imgDataOffset; |
557 m_needToProcessColorTable = false; | 560 m_needToProcessColorTable = false; |
(...skipping 29 matching lines...) Expand all Loading... | |
587 // Impossible to decode row-at-a-time, so just do things as a stream of | 590 // Impossible to decode row-at-a-time, so just do things as a stream of |
588 // bytes. | 591 // bytes. |
589 while (true) { | 592 while (true) { |
590 // Every entry takes at least two bytes; bail if there isn't enough | 593 // Every entry takes at least two bytes; bail if there isn't enough |
591 // data. | 594 // data. |
592 if ((m_data->size() - m_decodedOffset) < 2) | 595 if ((m_data->size() - m_decodedOffset) < 2) |
593 return InsufficientData; | 596 return InsufficientData; |
594 | 597 |
595 // For every entry except EOF, we'd better not have reached the end of | 598 // For every entry except EOF, we'd better not have reached the end of |
596 // the image. | 599 // the image. |
597 const uint8_t count = m_data->data()[m_decodedOffset]; | 600 const uint8_t count = getByte(m_decodedOffset); |
598 const uint8_t code = m_data->data()[m_decodedOffset + 1]; | 601 const uint8_t code = getByte(m_decodedOffset + 1); |
599 if ((count || (code != 1)) && pastEndOfImage(0)) | 602 if ((count || (code != 1)) && pastEndOfImage(0)) |
600 return Failure; | 603 return Failure; |
601 | 604 |
602 // Decode. | 605 // Decode. |
603 if (!count) { | 606 if (!count) { |
604 switch (code) { | 607 switch (code) { |
605 case 0: // Magic token: EOL | 608 case 0: // Magic token: EOL |
606 // Skip any remaining pixels in this row. | 609 // Skip any remaining pixels in this row. |
607 if (m_coord.x() < m_parent->size().width()) | 610 if (m_coord.x() < m_parent->size().width()) |
608 m_buffer->setHasAlpha(true); | 611 m_buffer->setHasAlpha(true); |
(...skipping 13 matching lines...) Expand all Loading... | |
622 return Success; | 625 return Success; |
623 | 626 |
624 case 2: { // Magic token: Delta | 627 case 2: { // Magic token: Delta |
625 // The next two bytes specify dx and dy. Bail if there isn't | 628 // The next two bytes specify dx and dy. Bail if there isn't |
626 // enough data. | 629 // enough data. |
627 if ((m_data->size() - m_decodedOffset) < 4) | 630 if ((m_data->size() - m_decodedOffset) < 4) |
628 return InsufficientData; | 631 return InsufficientData; |
629 | 632 |
630 // Fail if this takes us past the end of the desired row or | 633 // Fail if this takes us past the end of the desired row or |
631 // past the end of the image. | 634 // past the end of the image. |
632 const uint8_t dx = m_data->data()[m_decodedOffset + 2]; | 635 const uint8_t dx = getByte(m_decodedOffset + 2); |
633 const uint8_t dy = m_data->data()[m_decodedOffset + 3]; | 636 const uint8_t dy = getByte(m_decodedOffset + 3); |
634 if (dx || dy) | 637 if (dx || dy) |
635 m_buffer->setHasAlpha(true); | 638 m_buffer->setHasAlpha(true); |
636 if (((m_coord.x() + dx) > m_parent->size().width()) || pastEndOf Image(dy)) | 639 if (((m_coord.x() + dx) > m_parent->size().width()) || pastEndOf Image(dy)) |
637 return Failure; | 640 return Failure; |
638 | 641 |
639 // Skip intervening pixels. | 642 // Skip intervening pixels. |
640 m_coord.move(dx, m_isTopDown ? dy : -dy); | 643 m_coord.move(dx, m_isTopDown ? dy : -dy); |
641 | 644 |
642 m_decodedOffset += 4; | 645 m_decodedOffset += 4; |
643 break; | 646 break; |
(...skipping 19 matching lines...) Expand all Loading... | |
663 // Strangely, some BMPs seem to specify excessively large counts | 666 // Strangely, some BMPs seem to specify excessively large counts |
664 // here; ignore pixels past the end of the row. | 667 // here; ignore pixels past the end of the row. |
665 const int endX = std::min(m_coord.x() + count, m_parent->size().widt h()); | 668 const int endX = std::min(m_coord.x() + count, m_parent->size().widt h()); |
666 | 669 |
667 if (m_infoHeader.biCompression == RLE24) { | 670 if (m_infoHeader.biCompression == RLE24) { |
668 // Bail if there isn't enough data. | 671 // Bail if there isn't enough data. |
669 if ((m_data->size() - m_decodedOffset) < 4) | 672 if ((m_data->size() - m_decodedOffset) < 4) |
670 return InsufficientData; | 673 return InsufficientData; |
671 | 674 |
672 // One BGR triple that we copy |count| times. | 675 // One BGR triple that we copy |count| times. |
673 fillRGBA(endX, m_data->data()[m_decodedOffset + 3], m_data->data ()[m_decodedOffset + 2], code, 0xff); | 676 fillRGBA(endX, getByte(m_decodedOffset + 3), getByte(m_decodedOf fset + 2), code, 0xff); |
674 m_decodedOffset += 4; | 677 m_decodedOffset += 4; |
675 } else { | 678 } else { |
676 // RLE8 has one color index that gets repeated; RLE4 has two | 679 // RLE8 has one color index that gets repeated; RLE4 has two |
677 // color indexes in the upper and lower 4 bits of the byte, | 680 // color indexes in the upper and lower 4 bits of the byte, |
678 // which are alternated. | 681 // which are alternated. |
679 size_t colorIndexes[2] = {code, code}; | 682 size_t colorIndexes[2] = {code, code}; |
680 if (m_infoHeader.biCompression == RLE4) { | 683 if (m_infoHeader.biCompression == RLE4) { |
681 colorIndexes[0] = (colorIndexes[0] >> 4) & 0xf; | 684 colorIndexes[0] = (colorIndexes[0] >> 4) & 0xf; |
682 colorIndexes[1] &= 0xf; | 685 colorIndexes[1] &= 0xf; |
683 } | 686 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 // Bail if we don't have enough data for the desired number of pixels. | 729 // Bail if we don't have enough data for the desired number of pixels. |
727 if ((m_data->size() - m_decodedOffset) < paddedNumBytes) | 730 if ((m_data->size() - m_decodedOffset) < paddedNumBytes) |
728 return InsufficientData; | 731 return InsufficientData; |
729 | 732 |
730 if (m_infoHeader.biBitCount < 16) { | 733 if (m_infoHeader.biBitCount < 16) { |
731 // Paletted data. Pixels are stored little-endian within bytes. | 734 // Paletted data. Pixels are stored little-endian within bytes. |
732 // Decode pixels one byte at a time, left to right (so, starting at | 735 // Decode pixels one byte at a time, left to right (so, starting at |
733 // the most significant bits in the byte). | 736 // the most significant bits in the byte). |
734 const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1; | 737 const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1; |
735 for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) { | 738 for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) { |
736 uint8_t pixelData = m_data->data()[m_decodedOffset + byte]; | 739 uint8_t pixelData = getByte(m_decodedOffset + byte); |
737 for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) { | 740 for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) { |
738 const size_t colorIndex = (pixelData >> (8 - m_infoHeader.bi BitCount)) & mask; | 741 const size_t colorIndex = (pixelData >> (8 - m_infoHeader.bi BitCount)) & mask; |
739 if (m_decodingAndMask) { | 742 if (m_decodingAndMask) { |
740 // There's no way to accurately represent an AND + XOR | 743 // There's no way to accurately represent an AND + XOR |
741 // operation as an RGBA image, so where the AND values | 744 // operation as an RGBA image, so where the AND values |
742 // are 1, we simply set the framebuffer pixels to fully | 745 // are 1, we simply set the framebuffer pixels to fully |
743 // transparent, on the assumption that most ICOs on the | 746 // transparent, on the assumption that most ICOs on the |
744 // web will not be doing a lot of inverting. | 747 // web will not be doing a lot of inverting. |
745 if (colorIndex) { | 748 if (colorIndex) { |
746 setRGBA(0, 0, 0, 0); | 749 setRGBA(0, 0, 0, 0); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
799 // Finished decoding whole image. | 802 // Finished decoding whole image. |
800 return Success; | 803 return Success; |
801 } | 804 } |
802 | 805 |
803 void BMPImageReader::moveBufferToNextRow() | 806 void BMPImageReader::moveBufferToNextRow() |
804 { | 807 { |
805 m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); | 808 m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); |
806 } | 809 } |
807 | 810 |
808 } // namespace blink | 811 } // namespace blink |
OLD | NEW |