diff options
Diffstat (limited to 'vcl/source/bitmap/dibtools.cxx')
-rw-r--r-- | vcl/source/bitmap/dibtools.cxx | 162 |
1 files changed, 91 insertions, 71 deletions
diff --git a/vcl/source/bitmap/dibtools.cxx b/vcl/source/bitmap/dibtools.cxx index cd7155e47935..e7a0d4ed8c7f 100644 --- a/vcl/source/bitmap/dibtools.cxx +++ b/vcl/source/bitmap/dibtools.cxx @@ -34,6 +34,7 @@ #include <vcl/bitmapex.hxx> #include <vcl/outdev.hxx> #include <vcl/BitmapWriteAccess.hxx> +#include <vcl/ColorMask.hxx> #include <memory> #define DIBCOREHEADERSIZE ( 12UL ) @@ -137,11 +138,6 @@ vcl::PixelFormat convertToBPP(sal_uInt16 nCount) vcl::PixelFormat::N24_BPP; } -bool isBitfieldCompression( ScanlineFormat nScanlineFormat ) -{ - return ScanlineFormat::N32BitTcMask == nScanlineFormat; -} - bool ImplReadDIBInfoHeader(SvStream& rIStm, DIBV5Header& rHeader, bool& bTopDown, bool bMSOFormat) { if (rIStm.remainingSize() <= 4) @@ -499,7 +495,7 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r { // we can't trust arbitrary-sourced index based formats to have correct indexes, so we exclude the pal formats // from raw read and force checking their colormap indexes - bNative = bTopDown && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ); + bNative = ( ( rAcc.IsBottomUp() != bTopDown ) && !bRLE && !bTCMask && ( rAcc.GetScanlineSize() == nAlignedWidth ) ); break; } @@ -1232,7 +1228,7 @@ bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess const & rAcc, sal_uLong { if(BITFIELDS == nCompression) { - const ColorMask& rMask = rAcc.GetColorMask(); + ColorMask rMask; SVBT32 aVal32; UInt32ToSVBT32( rMask.GetRedMask(), aVal32 ); @@ -1246,8 +1242,13 @@ bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess const & rAcc, sal_uLong rImageSize = rOStm.Tell(); - for( tools::Long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0; nY-- ) - rOStm.WriteBytes( rAcc.GetScanline(nY), nScanlineSize ); + if( rAcc.IsBottomUp() ) + rOStm.WriteBytes(rAcc.GetBuffer(), rAcc.Height() * rAcc.GetScanlineSize()); + else + { + for( tools::Long nY = rAcc.Height() - 1, nScanlineSize = rAcc.GetScanlineSize(); nY >= 0; nY-- ) + rOStm.WriteBytes( rAcc.GetScanline(nY), nScanlineSize ); + } } else if((RLE_4 == nCompression) || (RLE_8 == nCompression)) { @@ -1266,60 +1267,88 @@ bool ImplWriteDIBBits(SvStream& rOStm, BitmapReadAccess const & rAcc, sal_uLong // (other cases are not written below) const auto ePixelFormat(convertToBPP(rAcc.GetBitCount())); const sal_uLong nAlignedWidth(AlignedWidth4Bytes(rAcc.Width() * sal_Int32(ePixelFormat))); + bool bNative(false); - rImageSize = rOStm.Tell(); - - const tools::Long nWidth(rAcc.Width()); - const tools::Long nHeight(rAcc.Height()); - std::vector<sal_uInt8> aBuf(nAlignedWidth); - switch(ePixelFormat) + switch(rAcc.GetScanlineFormat()) { - case vcl::PixelFormat::N8_BPP: + case ScanlineFormat::N1BitMsbPal: + case ScanlineFormat::N8BitPal: + case ScanlineFormat::N24BitTcBgr: { - for( tools::Long nY = nHeight - 1; nY >= 0; nY-- ) + if(rAcc.IsBottomUp() && (rAcc.GetScanlineSize() == nAlignedWidth)) { - sal_uInt8* pTmp = aBuf.data(); - Scanline pScanline = rAcc.GetScanline( nY ); - - for( tools::Long nX = 0; nX < nWidth; nX++ ) - *pTmp++ = rAcc.GetIndexFromData( pScanline, nX ); - - rOStm.WriteBytes(aBuf.data(), nAlignedWidth); + bNative = true; } + + break; } - break; - case vcl::PixelFormat::N24_BPP: + default: { - //valgrind, zero out the trailing unused alignment bytes - size_t nUnusedBytes = nAlignedWidth - nWidth * 3; - memset(aBuf.data() + nAlignedWidth - nUnusedBytes, 0, nUnusedBytes); + break; } - [[fallthrough]]; - // #i59239# fallback to 24 bit format, if bitcount is non-default - default: + } + + rImageSize = rOStm.Tell(); + + if(bNative) + { + rOStm.WriteBytes(rAcc.GetBuffer(), nAlignedWidth * rAcc.Height()); + } + else + { + const tools::Long nWidth(rAcc.Width()); + const tools::Long nHeight(rAcc.Height()); + std::vector<sal_uInt8> aBuf(nAlignedWidth); + switch(ePixelFormat) { - BitmapColor aPixelColor; + case vcl::PixelFormat::N8_BPP: + { + for( tools::Long nY = nHeight - 1; nY >= 0; nY-- ) + { + sal_uInt8* pTmp = aBuf.data(); + Scanline pScanline = rAcc.GetScanline( nY ); + + for( tools::Long nX = 0; nX < nWidth; nX++ ) + *pTmp++ = rAcc.GetIndexFromData( pScanline, nX ); + + rOStm.WriteBytes(aBuf.data(), nAlignedWidth); + } + } + break; - for( tools::Long nY = nHeight - 1; nY >= 0; nY-- ) + case vcl::PixelFormat::N24_BPP: { - sal_uInt8* pTmp = aBuf.data(); + //valgrind, zero out the trailing unused alignment bytes + size_t nUnusedBytes = nAlignedWidth - nWidth * 3; + memset(aBuf.data() + nAlignedWidth - nUnusedBytes, 0, nUnusedBytes); + } + [[fallthrough]]; + // #i59239# fallback to 24 bit format, if bitcount is non-default + default: + { + BitmapColor aPixelColor; - for( tools::Long nX = 0; nX < nWidth; nX++ ) + for( tools::Long nY = nHeight - 1; nY >= 0; nY-- ) { - // when alpha is used, this may be non-24bit main bitmap, so use GetColor - // instead of GetPixel to ensure RGB value - aPixelColor = rAcc.GetColor( nY, nX ); + sal_uInt8* pTmp = aBuf.data(); - *pTmp++ = aPixelColor.GetBlue(); - *pTmp++ = aPixelColor.GetGreen(); - *pTmp++ = aPixelColor.GetRed(); - } + for( tools::Long nX = 0; nX < nWidth; nX++ ) + { + // when alpha is used, this may be non-24bit main bitmap, so use GetColor + // instead of GetPixel to ensure RGB value + aPixelColor = rAcc.GetColor( nY, nX ); + + *pTmp++ = aPixelColor.GetBlue(); + *pTmp++ = aPixelColor.GetGreen(); + *pTmp++ = aPixelColor.GetRed(); + } - rOStm.WriteBytes(aBuf.data(), nAlignedWidth); + rOStm.WriteBytes(aBuf.data(), nAlignedWidth); + } } + break; } - break; } } @@ -1342,32 +1371,23 @@ bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess c aHeader.nHeight = rAcc.Height(); aHeader.nPlanes = 1; - if(isBitfieldCompression(rAcc.GetScanlineFormat())) + // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are + // not handled properly below (would have to set color + // masks, and nCompression=BITFIELDS - but color mask is + // not set for formats != *_TC_*). Note that this very + // problem might cause trouble at other places - the + // introduction of 32 bit RGBA bitmaps is relatively + // recent. + // #i59239# discretize bitcount to 1,8,24 (other cases + // are not written below) + const auto ePixelFormat(convertToBPP(rAcc.GetBitCount())); + aHeader.nBitCount = sal_uInt16(ePixelFormat); + aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount); + + if (bCompressed) { - aHeader.nBitCount = 32; - aHeader.nSizeImage = rAcc.Height() * rAcc.GetScanlineSize(); - nCompression = BITFIELDS; - } - else - { - // #i5xxx# Limit bitcount to 24bit, the 32 bit cases are - // not handled properly below (would have to set color - // masks, and nCompression=BITFIELDS - but color mask is - // not set for formats != *_TC_*). Note that this very - // problem might cause trouble at other places - the - // introduction of 32 bit RGBA bitmaps is relatively - // recent. - // #i59239# discretize bitcount to 1,8,24 (other cases - // are not written below) - const auto ePixelFormat(convertToBPP(rAcc.GetBitCount())); - aHeader.nBitCount = sal_uInt16(ePixelFormat); - aHeader.nSizeImage = rAcc.Height() * AlignedWidth4Bytes(rAcc.Width() * aHeader.nBitCount); - - if (bCompressed) - { - if (ePixelFormat == vcl::PixelFormat::N8_BPP) - nCompression = RLE_8; - } + if (ePixelFormat == vcl::PixelFormat::N8_BPP) + nCompression = RLE_8; } if((rOStm.GetCompressMode() & SvStreamCompressFlags::ZBITMAP) && (rOStm.GetVersion() >= SOFFICE_FILEFORMAT_40)) @@ -1477,7 +1497,7 @@ bool ImplWriteDIBBody(const Bitmap& rBitmap, SvStream& rOStm, BitmapReadAccess c bool ImplWriteDIBFileHeader(SvStream& rOStm, BitmapReadAccess const & rAcc) { - const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : isBitfieldCompression(rAcc.GetScanlineFormat()) ? 3UL : 0UL)); + const sal_uInt32 nPalCount((rAcc.HasPalette() ? rAcc.GetPaletteEntryCount() : 0UL)); const sal_uInt32 nOffset(14 + DIBINFOHEADERSIZE + nPalCount * 4UL); rOStm.WriteUInt16( 0x4D42 ); // 'MB' from BITMAPFILEHEADER |