summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndras Timar <andras.timar@collabora.com>2022-01-03 22:12:01 +0100
committerXisco Fauli <xiscofauli@libreoffice.org>2022-01-10 19:26:41 +0100
commite16a9fda5ab95f1abc0d3d6ca0437081384aa36b (patch)
tree997f4c657a66941328717d7f516c4c247215f89d
parent0c54ddf5237914560a121453b41c8e3a50f02019 (diff)
tdf#73523 support WinBMPv3-NT version of BMP files (found in Visio files)
It is a special case when there are additional 12 bytes of color bitfields after the info header. See also the useful comments at https://searchfox.org/mozilla-central/source/image/decoders/nsBMPDecoder.cpp#47 It turned out we generate this type of BMP files internally from EMF files, but in that case the bfOffBits of BITMAPFILEHEADER struct points to the pixel data. In case of Visio, bfOffBits points to the color mask. There was no better solution than preventing jumping back in the stream. Change-Id: I97f0fd4f184ea77beeab8b22fc98fdb78472d9bb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127920 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127927 Tested-by: Jenkins Reviewed-by: Andras Timar <andras.timar@collabora.com> (cherry picked from commit 3a0d539b3a8a76efc2cdac04c658645fe750bec4) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128158 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r--vcl/qa/cppunit/BmpFilterTest.cxx13
-rw-r--r--vcl/qa/cppunit/data/tdf73523.bmpbin0 -> 70 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmp (renamed from vcl/qa/cppunit/graphicfilter/data/bmp/fail/crash-1.bmp)bin632 -> 632 bytes
-rw-r--r--vcl/source/bitmap/dibtools.cxx34
4 files changed, 37 insertions, 10 deletions
diff --git a/vcl/qa/cppunit/BmpFilterTest.cxx b/vcl/qa/cppunit/BmpFilterTest.cxx
index 20be739d0e98..1ab7bc2a0a4a 100644
--- a/vcl/qa/cppunit/BmpFilterTest.cxx
+++ b/vcl/qa/cppunit/BmpFilterTest.cxx
@@ -204,4 +204,17 @@ CPPUNIT_TEST_FIXTURE(BmpFilterTest, testBMP_V2)
CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, aBitmap.GetPixelColor(2, 2));
}
+CPPUNIT_TEST_FIXTURE(BmpFilterTest, testTdf73523)
+{
+ SvFileStream aFileStream(getFullUrl(u"tdf73523.bmp"), StreamMode::READ);
+ Graphic aGraphic;
+ CPPUNIT_ASSERT(BmpReader(aFileStream, aGraphic));
+ auto aBitmap = aGraphic.GetBitmapEx();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: c[80000000]
+ // - Actual : c[00000000]
+ // i.e. the pixel is red not black
+ CPPUNIT_ASSERT_EQUAL(COL_RED, aBitmap.GetPixelColor(0, 0));
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/data/tdf73523.bmp b/vcl/qa/cppunit/data/tdf73523.bmp
new file mode 100644
index 000000000000..f4364ea3e841
--- /dev/null
+++ b/vcl/qa/cppunit/data/tdf73523.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/crash-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmp
index 84b6c35c87e6..84b6c35c87e6 100644
--- a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/crash-1.bmp
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/crash-1.bmp
Binary files differ
diff --git a/vcl/source/bitmap/dibtools.cxx b/vcl/source/bitmap/dibtools.cxx
index 55e287e44411..b1e7648d0282 100644
--- a/vcl/source/bitmap/dibtools.cxx
+++ b/vcl/source/bitmap/dibtools.cxx
@@ -246,8 +246,18 @@ bool ImplReadDIBInfoHeader(SvStream& rIStm, DIBV5Header& rHeader, bool& bTopDown
readUInt32( rHeader.nV5ProfileSize );
readUInt32( rHeader.nV5Reserved );
+ // Read color mask. An additional 12 bytes of color bitfields follow the info header (WinBMPv3-NT)
+ sal_uInt32 nColorMask = 0;
+ if (BITFIELDS == rHeader.nCompression && DIBINFOHEADERSIZE == rHeader.nSize)
+ {
+ rIStm.ReadUInt32( rHeader.nV5RedMask );
+ rIStm.ReadUInt32( rHeader.nV5GreenMask );
+ rIStm.ReadUInt32( rHeader.nV5BlueMask );
+ nColorMask = 12;
+ }
+
// seek to EndPos
- if (!checkSeek(rIStm, aStartPos + rHeader.nSize))
+ if (!checkSeek(rIStm, aStartPos + rHeader.nSize + nColorMask))
return false;
}
@@ -530,14 +540,12 @@ bool ImplReadDIBBits(SvStream& rIStm, DIBV5Header& rHeader, BitmapWriteAccess& r
}
else
{
- // Read color mask
- if(bTCMask && BITFIELDS == rHeader.nCompression)
- {
- rIStm.SeekRel( -12 );
- rIStm.ReadUInt32( nRMask );
- rIStm.ReadUInt32( nGMask );
- rIStm.ReadUInt32( nBMask );
- }
+ if (rHeader.nV5RedMask > 0)
+ nRMask = rHeader.nV5RedMask;
+ if (rHeader.nV5GreenMask > 0)
+ nGMask = rHeader.nV5GreenMask;
+ if (rHeader.nV5BlueMask > 0)
+ nBMask = rHeader.nV5BlueMask;
const tools::Long nWidth(rHeader.nWidth);
const tools::Long nHeight(rHeader.nHeight);
@@ -908,7 +916,13 @@ bool ImplReadDIBBody(SvStream& rIStm, Bitmap& rBmp, AlphaMask* pBmpAlpha, sal_uL
if (nOffset)
{
- pIStm->SeekRel(nOffset - (pIStm->Tell() - nStmPos));
+ // It is problematic to seek backwards. We are at the
+ // end of BITMAPINFOHEADER or 12 bytes further in case
+ // of WinBMPv3-NT format. It is possible to seek forward
+ // though because a gap may be there.
+ sal_Int32 nSeekRel = nOffset - (pIStm->Tell() - nStmPos);
+ if (nSeekRel > 0)
+ pIStm->SeekRel(nSeekRel);
}
const sal_Int64 nBitsPerLine (static_cast<sal_Int64>(aHeader.nWidth) * static_cast<sal_Int64>(aHeader.nBitCount));