summaryrefslogtreecommitdiff
path: root/vcl/source/bitmap/dibtools.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/bitmap/dibtools.cxx')
-rw-r--r--vcl/source/bitmap/dibtools.cxx162
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