From 547386eef9b1723812dfdab5aed33e9025a372c6 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 14 Jun 2021 12:09:01 +0200 Subject: sw XHTML/reqif export, OLE data for transparent images: avoid black background Once a semi-transparent images is exported to reqif in OLE mode, the native data is 24bit BMP. This needs some solid color as a background for the transparent pixels. The OLE presentation data had white, the OLE native data had black, so this was inconsistent. Fix the problem by going with white for the native data as well. Change-Id: I1b5e9ed37369b541425cfcd7f690e1b0bba97ddc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117144 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- sw/qa/extras/htmlexport/data/transparent.png | Bin 0 -> 2950 bytes sw/qa/extras/htmlexport/htmlexport.cxx | 48 ++++++++++++++++++++++++++- sw/source/filter/html/htmlreqifreader.cxx | 8 ++++- 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 sw/qa/extras/htmlexport/data/transparent.png (limited to 'sw') diff --git a/sw/qa/extras/htmlexport/data/transparent.png b/sw/qa/extras/htmlexport/data/transparent.png new file mode 100644 index 000000000000..936980b0a19b Binary files /dev/null and b/sw/qa/extras/htmlexport/data/transparent.png differ diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 8642b5baa4f5..5d9232c8b286 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -141,6 +142,7 @@ bool TestReqIfRtfReader::WriteObjectData(SvStream& rOLE) struct OLE1Reader { sal_uInt32 m_nNativeDataSize; + std::vector m_aNativeData; sal_uInt32 m_nPresentationDataSize; OLE1Reader(SvStream& rStream); @@ -162,7 +164,8 @@ OLE1Reader::OLE1Reader(SvStream& rStream) rStream.SeekRel(nData); rStream.ReadUInt32(m_nNativeDataSize); - rStream.SeekRel(m_nNativeDataSize); + m_aNativeData.resize(m_nNativeDataSize); + rStream.ReadBytes(m_aNativeData.data(), m_aNativeData.size()); rStream.ReadUInt32(nData); // OLEVersion for presentation data CPPUNIT_ASSERT(rStream.good()); @@ -1801,6 +1804,49 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifEmbedShapeAsPNGCustomDPI) OUString::number(aPixelSize.getWidth())); } +CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOleBmpTransparent) +{ + // Given a document with a transparent image: + loadURL("private:factory/swriter", nullptr); + OUString aImageURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "transparent.png"; + uno::Sequence aArgs = { + comphelper::makePropertyValue("FileName", aImageURL), + }; + dispatchCommand(mxComponent, ".uno:InsertGraphic", aArgs); + + // When exporting to reqif with ExportImagesAsOLE=true: + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence aStoreProperties = { + comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")), + comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")), + comphelper::makePropertyValue("ExportImagesAsOLE", true), + }; + xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties); + + // Then make sure the transparent pixel turns into white: + OUString aRtfUrl = GetOlePath(); + SvMemoryStream aRtf; + HtmlExportTest::wrapRtfFragment(aRtfUrl, aRtf); + tools::SvRef xReader(new TestReqIfRtfReader(aRtf)); + CPPUNIT_ASSERT(xReader->CallParser() != SvParserState::Error); + SvMemoryStream aOle1; + CPPUNIT_ASSERT(xReader->WriteObjectData(aOle1)); + OLE1Reader aOle1Reader(aOle1); + SvMemoryStream aBitmapStream(aOle1Reader.m_aNativeData.data(), aOle1Reader.m_aNativeData.size(), + StreamMode::READ); + Bitmap aBitmap; + ReadDIB(aBitmap, aBitmapStream, /*bFileHeader=*/true); + Size aBitmapSize = aBitmap.GetSizePixel(); + BitmapEx aBitmapEx(aBitmap); + Color nActualColor + = aBitmapEx.GetPixelColor(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: Color: R:255 G:255 B:255 A:0 + // - Actual : Color: R:0 G:0 B:0 A:0 + // i.e. the bitmap without an alpha channel was black, not white. + CPPUNIT_ASSERT_EQUAL(COL_WHITE, nActualColor); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx index 8cd2728ef7c6..30c027edb351 100644 --- a/sw/source/filter/html/htmlreqifreader.cxx +++ b/sw/source/filter/html/htmlreqifreader.cxx @@ -545,7 +545,13 @@ bool WrapGraphicInRtf(const Graphic& rGraphic, const SwFrameFormat& rFormat, SvS // NativeDataSize SvMemoryStream aNativeData; - if (GraphicConverter::Export(aNativeData, rGraphic, ConvertDataFormat::BMP) != ERRCODE_NONE) + + // Set white background for the semi-transparent pixels. + BitmapEx aBitmapEx = rGraphic.GetBitmapEx(); + Bitmap aBitmap = aBitmapEx.GetBitmap(/*aTransparentReplaceColor=*/COL_WHITE); + + if (GraphicConverter::Export(aNativeData, BitmapEx(aBitmap), ConvertDataFormat::BMP) + != ERRCODE_NONE) { SAL_WARN("sw.html", "WrapGraphicInRtf: bmp conversion failed"); } -- cgit