1/* 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "BMPImageDecoder.h" 33 34#include "BMPImageReader.h" 35 36namespace WebCore { 37 38// Number of bits in .BMP used to store the file header (doesn't match 39// "sizeof(BMPImageDecoder::BitmapFileHeader)" since we omit some fields and 40// don't pack). 41static const size_t sizeOfFileHeader = 14; 42 43BMPImageDecoder::BMPImageDecoder() 44 : ImageDecoder() 45 , m_allDataReceived(false) 46 , m_decodedOffset(0) 47{ 48} 49 50void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) 51{ 52 if (failed()) 53 return; 54 55 ImageDecoder::setData(data, allDataReceived); 56 m_allDataReceived = allDataReceived; 57 if (m_reader) 58 m_reader->setData(data); 59} 60 61bool BMPImageDecoder::isSizeAvailable() 62{ 63 if (!ImageDecoder::isSizeAvailable() && !failed()) 64 decodeWithCheckForDataEnded(true); 65 66 return ImageDecoder::isSizeAvailable(); 67} 68 69RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index) 70{ 71 if (index) 72 return 0; 73 74 if (m_frameBufferCache.isEmpty()) 75 m_frameBufferCache.resize(1); 76 77 RGBA32Buffer* buffer = &m_frameBufferCache.first(); 78 if (buffer->status() != RGBA32Buffer::FrameComplete && !failed()) 79 decodeWithCheckForDataEnded(false); 80 return buffer; 81} 82 83void BMPImageDecoder::decodeWithCheckForDataEnded(bool onlySize) 84{ 85 if (failed()) 86 return; 87 88 // If we couldn't decode the image but we've received all the data, decoding 89 // has failed. 90 if (!decode(onlySize) && m_allDataReceived) 91 setFailed(); 92} 93 94bool BMPImageDecoder::decode(bool onlySize) 95{ 96 size_t imgDataOffset = 0; 97 if ((m_decodedOffset < sizeOfFileHeader) 98 && !processFileHeader(&imgDataOffset)) 99 return false; 100 101 if (!m_reader) { 102 m_reader.set(new BMPImageReader(this, m_decodedOffset, imgDataOffset, 103 false)); 104 m_reader->setData(m_data.get()); 105 } 106 107 if (!m_frameBufferCache.isEmpty()) 108 m_reader->setBuffer(&m_frameBufferCache.first()); 109 110 return m_reader->decodeBMP(onlySize); 111} 112 113bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset) 114{ 115 ASSERT(imgDataOffset); 116 117 // Read file header. 118 ASSERT(!m_decodedOffset); 119 if (m_data->size() < sizeOfFileHeader) 120 return false; 121 const uint16_t fileType = 122 (m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]); 123 *imgDataOffset = readUint32(10); 124 m_decodedOffset = sizeOfFileHeader; 125 126 // See if this is a bitmap filetype we understand. 127 enum { 128 BMAP = 0x424D, // "BM" 129 // The following additional OS/2 2.x header values (see 130 // http://www.fileformat.info/format/os2bmp/egff.htm ) aren't widely 131 // decoded, and are unlikely to be in much use. 132 /* 133 ICON = 0x4943, // "IC" 134 POINTER = 0x5054, // "PT" 135 COLORICON = 0x4349, // "CI" 136 COLORPOINTER = 0x4350, // "CP" 137 BITMAPARRAY = 0x4241, // "BA" 138 */ 139 }; 140 if (fileType != BMAP) { 141 setFailed(); 142 return false; 143 } 144 145 return true; 146} 147 148} // namespace WebCore 149