Add initial support for bitmap version 4/5 headers.

The headers are just skipped, information stored in them is ignored.

Merge-request: 824

Change-Id: I48f37757114ed83cd5c92cb3d5a43eeaca4b91b3
Reviewed-on: http://codereview.qt.nokia.com/2108
Reviewed-by: Kim M. Kalland <kim.kalland@nokia.com>
This commit is contained in:
Ilya Konkov 2011-07-22 13:25:46 +02:00 committed by Qt by Nokia
parent b949b17c3c
commit 3ef653f681
5 changed files with 79 additions and 9 deletions

View File

@ -97,8 +97,10 @@ static QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf)
const int BMP_OLD = 12; // old Windows/OS2 BMP size const int BMP_OLD = 12; // old Windows/OS2 BMP size
const int BMP_WIN = 40; // new Windows BMP size const int BMP_WIN = 40; // Windows BMP v3 size
const int BMP_OS2 = 64; // new OS/2 BMP size const int BMP_OS2 = 64; // new OS/2 BMP size
const int BMP_WIN4 = 108; // Windows BMP v4 size
const int BMP_WIN5 = 124; // Windows BMP v5 size
const int BMP_RGB = 0; // no compression const int BMP_RGB = 0; // no compression
const int BMP_RLE8 = 1; // run-length encoded, 8 bits const int BMP_RLE8 = 1; // run-length encoded, 8 bits
@ -109,7 +111,7 @@ const int BMP_BITFIELDS = 3; // RGB values encoded in dat
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi) static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
{ {
s >> bi.biSize; s >> bi.biSize;
if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2) { if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2 || bi.biSize == BMP_WIN4 || bi.biSize == BMP_WIN5) {
s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount; s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount;
s >> bi.biCompression >> bi.biSizeImage; s >> bi.biCompression >> bi.biSizeImage;
s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter; s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter;
@ -255,7 +257,57 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
image.setDotsPerMeterY(bi.biYPelsPerMeter); image.setDotsPerMeterY(bi.biYPelsPerMeter);
if (!d->isSequential()) if (!d->isSequential())
d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap
if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) {
Q_ASSERT(ncols == 0);
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
return false;
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
return false;
// Read BMP v4+ header
if (bi.biSize >= BMP_WIN4) {
int alpha_mask = 0;
int CSType = 0;
int gamma_red = 0;
int gamma_green = 0;
int gamma_blue = 0;
int endpoints[9];
if (d->read((char *)&alpha_mask, sizeof(alpha_mask)) != sizeof(alpha_mask))
return false;
if (d->read((char *)&CSType, sizeof(CSType)) != sizeof(CSType))
return false;
if (d->read((char *)&endpoints, sizeof(endpoints)) != sizeof(endpoints))
return false;
if (d->read((char *)&gamma_red, sizeof(gamma_red)) != sizeof(gamma_red))
return false;
if (d->read((char *)&gamma_green, sizeof(gamma_green)) != sizeof(gamma_green))
return false;
if (d->read((char *)&gamma_blue, sizeof(gamma_blue)) != sizeof(gamma_blue))
return false;
if (bi.biSize == BMP_WIN5) {
qint32 intent = 0;
qint32 profileData = 0;
qint32 profileSize = 0;
qint32 reserved = 0;
if (d->read((char *)&intent, sizeof(intent)) != sizeof(intent))
return false;
if (d->read((char *)&profileData, sizeof(profileData)) != sizeof(profileData))
return false;
if (d->read((char *)&profileSize, sizeof(profileSize)) != sizeof(profileSize))
return false;
if (d->read((char *)&reserved, sizeof(reserved)) != sizeof(reserved) || reserved != 0)
return false;
}
}
}
if (ncols > 0) { // read color table if (ncols > 0) { // read color table
uchar rgb[4]; uchar rgb[4];
@ -268,12 +320,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
return false; return false;
} }
} else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) { } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
return false;
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
return false;
red_shift = calc_shift(red_mask); red_shift = calc_shift(red_mask);
red_scale = 256 / ((red_mask >> red_shift) + 1); red_scale = 256 / ((red_mask >> red_shift) + 1);
green_shift = calc_shift(green_mask); green_shift = calc_shift(green_mask);

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@ -42,6 +42,8 @@
<file>images/teapot.ppm</file> <file>images/teapot.ppm</file>
<file>images/test.ppm</file> <file>images/test.ppm</file>
<file>images/test.xpm</file> <file>images/test.xpm</file>
<file>images/test32bfv4.bmp</file>
<file>images/test32v5.bmp</file>
<file>images/tst7.bmp</file> <file>images/tst7.bmp</file>
<file>images/tst7.png</file> <file>images/tst7.png</file>
<file>images/transparent.xpm</file> <file>images/transparent.xpm</file>

View File

@ -234,6 +234,8 @@ void tst_QImageReader::readImage_data()
QTest::newRow("empty") << QString() << false << QByteArray(); QTest::newRow("empty") << QString() << false << QByteArray();
QTest::newRow("BMP: colorful") << QString("colorful.bmp") << true << QByteArray("bmp"); QTest::newRow("BMP: colorful") << QString("colorful.bmp") << true << QByteArray("bmp");
QTest::newRow("BMP: test32bfv4") << QString("test32bfv4.bmp") << true << QByteArray("bmp");
QTest::newRow("BMP: test32v5") << QString("test32v5.bmp") << true << QByteArray("bmp");
QTest::newRow("BMP: font") << QString("font.bmp") << true << QByteArray("bmp"); QTest::newRow("BMP: font") << QString("font.bmp") << true << QByteArray("bmp");
QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << true << QByteArray("bmp"); QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << true << QByteArray("bmp");
QTest::newRow("BMP: 4bpp RLE") << QString("4bpp-rle.bmp") << true << QByteArray("bmp"); QTest::newRow("BMP: 4bpp RLE") << QString("4bpp-rle.bmp") << true << QByteArray("bmp");
@ -432,6 +434,8 @@ void tst_QImageReader::setClipRect_data()
QTest::addColumn<QRect>("newRect"); QTest::addColumn<QRect>("newRect");
QTest::addColumn<QByteArray>("format"); QTest::addColumn<QByteArray>("format");
QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp"); QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: test32bfv4") << "test32bfv4" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: test32v5") << "test32v5" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp"); QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: 4bpp uncompressed") << "tst7.bmp" << QRect(0, 0, 31, 31) << QByteArray("bmp"); QTest::newRow("BMP: 4bpp uncompressed") << "tst7.bmp" << QRect(0, 0, 31, 31) << QByteArray("bmp");
QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm"); QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
@ -484,6 +488,8 @@ void tst_QImageReader::setScaledClipRect_data()
QTest::addColumn<QByteArray>("format"); QTest::addColumn<QByteArray>("format");
QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp"); QTest::newRow("BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: test32bfv4") << "test32bfv4" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: test32v5") << "test32v5" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp"); QTest::newRow("BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm"); QTest::newRow("XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
QTest::newRow("PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png"); QTest::newRow("PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
@ -555,6 +561,8 @@ void tst_QImageReader::imageFormat_data()
QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm") << QImage::Format_Indexed8; QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm") << QImage::Format_Indexed8;
QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp") << QImage::Format_Indexed8; QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp") << QImage::Format_Indexed8; QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32; QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32; QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng") << QImage::Format_Invalid; QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng") << QImage::Format_Invalid;
@ -684,6 +692,8 @@ void tst_QImageReader::supportsAnimation_data()
QTest::newRow("BMP: colorful") << QString("colorful.bmp") << false; QTest::newRow("BMP: colorful") << QString("colorful.bmp") << false;
QTest::newRow("BMP: font") << QString("font.bmp") << false; QTest::newRow("BMP: font") << QString("font.bmp") << false;
QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << false; QTest::newRow("BMP: signed char") << QString("crash-signed-char.bmp") << false;
QTest::newRow("BMP: test32bfv4") << QString("test32bfv4.bmp") << false;;
QTest::newRow("BMP: test32v5") << QString("test32v5.bmp") << false;
QTest::newRow("XPM: marble") << QString("marble.xpm") << false; QTest::newRow("XPM: marble") << QString("marble.xpm") << false;
QTest::newRow("PNG: kollada") << QString("kollada.png") << false; QTest::newRow("PNG: kollada") << QString("kollada.png") << false;
QTest::newRow("PPM: teapot") << QString("teapot.ppm") << false; QTest::newRow("PPM: teapot") << QString("teapot.ppm") << false;
@ -1064,6 +1074,8 @@ void tst_QImageReader::readFromDevice_data()
QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm"); QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp"); QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp"); QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
QTest::newRow("png") << QString("kollada.png") << QByteArray("png"); QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
#ifdef QTEST_HAVE_MNG #ifdef QTEST_HAVE_MNG
QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng"); QTest::newRow("mng-1") << QString("ball.mng") << QByteArray("mng");
@ -1155,6 +1167,8 @@ void tst_QImageReader::readFromFileAfterJunk_data()
QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm"); QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp"); QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp"); QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
QTest::newRow("png") << QString("kollada.png") << QByteArray("png"); QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
// QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng"); // QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng");
// QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng"); // QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng");
@ -1233,6 +1247,8 @@ void tst_QImageReader::devicePosition_data()
QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm"); QTest::newRow("xpm") << QString("marble.xpm") << QByteArray("xpm");
QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp"); QTest::newRow("bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp"); QTest::newRow("bmp-2") << QString("font.bmp") << QByteArray("bmp");
QTest::newRow("bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
QTest::newRow("png") << QString("kollada.png") << QByteArray("png"); QTest::newRow("png") << QString("kollada.png") << QByteArray("png");
// QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng"); // QTest::newRow("mng-1") << QString("images/ball.mng") << QByteArray("mng");
// QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng"); // QTest::newRow("mng-2") << QString("images/fire.mng") << QByteArray("mng");
@ -1305,6 +1321,12 @@ void tst_QImageReader::readFromResources_data()
QTest::newRow("4bpp-rle.bmp") << QString("4bpp-rle.bmp") QTest::newRow("4bpp-rle.bmp") << QString("4bpp-rle.bmp")
<< QByteArray("bmp") << QSize(640, 480) << QByteArray("bmp") << QSize(640, 480)
<< QString(""); << QString("");
QTest::newRow("test32bfv4.bmp") << QString("test32bfv4.bmp")
<< QByteArray("bmp") << QSize(373, 156)
<< QString("");
QTest::newRow("test32v5.bmp") << QString("test32v5.bmp")
<< QByteArray("bmp") << QSize(373, 156)
<< QString("");
#ifdef QTEST_HAVE_GIF #ifdef QTEST_HAVE_GIF
QTest::newRow("corrupt.gif") << QString("corrupt.gif") QTest::newRow("corrupt.gif") << QString("corrupt.gif")
<< QByteArray("gif") << QSize(0, 0) << QByteArray("gif") << QSize(0, 0)