sw reqif-xhtml export: fix export of transparent TIF
Since commit 22b50f1937de67e4ad9e692d6964aa5b8d33af7a (use libtiff for
tiff import, 2022-05-21), transparent TIFs are imported correctly.
As the result, reqif export started to output the transparent TIF
images as GIFs, because XOutFlags::UseGifIfSensible handles case of
transparency, and XOutFlags::UseNativeIfPossible didn't handle TIF.
Additionally, the resulting mediatype was reported incorrectly:
<reqif-xhtml:object data="[...].gif" type="image/tiff" ... >
1. Handle TIFs in XOutBitmap::WriteGraphic when XOutFlags::UseNativeIfPossible
is specified.
2. Return the corrected mediatype from XOutBitmap::WriteGraphic,
to inform the caller about the possible change.
3. Remove the XOutFlags::UseGifIfSensible flag when doing the
reqif export, to avoid the format change at all.
Change-Id: I99f7cfb8d12ef66d372700ec810bd8b269868ffd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149744
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/include/svx/xoutbmp.hxx b/include/svx/xoutbmp.hxx
index 43a666d..d2137f6 100644
--- a/include/svx/xoutbmp.hxx
+++ b/include/svx/xoutbmp.hxx
@@ -59,7 +59,8 @@ public:
static ErrCode WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
const OUString& rFilterName, const XOutFlags nFlags,
const Size* pMtfSize_100TH_MM = nullptr,
const css::uno::Sequence< css::beans::PropertyValue >* pFilterData = nullptr);
const css::uno::Sequence< css::beans::PropertyValue >* pFilterData = nullptr,
OUString* pMediaType = nullptr );
static bool GraphicToBase64(const Graphic& rGraphic, OUString& rOUString,
bool bAddPrefix = true,
ConvertDataFormat aTargetFormat = ConvertDataFormat::Unknown);
diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx
index 7241fed..d392426 100644
--- a/svx/source/xoutdev/_xoutbmp.cxx
+++ b/svx/source/xoutdev/_xoutbmp.cxx
@@ -30,10 +30,13 @@
#include <vcl/cvtgrf.hxx>
#include <memory>
#include <com/sun/star/beans/XPropertySet.hpp>
constexpr OUStringLiteral FORMAT_BMP = u"bmp";
constexpr OUStringLiteral FORMAT_GIF = u"gif";
constexpr OUStringLiteral FORMAT_JPG = u"jpg";
constexpr OUStringLiteral FORMAT_PNG = u"png";
constexpr OUStringLiteral FORMAT_TIF = u"tif";
constexpr OUStringLiteral FORMAT_WEBP = u"webp";
using namespace com::sun::star;
@@ -104,7 +107,8 @@ Graphic XOutBitmap::MirrorGraphic( const Graphic& rGraphic, const BmpMirrorFlags
ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
const OUString& rFilterName, const XOutFlags nFlags,
const Size* pMtfSize_100TH_MM,
const css::uno::Sequence< css::beans::PropertyValue >* pFilterData )
const css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
OUString* pMediaType )
{
if( rGraphic.GetType() == GraphicType::NONE )
return ERRCODE_NONE;
@@ -183,6 +187,7 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
case GfxLinkType::NativeJpg: aExt = FORMAT_JPG; break;
case GfxLinkType::NativePng: aExt = FORMAT_PNG; break;
case GfxLinkType::NativeTif: aExt = FORMAT_TIF; break;
case GfxLinkType::NativeWebp: aExt = FORMAT_WEBP; break;
default:
@@ -197,6 +202,9 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
if( !(nFlags & XOutFlags::DontAddExtension) )
aURL.setExtension( aExt );
rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
if (pMediaType)
if (auto xGraphic = rGraphic.GetXGraphic().query<css::beans::XPropertySet>())
xGraphic->getPropertyValue("MimeType") >>= *pMediaType;
SfxMedium aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE | StreamMode::SHARE_DENYNONE | StreamMode::TRUNC);
SvStream* pOStm = aMedium.GetOutStream();
@@ -308,6 +316,8 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName,
if( !(nFlags & XOutFlags::DontAddExtension) )
aURL.setExtension( aExt );
rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
if (pMediaType)
*pMediaType = rFilter.GetExportFormatMediaType(nFilter);
nErr = ExportGraphic( aGraphic, aURL, rFilter, nFilter, pFilterData );
}
}
diff --git a/sw/qa/extras/htmlexport/data/reqif-transparent-tif-img.odt b/sw/qa/extras/htmlexport/data/reqif-transparent-tif-img.odt
new file mode 100644
index 0000000..278cf9e
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/reqif-transparent-tif-img.odt
Binary files differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index ca9b816..1dd8dff 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -2488,6 +2488,29 @@ CPPUNIT_TEST_FIXTURE(HtmlExportTest, testTdf153923)
assertXPath(pDoc, "/html/body//dd");
}
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIfTransparentTifImg)
{
// reqIf export must keep the TIF encoding of the image
createSwDoc("reqif-transparent-tif-img.odt");
ExportToReqif();
SvMemoryStream aStream;
WrapReqifFromTempFile(aStream);
xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
assertXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object[1]", "type", "image/tiff");
OUString imageName = getXPath(pXmlDoc, "//reqif-xhtml:p/reqif-xhtml:object[1]", "data");
// Without the accompanying fix in place, this test would have failed,
// ending with .gif, because XOutFlags::UseGifIfSensible flag combined
// with the transparent image would result in GIF export
CPPUNIT_ASSERT(imageName.endsWith(".tif"));
INetURLObject aURL(maTempFile.GetURL());
aURL.setName(imageName);
GraphicDescriptor aDescriptor(aURL);
aDescriptor.Detect();
CPPUNIT_ASSERT_EQUAL(GraphicFileFormat::TIF, aDescriptor.GetFileFormat());
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx
index 85caaff8..acfeec1 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -1951,18 +1951,21 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
Size aMM100Size = o3tl::convert( rSize.GetSize(),
o3tl::Length::twip, o3tl::Length::mm100 );
OUString aFilterName("");
OUString aFilterName;
if (rWrt.mbReqIF && !bWritePNGFallback)
if (rWrt.mbReqIF)
{
// Writing image without fallback PNG in ReqIF mode: force PNG
// output.
// But don't force it when writing the original format and we'll write PNG inside
// that.
aFilterName = "PNG";
nFlags &= ~XOutFlags::UseNativeIfPossible;
// In ReqIF mode, do not try to write GIF for other image types
nFlags &= ~XOutFlags::UseGifIfSensible;
aMimeType = "image/png";
if (!bWritePNGFallback)
{
// Writing image without fallback PNG in ReqIF mode: force PNG
// output.
// But don't force it when writing the original format and we'll write PNG inside
// that.
aFilterName = "PNG";
nFlags &= ~XOutFlags::UseNativeIfPossible;
}
}
const Graphic& rGraphic = pGrfNd->GetGrf();
@@ -1971,6 +1974,8 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
if (!rGraphic.isAvailable())
const_cast<Graphic&>(rGraphic).makeAvailable();
OUString aMimeTypeOverride;
if (rWrt.mbReqIF && bWritePNGFallback)
{
// ReqIF: force native data if possible.
@@ -1982,7 +1987,7 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
else if (rGraphic.GetGfxLink().IsEMF())
{
aFilterName = "emf";
aMimeType = "image/x-emf"; // avoid image/x-wmf
aMimeTypeOverride = "image/x-emf"; // avoid image/x-wmf
}
else if (pVectorGraphicData && pVectorGraphicData->getType() == VectorGraphicDataType::Wmf)
{
@@ -1991,12 +1996,12 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
else if (rGraphic.GetGfxLink().GetType() == GfxLinkType::NativeTif)
{
aFilterName = "tif";
aMimeType = "image/tiff"; // avoid image/x-vclgraphic
aMimeTypeOverride = "image/tiff"; // avoid image/x-vclgraphic
}
}
ErrCode nErr = XOutBitmap::WriteGraphic( rGraphic, aGraphicURL,
aFilterName, nFlags, &aMM100Size );
aFilterName, nFlags, &aMM100Size, nullptr, &aMimeType );
if( nErr )
{
rWrt.m_nWarn = WARN_SWG_POOR_LOAD;
@@ -2005,6 +2010,8 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFra
aGraphicURL = URIHelper::SmartRel2Abs(
INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
URIHelper::GetMaybeFileHdl() );
if (!aMimeTypeOverride.isEmpty())
aMimeType = aMimeTypeOverride;
}
else
{