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

Unified Diff: Source/platform/image-decoders/bmp/BMPImageReader.h

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years 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 side-by-side diff with in-line comments
Download patch
Index: Source/platform/image-decoders/bmp/BMPImageReader.h
diff --git a/Source/platform/image-decoders/bmp/BMPImageReader.h b/Source/platform/image-decoders/bmp/BMPImageReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d109cb9e6ebb90913ab7561c10dfd722ca6dbfe
--- /dev/null
+++ b/Source/platform/image-decoders/bmp/BMPImageReader.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BMPImageReader_h
+#define BMPImageReader_h
+
+#include <stdint.h>
+#include "platform/image-decoders/ImageDecoder.h"
+#include "wtf/CPU.h"
+
+namespace WebCore {
+
+// This class decodes a BMP image. It is used in the BMP and ICO decoders,
+// which wrap it in the appropriate code to read file headers, etc.
+class PLATFORM_EXPORT BMPImageReader {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ // Read a value from |data[offset]|, converting from little to native
+ // endianness.
+ static inline uint16_t readUint16(SharedBuffer* data, int offset)
+ {
+ uint16_t result;
+ memcpy(&result, &data->data()[offset], 2);
+ #if CPU(BIG_ENDIAN)
+ result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8);
+ #endif
+ return result;
+ }
+
+ static inline uint32_t readUint32(SharedBuffer* data, int offset)
+ {
+ uint32_t result;
+ memcpy(&result, &data->data()[offset], 4);
+ #if CPU(BIG_ENDIAN)
+ result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24);
+ #endif
+ return result;
+ }
+
+ // |parent| is the decoder that owns us.
+ // |startOffset| points to the start of the BMP within the file.
+ // |buffer| points at an empty ImageFrame that we'll initialize and
+ // fill with decoded data.
+ BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask);
+
+ void setBuffer(ImageFrame* buffer) { m_buffer = buffer; }
+ void setData(SharedBuffer* data) { m_data = data; }
+
+ // Does the actual decoding. If |onlySize| is true, decoding only
+ // progresses as far as necessary to get the image size. Returns
+ // whether decoding succeeded.
+ bool decodeBMP(bool onlySize);
+
+private:
+ // The various BMP compression types. We don't currently decode all
+ // these.
+ enum CompressionType {
+ // Universal types
+ RGB = 0,
+ RLE8 = 1,
+ RLE4 = 2,
+ // Windows V3+ only
+ BITFIELDS = 3,
+ JPEG = 4,
+ PNG = 5,
+ // OS/2 2.x-only
+ HUFFMAN1D, // Stored in file as 3
+ RLE24, // Stored in file as 4
+ };
+ enum AndMaskState {
+ None,
+ NotYetDecoded,
+ Decoding,
+ };
+ enum ProcessingResult {
+ Success,
+ Failure,
+ InsufficientData,
+ };
+
+ // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE
+ // structs, but with unnecessary entries removed.
+ struct BitmapInfoHeader {
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biBitCount;
+ CompressionType biCompression;
+ uint32_t biClrUsed;
+ };
+ struct RGBTriple {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ };
+
+ inline uint16_t readUint16(int offset) const
+ {
+ return readUint16(m_data.get(), m_decodedOffset + offset);
+ }
+
+ inline uint32_t readUint32(int offset) const
+ {
+ return readUint32(m_data.get(), m_decodedOffset + offset);
+ }
+
+ // Determines the size of the BMP info header. Returns true if the size
+ // is valid.
+ bool readInfoHeaderSize();
+
+ // Processes the BMP info header. Returns true if the info header could
+ // be decoded.
+ bool processInfoHeader();
+
+ // Helper function for processInfoHeader() which does the actual reading
+ // of header values from the byte stream. Returns false on error.
+ bool readInfoHeader();
+
+ // Returns true if this is a Windows V4+ BMP.
+ inline bool isWindowsV4Plus() const
+ {
+ // Windows V4 info header is 108 bytes. V5 is 124 bytes.
+ return (m_infoHeader.biSize == 108) || (m_infoHeader.biSize == 124);
+ }
+
+ // Returns false if consistency errors are found in the info header.
+ bool isInfoHeaderValid() const;
+
+ // For BI_BITFIELDS images, initializes the m_bitMasks[] and
+ // m_bitOffsets[] arrays. processInfoHeader() will initialize these for
+ // other compression types where needed.
+ bool processBitmasks();
+
+ // For paletted images, allocates and initializes the m_colorTable[]
+ // array.
+ bool processColorTable();
+
+ // Processes an RLE-encoded image. Returns true if the entire image was
+ // decoded.
+ bool processRLEData();
+
+ // Processes a set of non-RLE-compressed pixels. Two cases:
+ // * inRLE = true: the data is inside an RLE-encoded bitmap. Tries to
+ // process |numPixels| pixels on the current row.
+ // * inRLE = false: the data is inside a non-RLE-encoded bitmap.
+ // |numPixels| is ignored. Expects |m_coord| to point at the
+ // beginning of the next row to be decoded. Tries to process as
+ // many complete rows as possible. Returns InsufficientData if
+ // there wasn't enough data to decode the whole image.
+ //
+ // This function returns a ProcessingResult instead of a bool so that it
+ // can avoid calling m_parent->setFailed(), which could lead to memory
+ // corruption since that will delete |this| but some callers still want
+ // to access member variables after this returns.
+ ProcessingResult processNonRLEData(bool inRLE, int numPixels);
+
+ // Returns true if the current y-coordinate plus |numRows| would be past
+ // the end of the image. Here "plus" means "toward the end of the
+ // image", so downwards for m_isTopDown images and upwards otherwise.
+ inline bool pastEndOfImage(int numRows)
+ {
+ return m_isTopDown ? ((m_coord.y() + numRows) >= m_parent->size().height()) : ((m_coord.y() - numRows) < 0);
+ }
+
+ // Returns the pixel data for the current X coordinate in a uint32_t.
+ // Assumes m_decodedOffset has been set to the beginning of the current
+ // row.
+ // NOTE: Only as many bytes of the return value as are needed to hold
+ // the pixel data will actually be set.
+ inline uint32_t readCurrentPixel(int bytesPerPixel) const
+ {
+ const int offset = m_coord.x() * bytesPerPixel;
+ switch (bytesPerPixel) {
+ case 2:
+ return readUint16(offset);
+
+ case 3: {
+ // It doesn't matter that we never set the most significant byte
+ // of the return value here in little-endian mode, the caller
+ // won't read it.
+ uint32_t pixel;
+ memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3);
+ #if CPU(BIG_ENDIAN)
+ pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | ((pixel & 0xff000000) >> 24);
+ #endif
+ return pixel;
+ }
+
+ case 4:
+ return readUint32(offset);
+
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+ }
+
+ // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A)
+ // in the given pixel data.
+ inline unsigned getComponent(uint32_t pixel, int component) const
+ {
+ return ((pixel & m_bitMasks[component]) >> m_bitShiftsRight[component]) << m_bitShiftsLeft[component];
+ }
+
+ inline unsigned getAlpha(uint32_t pixel) const
+ {
+ // For images without alpha, return alpha of 0xff.
+ return m_bitMasks[3] ? getComponent(pixel, 3) : 0xff;
+ }
+
+ // Sets the current pixel to the color given by |colorIndex|. This also
+ // increments the relevant local variables to move the current pixel
+ // right by one.
+ inline void setI(size_t colorIndex)
+ {
+ setRGBA(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen, m_colorTable[colorIndex].rgbBlue, 0xff);
+ }
+
+ // Like setI(), but with the individual component values specified.
+ inline void setRGBA(unsigned red,
+ unsigned green,
+ unsigned blue,
+ unsigned alpha)
+ {
+ m_buffer->setRGBA(m_coord.x(), m_coord.y(), red, green, blue, alpha);
+ m_coord.move(1, 0);
+ }
+
+ // Fills pixels from the current X-coordinate up to, but not including,
+ // |endCoord| with the color given by the individual components. This
+ // also increments the relevant local variables to move the current
+ // pixel right to |endCoord|.
+ inline void fillRGBA(int endCoord,
+ unsigned red,
+ unsigned green,
+ unsigned blue,
+ unsigned alpha)
+ {
+ while (m_coord.x() < endCoord)
+ setRGBA(red, green, blue, alpha);
+ }
+
+ // Resets the relevant local variables to start drawing at the left edge
+ // of the "next" row, where "next" is above or below the current row
+ // depending on the value of |m_isTopDown|.
+ void moveBufferToNextRow();
+
+ // The decoder that owns us.
+ ImageDecoder* m_parent;
+
+ // The destination for the pixel data.
+ ImageFrame* m_buffer;
+
+ // The file to decode.
+ RefPtr<SharedBuffer> m_data;
+
+ // An index into |m_data| representing how much we've already decoded.
+ size_t m_decodedOffset;
+
+ // The file offset at which the BMP info header starts.
+ size_t m_headerOffset;
+
+ // The file offset at which the actual image bits start. When decoding
+ // ICO files, this is set to 0, since it's not stored anywhere in a
+ // header; the reader functions expect the image data to start
+ // immediately after the header and (if necessary) color table.
+ size_t m_imgDataOffset;
+
+ // The BMP info header.
+ BitmapInfoHeader m_infoHeader;
+
+ // True if this is an OS/2 1.x (aka Windows 2.x) BMP. The struct
+ // layouts for this type of BMP are slightly different from the later,
+ // more common formats.
+ bool m_isOS21x;
+
+ // True if this is an OS/2 2.x BMP. The meanings of compression types 3
+ // and 4 for this type of BMP differ from Windows V3+ BMPs.
+ //
+ // This will be falsely negative in some cases, but only ones where the
+ // way we misinterpret the data is irrelevant.
+ bool m_isOS22x;
+
+ // True if the BMP is not vertically flipped, that is, the first line of
+ // raster data in the file is the top line of the image.
+ bool m_isTopDown;
+
+ // These flags get set to false as we finish each processing stage.
+ bool m_needToProcessBitmasks;
+ bool m_needToProcessColorTable;
+
+ // Masks/offsets for the color values for non-palette formats. These
+ // are bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B,
+ // A.
+ //
+ // The right/left shift values are meant to be applied after the masks.
+ // We need to right shift to compensate for the bitfields' offsets into
+ // the 32 bits of pixel data, and left shift to scale the color values
+ // up for fields with less than 8 bits of precision. Sadly, we can't
+ // just combine these into one shift value because the net shift amount
+ // could go either direction. (If only "<< -x" were equivalent to
+ // ">> x"...)
+ uint32_t m_bitMasks[4];
+ int m_bitShiftsRight[4];
+ int m_bitShiftsLeft[4];
+
+ // The color palette, for paletted formats.
+ size_t m_tableSizeInBytes;
+ Vector<RGBTriple> m_colorTable;
+
+ // The coordinate to which we've decoded the image.
+ IntPoint m_coord;
+
+ // Variables that track whether we've seen pixels with alpha values != 0
+ // and == 0, respectively. See comments in processNonRLEData() on how
+ // these are used.
+ bool m_seenNonZeroAlphaPixel;
+ bool m_seenZeroAlphaPixel;
+
+ // ICOs store a 1bpp "mask" immediately after the main bitmap image data
+ // (and, confusingly, add its height to the biHeight value in the info
+ // header, thus doubling it). This variable tracks whether we have such
+ // a mask and if we've started decoding it yet.
+ AndMaskState m_andMaskState;
+};
+
+} // namespace WebCore
+
+#endif
« no previous file with comments | « Source/platform/image-decoders/bmp/BMPImageDecoder.cpp ('k') | Source/platform/image-decoders/bmp/BMPImageReader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698