diff options
author | aavit <eirik.aavitsland@digia.com> | 2013-12-10 14:39:09 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-08 09:40:50 +0100 |
commit | 6f1b82fccdaf202856dcc6510c16b0531680fe23 (patch) | |
tree | 8c64215e7e358c2a84c5a4343b4f6932ecb99b36 /src/gui/image | |
parent | cd44f363ffd71f402265a03e7168f9774033a664 (diff) |
Fixes: 32 bit and alpha bmp format image reading
The bmp handler would ignore the high byte of a 32bit bmp. It
would also ignore any alpha channel.
The actual change is really simple; it just adds the alpha_* members
and the reading of the 4th byte in 32bit depth. However, detection
of alpha channel required switching the order of two independent
blocks of code, hence the size of this patch.
[ChangeLog][QtGui] Support reading bmp images with alpha channel
Task-number: QTBUG-35220
Change-Id: Ib133c3644c03c5cfc728f5fa2c837219804e69ae
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qbmphandler.cpp | 107 |
1 files changed, 61 insertions, 46 deletions
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index c03d9b8e5d..bb79a139b3 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -210,54 +210,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int uint red_mask = 0; uint green_mask = 0; uint blue_mask = 0; + uint alpha_mask = 0; int red_shift = 0; int green_shift = 0; int blue_shift = 0; + int alpha_shift = 0; int red_scale = 0; int green_scale = 0; int blue_scale = 0; - - int ncols = 0; - int depth = 0; - QImage::Format format; - switch (nbits) { - case 32: - case 24: - case 16: - depth = 32; - format = QImage::Format_RGB32; - break; - case 8: - case 4: - depth = 8; - format = QImage::Format_Indexed8; - break; - default: - depth = 1; - format = QImage::Format_Mono; - } - - if (bi.biHeight < 0) - h = -h; // support images with negative height - - if (image.size() != QSize(w, h) || image.format() != format) { - image = QImage(w, h, format); - if (image.isNull()) // could not create image - return false; - } - - if (depth != 32) { - ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; - if (ncols > 256) // sanity check - don't run out of mem if color table is broken - return false; - image.setColorCount(ncols); - } - - image.setDotsPerMeterX(bi.biXPelsPerMeter); - image.setDotsPerMeterY(bi.biYPelsPerMeter); - - if (!d->isSequential()) - d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap + int alpha_scale = 0; if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) { if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask)) @@ -269,7 +230,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int // Read BMP v4+ header if (bi.biSize >= BMP_WIN4) { - int alpha_mask = 0; int CSType = 0; int gamma_red = 0; int gamma_green = 0; @@ -307,6 +267,49 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int } } + bool transp = (comp == BMP_BITFIELDS) && alpha_mask; + int ncols = 0; + int depth = 0; + QImage::Format format; + switch (nbits) { + case 32: + case 24: + case 16: + depth = 32; + format = transp ? QImage::Format_ARGB32 : QImage::Format_RGB32; + break; + case 8: + case 4: + depth = 8; + format = QImage::Format_Indexed8; + break; + default: + depth = 1; + format = QImage::Format_Mono; + } + + if (bi.biHeight < 0) + h = -h; // support images with negative height + + if (image.size() != QSize(w, h) || image.format() != format) { + image = QImage(w, h, format); + if (image.isNull()) // could not create image + return false; + } + + if (depth != 32) { + ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; + if (ncols > 256) // sanity check - don't run out of mem if color table is broken + return false; + image.setColorCount(ncols); + } + + image.setDotsPerMeterX(bi.biXPelsPerMeter); + image.setDotsPerMeterY(bi.biYPelsPerMeter); + + if (!d->isSequential()) + d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap + if (ncols > 0) { // read color table uchar rgb[4]; int rgb_len = t == BMP_OLD ? 3 : 4; @@ -324,6 +327,8 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int green_scale = 256 / ((green_mask >> green_shift) + 1); blue_shift = calc_shift(blue_mask); blue_scale = 256 / ((blue_mask >> blue_shift) + 1); + alpha_shift = calc_shift(alpha_mask); + alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1); } else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) { blue_mask = 0x000000ff; green_mask = 0x0000ff00; @@ -344,6 +349,13 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int blue_scale = 8; } +#if 0 + qDebug("Rmask: %08x Rshift: %08x Rscale:%08x", red_mask, red_shift, red_scale); + qDebug("Gmask: %08x Gshift: %08x Gscale:%08x", green_mask, green_shift, green_scale); + qDebug("Bmask: %08x Bshift: %08x Bscale:%08x", blue_mask, blue_shift, blue_scale); + qDebug("Amask: %08x Ashift: %08x Ascale:%08x", alpha_mask, alpha_shift, alpha_scale); +#endif + // offset can be bogus, be careful if (offset>=0 && startpos + offset > d->pos()) { if (!d->isSequential()) @@ -535,11 +547,14 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int b = buf24; while (p < end) { c = *(uchar*)b | (*(uchar*)(b+1)<<8); - if (nbits != 16) + if (nbits > 16) c |= *(uchar*)(b+2)<<16; - *p++ = qRgb(((c & red_mask) >> red_shift) * red_scale, + if (nbits > 24) + c |= *(uchar*)(b+3)<<24; + *p++ = qRgba(((c & red_mask) >> red_shift) * red_scale, ((c & green_mask) >> green_shift) * green_scale, - ((c & blue_mask) >> blue_shift) * blue_scale); + ((c & blue_mask) >> blue_shift) * blue_scale, + transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff); b += nbits/8; } } |