| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 1
59, | 59 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 1
59, |
| 60 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 1
91, | 60 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 1
91, |
| 61 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 2
23, | 61 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 2
23, |
| 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 WebCore { | 67 namespace WebCore { |
| 68 | 68 |
| 69 BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffs
et, size_t imgDataOffset, bool usesAndMask) | 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_decodedOffset(decodedAndHeaderOffset) | 72 , m_decodedOffset(decodedAndHeaderOffset) |
| 73 , m_headerOffset(decodedAndHeaderOffset) | 73 , m_headerOffset(decodedAndHeaderOffset) |
| 74 , m_imgDataOffset(imgDataOffset) | 74 , m_imgDataOffset(imgDataOffset) |
| 75 , m_isOS21x(false) | 75 , m_isOS21x(false) |
| 76 , m_isOS22x(false) | 76 , m_isOS22x(false) |
| 77 , m_isTopDown(false) | 77 , m_isTopDown(false) |
| 78 , m_needToProcessBitmasks(false) | 78 , m_needToProcessBitmasks(false) |
| 79 , m_needToProcessColorTable(false) | 79 , m_needToProcessColorTable(false) |
| 80 , m_seenNonZeroAlphaPixel(false) | 80 , m_seenNonZeroAlphaPixel(false) |
| 81 , m_seenZeroAlphaPixel(false) | 81 , m_seenZeroAlphaPixel(false) |
| 82 , m_andMaskState(usesAndMask ? NotYetDecoded : None) | 82 , m_isInICO(isInICO) |
| 83 , m_decodingAndMask(false) |
| 83 { | 84 { |
| 84 // Clue-in decodeBMP() that we need to detect the correct info header size. | 85 // Clue-in decodeBMP() that we need to detect the correct info header size. |
| 85 memset(&m_infoHeader, 0, sizeof(m_infoHeader)); | 86 memset(&m_infoHeader, 0, sizeof(m_infoHeader)); |
| 86 } | 87 } |
| 87 | 88 |
| 88 bool BMPImageReader::decodeBMP(bool onlySize) | 89 bool BMPImageReader::decodeBMP(bool onlySize) |
| 89 { | 90 { |
| 90 // Calculate size of info header. | 91 // Calculate size of info header. |
| 91 if (!m_infoHeader.biSize && !readInfoHeaderSize()) | 92 if (!m_infoHeader.biSize && !readInfoHeaderSize()) |
| 92 return false; | 93 return false; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 119 m_buffer->setHasAlpha(false); | 120 m_buffer->setHasAlpha(false); |
| 120 | 121 |
| 121 // For BMPs, the frame always fills the entire image. | 122 // For BMPs, the frame always fills the entire image. |
| 122 m_buffer->setOriginalFrameRect(IntRect(IntPoint(), m_parent->size())); | 123 m_buffer->setOriginalFrameRect(IntRect(IntPoint(), m_parent->size())); |
| 123 | 124 |
| 124 if (!m_isTopDown) | 125 if (!m_isTopDown) |
| 125 m_coord.setY(m_parent->size().height() - 1); | 126 m_coord.setY(m_parent->size().height() - 1); |
| 126 } | 127 } |
| 127 | 128 |
| 128 // Decode the data. | 129 // Decode the data. |
| 129 if ((m_andMaskState != Decoding) && !pastEndOfImage(0)) { | 130 if (!m_decodingAndMask && !pastEndOfImage(0)) { |
| 130 if ((m_infoHeader.biCompression != RLE4) && (m_infoHeader.biCompression
!= RLE8) && (m_infoHeader.biCompression != RLE24)) { | 131 if ((m_infoHeader.biCompression != RLE4) && (m_infoHeader.biCompression
!= RLE8) && (m_infoHeader.biCompression != RLE24)) { |
| 131 const ProcessingResult result = processNonRLEData(false, 0); | 132 const ProcessingResult result = processNonRLEData(false, 0); |
| 132 if (result != Success) | 133 if (result != Success) |
| 133 return (result == Failure) ? m_parent->setFailed() : false; | 134 return (result == Failure) ? m_parent->setFailed() : false; |
| 134 } else if (!processRLEData()) | 135 } else if (!processRLEData()) |
| 135 return false; | 136 return false; |
| 136 } | 137 } |
| 137 | 138 |
| 138 // If the image has an AND mask and there was no alpha data, process the | 139 // If the image has an AND mask and there was no alpha data, process the |
| 139 // mask. | 140 // mask. |
| 140 if ((m_andMaskState == NotYetDecoded) && !m_buffer->hasAlpha()) { | 141 if (m_isInICO && !m_decodingAndMask && !m_buffer->hasAlpha()) { |
| 141 // Reset decoding coordinates to start of image. | 142 // Reset decoding coordinates to start of image. |
| 142 m_coord.setX(0); | 143 m_coord.setX(0); |
| 143 m_coord.setY(m_isTopDown ? 0 : (m_parent->size().height() - 1)); | 144 m_coord.setY(m_isTopDown ? 0 : (m_parent->size().height() - 1)); |
| 144 | 145 |
| 145 // The AND mask is stored as 1-bit data. | 146 // The AND mask is stored as 1-bit data. |
| 146 m_infoHeader.biBitCount = 1; | 147 m_infoHeader.biBitCount = 1; |
| 147 | 148 |
| 148 m_andMaskState = Decoding; | 149 m_decodingAndMask = true; |
| 149 } | 150 } |
| 150 if (m_andMaskState == Decoding) { | 151 if (m_decodingAndMask) { |
| 151 const ProcessingResult result = processNonRLEData(false, 0); | 152 const ProcessingResult result = processNonRLEData(false, 0); |
| 152 if (result != Success) | 153 if (result != Success) |
| 153 return (result == Failure) ? m_parent->setFailed() : false; | 154 return (result == Failure) ? m_parent->setFailed() : false; |
| 154 } | 155 } |
| 155 | 156 |
| 156 // Done! | 157 // Done! |
| 157 m_buffer->setStatus(ImageFrame::FrameComplete); | 158 m_buffer->setStatus(ImageFrame::FrameComplete); |
| 158 return true; | 159 return true; |
| 159 } | 160 } |
| 160 | 161 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 | 235 |
| 235 bool BMPImageReader::readInfoHeader() | 236 bool BMPImageReader::readInfoHeader() |
| 236 { | 237 { |
| 237 // Pre-initialize some fields that not all headers set. | 238 // Pre-initialize some fields that not all headers set. |
| 238 m_infoHeader.biCompression = RGB; | 239 m_infoHeader.biCompression = RGB; |
| 239 m_infoHeader.biClrUsed = 0; | 240 m_infoHeader.biClrUsed = 0; |
| 240 | 241 |
| 241 if (m_isOS21x) { | 242 if (m_isOS21x) { |
| 242 m_infoHeader.biWidth = readUint16(4); | 243 m_infoHeader.biWidth = readUint16(4); |
| 243 m_infoHeader.biHeight = readUint16(6); | 244 m_infoHeader.biHeight = readUint16(6); |
| 244 ASSERT(m_andMaskState == None); // ICO is a Windows format, not OS/2! | 245 ASSERT(!m_isInICO); // ICO is a Windows format, not OS/2! |
| 245 m_infoHeader.biBitCount = readUint16(10); | 246 m_infoHeader.biBitCount = readUint16(10); |
| 246 return true; | 247 return true; |
| 247 } | 248 } |
| 248 | 249 |
| 249 m_infoHeader.biWidth = readUint32(4); | 250 m_infoHeader.biWidth = readUint32(4); |
| 250 m_infoHeader.biHeight = readUint32(8); | 251 m_infoHeader.biHeight = readUint32(8); |
| 251 if (m_andMaskState != None) | 252 if (m_isInICO) |
| 252 m_infoHeader.biHeight /= 2; | 253 m_infoHeader.biHeight /= 2; |
| 253 m_infoHeader.biBitCount = readUint16(14); | 254 m_infoHeader.biBitCount = readUint16(14); |
| 254 | 255 |
| 255 // Read compression type, if present. | 256 // Read compression type, if present. |
| 256 if (m_infoHeader.biSize >= 20) { | 257 if (m_infoHeader.biSize >= 20) { |
| 257 uint32_t biCompression = readUint32(16); | 258 uint32_t biCompression = readUint32(16); |
| 258 | 259 |
| 259 // Detect OS/2 2.x-specific compression types. | 260 // Detect OS/2 2.x-specific compression types. |
| 260 if ((biCompression == 3) && (m_infoHeader.biBitCount == 1)) { | 261 if ((biCompression == 3) && (m_infoHeader.biBitCount == 1)) { |
| 261 m_infoHeader.biCompression = HUFFMAN1D; | 262 m_infoHeader.biCompression = HUFFMAN1D; |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 } | 434 } |
| 434 | 435 |
| 435 // Alpha is a poorly-documented and inconsistently-used feature. | 436 // Alpha is a poorly-documented and inconsistently-used feature. |
| 436 // | 437 // |
| 437 // Windows V4+ has an alpha bitmask in the info header. Unlike the R/G/B | 438 // Windows V4+ has an alpha bitmask in the info header. Unlike the R/G/B |
| 438 // bitmasks, the MSDN docs don't indicate that it is only valid for the | 439 // bitmasks, the MSDN docs don't indicate that it is only valid for the |
| 439 // BITFIELDS compression format, so we respect it at all times. | 440 // BITFIELDS compression format, so we respect it at all times. |
| 440 // | 441 // |
| 441 // To complicate things, Windows V3 BMPs, which lack this mask, can specify | 442 // To complicate things, Windows V3 BMPs, which lack this mask, can specify |
| 442 // 32bpp format, which to any sane reader would imply an 8-bit alpha | 443 // 32bpp format, which to any sane reader would imply an 8-bit alpha |
| 443 // channel -- and indeed, there exist BMPs in this format which clearly | 444 // channel -- and for BMPs-in-ICOs, that's precisely what's intended to |
| 445 // happen. There also exist standalone BMPs in this format which clearly |
| 444 // expect the alpha channel to be respected. However, there are many other | 446 // expect the alpha channel to be respected. However, there are many other |
| 445 // BMPs which, for example, fill this channel with all 0s, yet clearly | 447 // BMPs which, for example, fill this channel with all 0s, yet clearly |
| 446 // expect to not be displayed as a fully-transparent rectangle. | 448 // expect to not be displayed as a fully-transparent rectangle. |
| 447 // | 449 // |
| 448 // If these were the only two types of Windows V3, 32bpp BMPs in the wild, | 450 // If these were the only two types of Windows V3, 32bpp BMPs in the wild, |
| 449 // we could distinguish between them by scanning the alpha channel in the | 451 // we could distinguish between them by scanning the alpha channel in the |
| 450 // image, looking for nonzero values, and only enabling alpha if we found | 452 // image, looking for nonzero values, and only enabling alpha if we found |
| 451 // some. (It turns out we have to do this anyway, because, crazily, there | 453 // some. (It turns out we have to do this anyway, because, crazily, there |
| 452 // are also Windows V4+ BMPs with an explicit, non-zero alpha mask, which | 454 // are also Windows V4+ BMPs with an explicit, non-zero alpha mask, which |
| 453 // then zero-fill their alpha channels! See comments in | 455 // then zero-fill their alpha channels! See comments in |
| 454 // processNonRLEData().) | 456 // processNonRLEData().) |
| 455 // | 457 // |
| 456 // Unfortunately there are also V3 BMPs -- indeed, probably more than the | 458 // Unfortunately there are also V3 BMPs -- indeed, probably more than the |
| 457 // number of 32bpp, V3 BMPs which intentionally use alpha -- which specify | 459 // number of 32bpp, V3 BMPs which intentionally use alpha -- which specify |
| 458 // 32bpp format, use nonzero (and non-255) alpha values, and yet expect to | 460 // 32bpp format, use nonzero (and non-255) alpha values, and yet expect to |
| 459 // be rendered fully-opaque. And other browsers do so. | 461 // be rendered fully-opaque. And other browsers do so. |
| 460 // | 462 // |
| 461 // So it's impossible to display every BMP in the way its creators intended, | 463 // So it's impossible to display every BMP in the way its creators intended, |
| 462 // and we have to choose what to break. Given the paragraph above, we match | 464 // and we have to choose what to break. Given the paragraph above, we match |
| 463 // other browsers and ignore alpha in Windows V3 BMPs. | 465 // other browsers and ignore alpha in Windows V3 BMPs except inside ICO |
| 466 // files. |
| 464 if (!isWindowsV4Plus()) | 467 if (!isWindowsV4Plus()) |
| 465 m_bitMasks[3] = 0; | 468 m_bitMasks[3] = (m_isInICO && (m_infoHeader.biCompression != BITFIELDS)
&& (m_infoHeader.biBitCount == 32)) ? static_cast<uint32_t>(0xff000000) : 0; |
| 466 | 469 |
| 467 // We've now decoded all the non-image data we care about. Skip anything | 470 // We've now decoded all the non-image data we care about. Skip anything |
| 468 // else before the actual raster data. | 471 // else before the actual raster data. |
| 469 if (m_imgDataOffset) | 472 if (m_imgDataOffset) |
| 470 m_decodedOffset = m_imgDataOffset; | 473 m_decodedOffset = m_imgDataOffset; |
| 471 m_needToProcessBitmasks = false; | 474 m_needToProcessBitmasks = false; |
| 472 | 475 |
| 473 // Check masks and set shift and LUT address values. | 476 // Check masks and set shift and LUT address values. |
| 474 for (int i = 0; i < 4; ++i) { | 477 for (int i = 0; i < 4; ++i) { |
| 475 // Trim the mask to the allowed bit depth. Some Windows V4+ BMPs | 478 // Trim the mask to the allowed bit depth. Some Windows V4+ BMPs |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 | 722 |
| 720 if (m_infoHeader.biBitCount < 16) { | 723 if (m_infoHeader.biBitCount < 16) { |
| 721 // Paletted data. Pixels are stored little-endian within bytes. | 724 // Paletted data. Pixels are stored little-endian within bytes. |
| 722 // Decode pixels one byte at a time, left to right (so, starting at | 725 // Decode pixels one byte at a time, left to right (so, starting at |
| 723 // the most significant bits in the byte). | 726 // the most significant bits in the byte). |
| 724 const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1; | 727 const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1; |
| 725 for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) { | 728 for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) { |
| 726 uint8_t pixelData = m_data->data()[m_decodedOffset + byte]; | 729 uint8_t pixelData = m_data->data()[m_decodedOffset + byte]; |
| 727 for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() <
endX); ++pixel) { | 730 for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() <
endX); ++pixel) { |
| 728 const size_t colorIndex = (pixelData >> (8 - m_infoHeader.bi
BitCount)) & mask; | 731 const size_t colorIndex = (pixelData >> (8 - m_infoHeader.bi
BitCount)) & mask; |
| 729 if (m_andMaskState == Decoding) { | 732 if (m_decodingAndMask) { |
| 730 // There's no way to accurately represent an AND + XOR | 733 // There's no way to accurately represent an AND + XOR |
| 731 // operation as an RGBA image, so where the AND values | 734 // operation as an RGBA image, so where the AND values |
| 732 // are 1, we simply set the framebuffer pixels to fully | 735 // are 1, we simply set the framebuffer pixels to fully |
| 733 // transparent, on the assumption that most ICOs on the | 736 // transparent, on the assumption that most ICOs on the |
| 734 // web will not be doing a lot of inverting. | 737 // web will not be doing a lot of inverting. |
| 735 if (colorIndex) { | 738 if (colorIndex) { |
| 736 setRGBA(0, 0, 0, 0); | 739 setRGBA(0, 0, 0, 0); |
| 737 m_buffer->setHasAlpha(true); | 740 m_buffer->setHasAlpha(true); |
| 738 } else | 741 } else |
| 739 m_coord.move(1, 0); | 742 m_coord.move(1, 0); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 // Finished decoding whole image. | 792 // Finished decoding whole image. |
| 790 return Success; | 793 return Success; |
| 791 } | 794 } |
| 792 | 795 |
| 793 void BMPImageReader::moveBufferToNextRow() | 796 void BMPImageReader::moveBufferToNextRow() |
| 794 { | 797 { |
| 795 m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); | 798 m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); |
| 796 } | 799 } |
| 797 | 800 |
| 798 } // namespace WebCore | 801 } // namespace WebCore |
| OLD | NEW |