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#include <wtf/PassOwnPtr.h> 36 37namespace WebCore { 38 39// Number of bits in .BMP used to store the file header (doesn't match 40// "sizeof(BMPImageDecoder::BitmapFileHeader)" since we omit some fields and 41// don't pack). 42static const size_t sizeOfFileHeader = 14; 43 44BMPImageDecoder::BMPImageDecoder(ImageSource::AlphaOption alphaOption, 45 ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 46 : ImageDecoder(alphaOption, gammaAndColorProfileOption) 47 , m_decodedOffset(0) 48{ 49} 50 51void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) 52{ 53 if (failed()) 54 return; 55 56 ImageDecoder::setData(data, allDataReceived); 57 if (m_reader) 58 m_reader->setData(data); 59} 60 61bool BMPImageDecoder::isSizeAvailable() 62{ 63 if (!ImageDecoder::isSizeAvailable()) 64 decode(true); 65 66 return ImageDecoder::isSizeAvailable(); 67} 68 69ImageFrame* BMPImageDecoder::frameBufferAtIndex(size_t index) 70{ 71 if (index) 72 return 0; 73 74 if (m_frameBufferCache.isEmpty()) { 75 m_frameBufferCache.resize(1); 76 m_frameBufferCache.first().setPremultiplyAlpha(m_premultiplyAlpha); 77 } 78 79 ImageFrame* buffer = &m_frameBufferCache.first(); 80 if (buffer->status() != ImageFrame::FrameComplete) 81 decode(false); 82 return buffer; 83} 84 85bool BMPImageDecoder::setFailed() 86{ 87 m_reader.clear(); 88 return ImageDecoder::setFailed(); 89} 90 91void BMPImageDecoder::decode(bool onlySize) 92{ 93 if (failed()) 94 return; 95 96 // If we couldn't decode the image but we've received all the data, decoding 97 // has failed. 98 if (!decodeHelper(onlySize) && isAllDataReceived()) 99 setFailed(); 100 // If we're done decoding the image, we don't need the BMPImageReader 101 // anymore. (If we failed, |m_reader| has already been cleared.) 102 else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache.first().status() == ImageFrame::FrameComplete)) 103 m_reader.clear(); 104} 105 106bool BMPImageDecoder::decodeHelper(bool onlySize) 107{ 108 size_t imgDataOffset = 0; 109 if ((m_decodedOffset < sizeOfFileHeader) && !processFileHeader(&imgDataOffset)) 110 return false; 111 112 if (!m_reader) { 113 m_reader = adoptPtr(new BMPImageReader(this, m_decodedOffset, imgDataOffset, false)); 114 m_reader->setData(m_data.get()); 115 } 116 117 if (!m_frameBufferCache.isEmpty()) 118 m_reader->setBuffer(&m_frameBufferCache.first()); 119 120 return m_reader->decodeBMP(onlySize); 121} 122 123bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset) 124{ 125 ASSERT(imgDataOffset); 126 127 // Read file header. 128 ASSERT(!m_decodedOffset); 129 if (m_data->size() < sizeOfFileHeader) 130 return false; 131 const uint16_t fileType = (m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]); 132 *imgDataOffset = readUint32(10); 133 m_decodedOffset = sizeOfFileHeader; 134 135 // See if this is a bitmap filetype we understand. 136 enum { 137 BMAP = 0x424D, // "BM" 138 // The following additional OS/2 2.x header values (see 139 // http://www.fileformat.info/format/os2bmp/egff.htm ) aren't widely 140 // decoded, and are unlikely to be in much use. 141 /* 142 ICON = 0x4943, // "IC" 143 POINTER = 0x5054, // "PT" 144 COLORICON = 0x4349, // "CI" 145 COLORPOINTER = 0x4350, // "CP" 146 BITMAPARRAY = 0x4241, // "BA" 147 */ 148 }; 149 return (fileType == BMAP) || setFailed(); 150} 151 152} // namespace WebCore 153