Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(826)

Side by Side Diff: Source/platform/image-decoders/bmp/BMPImageReader.cpp

Issue 1259083003: Do not consolidate data in BMPImageDecoder (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@SegmentedBuffer
Patch Set: Make FastSharedBufferReader a member Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698