⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmpimagereader.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    if ((m_decodedOffset > data->size())        || ((data->size() - m_decodedOffset) < m_tableSizeInBytes))        return false;    m_colorTable.resize(m_infoHeader.biClrUsed);    for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) {        m_colorTable[i].rgbBlue = data->data()[m_decodedOffset++];        m_colorTable[i].rgbGreen = data->data()[m_decodedOffset++];        m_colorTable[i].rgbRed = data->data()[m_decodedOffset++];        // Skip padding byte (not present on OS/2 1.x).        if (!m_isOS21x)            ++m_decodedOffset;    }    // We've now decoded all the non-image data we care about.  Skip anything    // else before the actual raster data.    if (m_imgDataOffset)        m_decodedOffset = m_imgDataOffset;    m_needToProcessColorTable = false;    return true;}bool BMPImageReader::processRLEData(SharedBuffer* data){    if (m_decodedOffset > data->size())        return false;    // RLE decoding is poorly specified.  Two main problems:    // (1) Are EOL markers necessary?  What happens when we have too many    //     pixels for one row?    //     http://www.fileformat.info/format/bmp/egff.htm says extra pixels    //     should wrap to the next line.  Real BMPs I've encountered seem to    //     instead expect extra pixels to be ignored until the EOL marker is    //     seen, although this has only happened in a few cases and I suspect    //     those BMPs may be invalid.  So we only change lines on EOL (or Delta    //     with dy > 0), and fail in most cases when pixels extend past the end    //     of the line.    // (2) When Delta, EOL, or EOF are seen, what happens to the "skipped"    //     pixels?    //     http://www.daubnet.com/formats/BMP.html says these should be filled    //     with color 0.  However, the "do nothing" and "don't care" comments    //     of other references suggest leaving these alone, i.e. letting them    //     be transparent to the background behind the image.  This seems to    //     match how MSPAINT treats BMPs, so we do that.  Note that when we    //     actually skip pixels for a case like this, we need to note on the    //     framebuffer that we have alpha.    // Impossible to decode row-at-a-time, so just do things as a stream of    // bytes.    while (true) {        // Every entry takes at least two bytes; bail if there isn't enough        // data.        if ((data->size() - m_decodedOffset) < 2)            return false;        // For every entry except EOF, we'd better not have reached the end of        // the image.        const uint8_t count = data->data()[m_decodedOffset];        const uint8_t code = data->data()[m_decodedOffset + 1];        if (((count != 0) || (code != 1)) && pastEndOfImage(0)) {            m_failed = true;            return false;        }        // Decode.        if (count == 0) {            switch (code) {            case 0:  // Magic token: EOL                // Skip any remaining pixels in this row.                if (m_coord.x() < size().width())                    m_frameBufferCache.first().setHasAlpha(true);                moveBufferToNextRow();                m_decodedOffset += 2;                break;            case 1:  // Magic token: EOF                // Skip any remaining pixels in the image.                if ((m_coord.x() < size().width())                    || (m_isTopDown ? (m_coord.y() < (size().height() - 1)) : (m_coord.y() > 0)))                    m_frameBufferCache.first().setHasAlpha(true);                return true;            case 2: {  // Magic token: Delta                // The next two bytes specify dx and dy.  Bail if there isn't                // enough data.                if ((data->size() - m_decodedOffset) < 4)                    return false;                // Fail if this takes us past the end of the desired row or                // past the end of the image.                const uint8_t dx = data->data()[m_decodedOffset + 2];                const uint8_t dy = data->data()[m_decodedOffset + 3];                if ((dx != 0) || (dy != 0))                    m_frameBufferCache.first().setHasAlpha(true);                if (((m_coord.x() + dx) > size().width()) ||                    pastEndOfImage(dy)) {                    m_failed = true;                    return false;                }                // Skip intervening pixels.                m_coord.move(dx, m_isTopDown ? dy : -dy);                m_decodedOffset += 4;                break;            }            default:  // Absolute mode                // |code| pixels specified as in BI_RGB, zero-padded at the end                // to a multiple of 16 bits.                // Because processNonRLEData() expects m_decodedOffset to                // point to the beginning of the pixel data, bump it past                // the escape bytes and then reset if decoding failed.                m_decodedOffset += 2;                if (!processNonRLEData(data, true, code)) {                    m_decodedOffset -= 2;                    return false;                }                break;            }        } else {  // Encoded mode            // The following color data is repeated for |count| total pixels.            // Strangely, some BMPs seem to specify excessively large counts            // here; ignore pixels past the end of the row.            const int endX = std::min(m_coord.x() + count, size().width());            if (m_infoHeader.biCompression == RLE24) {                // Bail if there isn't enough data.                if ((data->size() - m_decodedOffset) < 4)                    return false;                // One BGR triple that we copy |count| times.                fillRGBA(endX, data->data()[m_decodedOffset + 3],                         data->data()[m_decodedOffset + 2], code, 0xff);                m_decodedOffset += 4;            } else {                // RLE8 has one color index that gets repeated; RLE4 has two                // color indexes in the upper and lower 4 bits of the byte,                // which are alternated.                size_t colorIndexes[2] = {code, code};                if (m_infoHeader.biCompression == RLE4) {                    colorIndexes[0] = (colorIndexes[0] >> 4) & 0xf;                    colorIndexes[1] &= 0xf;                }                if ((colorIndexes[0] >= m_infoHeader.biClrUsed)                    || (colorIndexes[1] >= m_infoHeader.biClrUsed)) {                    m_failed = true;                    return false;                }                for (int which = 0; m_coord.x() < endX; ) {                    setI(colorIndexes[which]);                    which = !which;                }                m_decodedOffset += 2;            }        }    }}bool BMPImageReader::processNonRLEData(SharedBuffer* data, bool inRLE, int numPixels){    if (m_decodedOffset > data->size())        return false;    if (!inRLE)        numPixels = size().width();    // Fail if we're being asked to decode more pixels than remain in the row.    const int endX = m_coord.x() + numPixels;    if (endX > size().width()) {        m_failed = true;        return false;    }    // Determine how many bytes of data the requested number of pixels    // requires.    const size_t pixelsPerByte = 8 / m_infoHeader.biBitCount;    const size_t bytesPerPixel = m_infoHeader.biBitCount / 8;    const size_t unpaddedNumBytes = (m_infoHeader.biBitCount < 16)        ? ((numPixels + pixelsPerByte - 1) / pixelsPerByte)        : (numPixels * bytesPerPixel);    // RLE runs are zero-padded at the end to a multiple of 16 bits.  Non-RLE    // data is in rows and is zero-padded to a multiple of 32 bits.    const size_t alignBits = inRLE ? 1 : 3;    const size_t paddedNumBytes = (unpaddedNumBytes + alignBits) & ~alignBits;    // Decode as many rows as we can.  (For RLE, where we only want to decode    // one row, we've already checked that this condition is true.)    while (!pastEndOfImage(0)) {        // Bail if we don't have enough data for the desired number of pixels.        if ((data->size() - m_decodedOffset) < paddedNumBytes)            return false;        if (m_infoHeader.biBitCount < 16) {            // Paletted data.  Pixels are stored little-endian within bytes.            // Decode pixels one byte at a time, left to right (so, starting at            // the most significant bits in the byte).            const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1;            for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) {                uint8_t pixelData = data->data()[m_decodedOffset + byte];                for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) {                    const size_t colorIndex =                        (pixelData >> (8 - m_infoHeader.biBitCount)) & mask;                    if (m_andMaskState == Decoding) {                        // There's no way to accurately represent an AND + XOR                        // operation as an RGBA image, so where the AND values                        // are 1, we simply set the framebuffer pixels to fully                        // transparent, on the assumption that most ICOs on the                        // web will not be doing a lot of inverting.                        if (colorIndex) {                            setRGBA(0, 0, 0, 0);                            m_frameBufferCache.first().setHasAlpha(true);                        } else                            m_coord.move(1, 0);                    } else {                        if (colorIndex >= m_infoHeader.biClrUsed) {                            m_failed = true;                            return false;                        }                        setI(colorIndex);                    }                    pixelData <<= m_infoHeader.biBitCount;                }            }        } else {            // RGB data.  Decode pixels one at a time, left to right.            while (m_coord.x() < endX) {                const uint32_t pixel = readCurrentPixel(data, bytesPerPixel);                // Some BMPs specify an alpha channel but don't actually use it                // (it contains all 0s).  To avoid displaying these images as                // fully-transparent, decode as if images are fully opaque                // until we actually see a non-zero alpha value; at that point,                // reset any previously-decoded pixels to fully transparent and                // continue decoding based on the real alpha channel values.                // As an optimization, avoid setting "hasAlpha" to true for                // images where all alpha values are 255; opaque images are                // faster to draw.                int alpha = getAlpha(pixel);                if (!m_seenNonZeroAlphaPixel && (alpha == 0)) {                    m_seenZeroAlphaPixel = true;                    alpha = 255;                } else {                    m_seenNonZeroAlphaPixel = true;                    if (m_seenZeroAlphaPixel) {                        // The eraseARGB() call here also sets "hasAlpha" true.                        m_frameBufferCache.first().bitmap().eraseARGB(0, 0, 0,                                                                      0);                        m_seenZeroAlphaPixel = false;                    } else if (alpha != 255)                        m_frameBufferCache.first().setHasAlpha(true);                }                setRGBA(getComponent(pixel, 0), getComponent(pixel, 1),                        getComponent(pixel, 2), alpha);            }        }        // Success, keep going.        m_decodedOffset += paddedNumBytes;        if (inRLE)            return true;        moveBufferToNextRow();    }    // Finished decoding whole image.    return true;}void BMPImageReader::moveBufferToNextRow(){    m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1);}} // namespace WebCore

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -