Chromium Code Reviews| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 // Clue-in decodeBMP() that we need to detect the correct info header size. | 88 // Clue-in decodeBMP() that we need to detect the correct info header size. |
| 89 memset(&m_infoHeader, 0, sizeof(m_infoHeader)); | 89 memset(&m_infoHeader, 0, sizeof(m_infoHeader)); |
| 90 } | 90 } |
| 91 | 91 |
| 92 bool BMPImageReader::decodeBMP(bool onlySize) | 92 bool BMPImageReader::decodeBMP(bool onlySize) |
| 93 { | 93 { |
| 94 // Calculate size of info header. | 94 // Calculate size of info header. |
| 95 if (!m_infoHeader.biSize && !readInfoHeaderSize()) | 95 if (!m_infoHeader.biSize && !readInfoHeaderSize()) |
| 96 return false; | 96 return false; |
| 97 | 97 |
| 98 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; | |
| 98 // Read and process info header. | 99 // Read and process info header. |
| 99 if ((m_decodedOffset < (m_headerOffset + m_infoHeader.biSize)) && !processIn foHeader()) | 100 if ((m_decodedOffset < headerEnd) && !processInfoHeader()) |
| 100 return false; | 101 return false; |
| 101 | 102 |
| 102 // processInfoHeader() set the size, so if that's all we needed, we're done. | 103 // processInfoHeader() set the size, so if that's all we needed, we're done. |
| 103 if (onlySize) | 104 if (onlySize) |
| 104 return true; | 105 return true; |
| 105 | 106 |
| 106 // Read and process the bitmasks, if needed. | 107 // Read and process the bitmasks, if needed. |
| 107 if (m_needToProcessBitmasks && !processBitmasks()) | 108 if (m_needToProcessBitmasks && !processBitmasks()) |
| 108 return false; | 109 return false; |
| 109 | 110 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 ASSERT(m_decodedOffset == m_headerOffset); | 169 ASSERT(m_decodedOffset == m_headerOffset); |
| 169 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < 4)) | 170 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < 4)) |
| 170 return false; | 171 return false; |
| 171 m_infoHeader.biSize = readUint32(0); | 172 m_infoHeader.biSize = readUint32(0); |
| 172 // Don't increment m_decodedOffset here, it just makes the code in | 173 // Don't increment m_decodedOffset here, it just makes the code in |
| 173 // processInfoHeader() more confusing. | 174 // processInfoHeader() more confusing. |
| 174 | 175 |
| 175 // Don't allow the header to overflow (which would be harmless here, but | 176 // Don't allow the header to overflow (which would be harmless here, but |
| 176 // problematic or at least confusing in other places), or to overrun the | 177 // problematic or at least confusing in other places), or to overrun the |
| 177 // image data. | 178 // image data. |
| 178 if (((m_headerOffset + m_infoHeader.biSize) < m_headerOffset) || (m_imgDataO ffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize)))) | 179 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; |
| 180 if ((headerEnd < m_headerOffset) || (m_imgDataOffset && (m_imgDataOffset < h eaderEnd))) | |
| 179 return m_parent->setFailed(); | 181 return m_parent->setFailed(); |
| 180 | 182 |
| 181 // See if this is a header size we understand: | 183 // See if this is a header size we understand: |
| 182 // OS/2 1.x: 12 | 184 // OS/2 1.x: 12 |
| 183 if (m_infoHeader.biSize == 12) | 185 if (m_infoHeader.biSize == 12) |
| 184 m_isOS21x = true; | 186 m_isOS21x = true; |
| 185 // Windows V3: 40 | 187 // Windows V3: 40 |
| 186 else if ((m_infoHeader.biSize == 40) || isWindowsV4Plus()) | 188 else if ((m_infoHeader.biSize == 40) || isWindowsV4Plus()) |
| 187 ; | 189 ; |
| 188 // OS/2 2.x: any multiple of 4 between 16 and 64, inclusive, or 42 or 46 | 190 // OS/2 2.x: any multiple of 4 between 16 and 64, inclusive, or 42 or 46 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 // 16 bits: MSB <- xRRRRRGG GGGBBBBB -> LSB | 417 // 16 bits: MSB <- xRRRRRGG GGGBBBBB -> LSB |
| 416 // 24/32 bits: MSB <- [AAAAAAAA] RRRRRRRR GGGGGGGG BBBBBBBB -> LSB | 418 // 24/32 bits: MSB <- [AAAAAAAA] RRRRRRRR GGGGGGGG BBBBBBBB -> LSB |
| 417 const int numBits = (m_infoHeader.biBitCount == 16) ? 5 : 8; | 419 const int numBits = (m_infoHeader.biBitCount == 16) ? 5 : 8; |
| 418 for (int i = 0; i <= 2; ++i) | 420 for (int i = 0; i <= 2; ++i) |
| 419 m_bitMasks[i] = ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^ ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1); | 421 m_bitMasks[i] = ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^ ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1); |
| 420 } else if (!isWindowsV4Plus()) { | 422 } else if (!isWindowsV4Plus()) { |
| 421 // For Windows V4+ BITFIELDS mode bitmaps, this was already done when | 423 // For Windows V4+ BITFIELDS mode bitmaps, this was already done when |
| 422 // we read the info header. | 424 // we read the info header. |
| 423 | 425 |
| 424 // Fail if we don't have enough file space for the bitmasks. | 426 // Fail if we don't have enough file space for the bitmasks. |
| 425 static const size_t SIZEOF_BITMASKS = 12; | 427 const size_t bitmasksSize = 12; |
|
Peter Kasting
2015/02/04 04:59:02
Tiny nit: Swap this line with the next
changseok
2015/02/04 05:34:46
Done.
| |
| 426 if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < (m_heade rOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_hea derOffset + m_infoHeader.biSize + SIZEOF_BITMASKS)))) | 428 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; |
| 429 const size_t bitmasksEnd = headerEnd + bitmasksSize; | |
| 430 if ((bitmasksEnd < headerEnd) || (m_imgDataOffset && (m_imgDataOffset < bitmasksEnd))) | |
| 427 return m_parent->setFailed(); | 431 return m_parent->setFailed(); |
| 428 | 432 |
| 429 // Read bitmasks. | 433 // Read bitmasks. |
| 430 if ((m_data->size() - m_decodedOffset) < SIZEOF_BITMASKS) | 434 if ((m_data->size() - m_decodedOffset) < bitmasksSize) |
| 431 return false; | 435 return false; |
| 432 m_bitMasks[0] = readUint32(0); | 436 m_bitMasks[0] = readUint32(0); |
| 433 m_bitMasks[1] = readUint32(4); | 437 m_bitMasks[1] = readUint32(4); |
| 434 m_bitMasks[2] = readUint32(8); | 438 m_bitMasks[2] = readUint32(8); |
| 435 | 439 |
| 436 m_decodedOffset += SIZEOF_BITMASKS; | 440 m_decodedOffset += bitmasksSize; |
| 437 } | 441 } |
| 438 | 442 |
| 439 // Alpha is a poorly-documented and inconsistently-used feature. | 443 // Alpha is a poorly-documented and inconsistently-used feature. |
| 440 // | 444 // |
| 441 // 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 |
| 442 // bitmasks, the MSDN docs don't indicate that it is only valid for the | 446 // bitmasks, the MSDN docs don't indicate that it is only valid for the |
| 443 // BITFIELDS compression format, so we respect it at all times. | 447 // BITFIELDS compression format, so we respect it at all times. |
| 444 // | 448 // |
| 445 // To complicate things, Windows V3 BMPs, which lack this mask, can specify | 449 // To complicate things, Windows V3 BMPs, which lack this mask, can specify |
| 446 // 32bpp format, which to any sane reader would imply an 8-bit alpha | 450 // 32bpp format, which to any sane reader would imply an 8-bit alpha |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 522 | 526 |
| 523 // Calculate LUT address. | 527 // Calculate LUT address. |
| 524 m_lookupTableAddresses[i] = numBits ? (nBitTo8BitlookupTable + (1 << num Bits) - 2) : 0; | 528 m_lookupTableAddresses[i] = numBits ? (nBitTo8BitlookupTable + (1 << num Bits) - 2) : 0; |
| 525 } | 529 } |
| 526 | 530 |
| 527 return true; | 531 return true; |
| 528 } | 532 } |
| 529 | 533 |
| 530 bool BMPImageReader::processColorTable() | 534 bool BMPImageReader::processColorTable() |
| 531 { | 535 { |
| 532 size_t tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4); | 536 const size_t tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4) ; |
|
Peter Kasting
2015/02/04 04:59:01
Tiny nit: Swap this line with the next
changseok
2015/02/04 05:34:46
Done.
| |
| 537 const size_t headerEnd = m_headerOffset + m_infoHeader.biSize; | |
| 538 const size_t tableEnd = headerEnd + tableSizeInBytes; | |
| 533 | 539 |
|
Peter Kasting
2015/02/04 04:59:01
Nit: Eliminate this newline and move the comment b
changseok
2015/02/04 05:34:46
Done.
| |
| 534 // Fail if we don't have enough file space for the color table. | 540 // Fail if we don't have enough file space for the color table. |
| 535 if (((m_headerOffset + m_infoHeader.biSize + tableSizeInBytes) < (m_headerOf fset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_header Offset + m_infoHeader.biSize + tableSizeInBytes)))) | 541 if ((tableEnd < headerEnd) || (m_imgDataOffset && (m_imgDataOffset < tableEn d))) |
| 536 return m_parent->setFailed(); | 542 return m_parent->setFailed(); |
| 537 | 543 |
| 538 // Read color table. | 544 // Read color table. |
| 539 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < tableSizeInBytes)) | 545 if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset ) < tableSizeInBytes)) |
| 540 return false; | 546 return false; |
| 541 m_colorTable.resize(m_infoHeader.biClrUsed); | 547 m_colorTable.resize(m_infoHeader.biClrUsed); |
| 542 for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) { | 548 for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) { |
| 543 m_colorTable[i].rgbBlue = m_data->data()[m_decodedOffset++]; | 549 m_colorTable[i].rgbBlue = m_data->data()[m_decodedOffset++]; |
| 544 m_colorTable[i].rgbGreen = m_data->data()[m_decodedOffset++]; | 550 m_colorTable[i].rgbGreen = m_data->data()[m_decodedOffset++]; |
| 545 m_colorTable[i].rgbRed = m_data->data()[m_decodedOffset++]; | 551 m_colorTable[i].rgbRed = m_data->data()[m_decodedOffset++]; |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 // Finished decoding whole image. | 801 // Finished decoding whole image. |
| 796 return Success; | 802 return Success; |
| 797 } | 803 } |
| 798 | 804 |
| 799 void BMPImageReader::moveBufferToNextRow() | 805 void BMPImageReader::moveBufferToNextRow() |
| 800 { | 806 { |
| 801 m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); | 807 m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); |
| 802 } | 808 } |
| 803 | 809 |
| 804 } // namespace blink | 810 } // namespace blink |
| OLD | NEW |