tdf168237 tdf168886 vcl: Fix image scaling of EMF+ export

Previously, EMF+ images could be exported with incorrect scaling because
the original reference device metrics were not preserved and applied
during the export process.

This patch fixes the scaling issue by extracting the original device pixel
size and physical dimensions from the "EMF_PLUS_HEADER_INFO" MetaAction
comment. If this data is present, the original image DPI is calculated
and compared against the current virtual output device's DPI. A new
SetPageTransform EMF+ record (with the UnitPixel flag 0x02) is then
injected to apply the precise scale factor, ensuring the exported image
retains its correct physical proportions.

Change-Id: I34bb7be5fe0466c288765f46b642d85e399b4ae1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/203187
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
This commit is contained in:
Bartosz Kosiorek
2026-05-08 04:18:12 +02:00
parent 39d901bfc3
commit ddbd78e13a
+32 -1
View File
@@ -107,7 +107,8 @@ enum class EmfPlusRecordType
SetAntiAliasMode = 0x401E,
SetInterpolationMode = 0x4021,
SetPixelOffsetMode = 0x4022,
SetCompositingQuality = 0x4024
SetCompositingQuality = 0x4024,
SetPageTransform = 0x4030
};
void EMFWriter::ImplBeginCommentRecord( sal_Int32 nCommentType )
@@ -1471,6 +1472,36 @@ void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
{
MetaCommentAction const*const pCommentAction(
static_cast<MetaCommentAction const*>(pAction));
SAL_INFO("vcl.filter", "MetaAction Comment: " << pCommentAction->GetComment()
<< " size: " << pCommentAction->GetDataSize());
if (pCommentAction->GetComment() == "EMF_PLUS_HEADER_INFO")
{
sal_Int32 nFrameLeft;
sal_Int32 nFrameTop;
sal_Int32 nFrameRight;
sal_Int32 nFrameBottom;
sal_Int32 nPixX;
sal_Int32 nPixY;
sal_Int32 nMmX;
sal_Int32 nMmY;
if (pCommentAction->GetDataSize() < 32)
break;
SvMemoryStream rMF(const_cast<sal_uInt8 *>(pCommentAction->GetData()), pCommentAction->GetDataSize(), StreamMode::READ);
rMF.ReadInt32(nFrameLeft).ReadInt32(nFrameTop).ReadInt32(nFrameRight).ReadInt32(nFrameBottom);
SAL_INFO ("vcl.filter", "EMF+ picture frame: " << nFrameLeft << "," << nFrameTop << " - " << nFrameRight << "," << nFrameBottom);
rMF.ReadInt32(nPixX).ReadInt32(nPixY).ReadInt32(nMmX).ReadInt32(nMmY);
SAL_INFO ("vcl.filter", "EMF+ ref device pixel size: " << nPixX << "x" << nPixY << " mm size: " << nMmX << "x" << nMmY);
if (nMmX == 0)
break;
ImplBeginCommentRecord(WIN_EMR_COMMENT_EMFPLUS);
ImplBeginPlusRecord(EmfPlusRecordType::SetPageTransform, 0x02);
// Calculate the scale factor by comparing current device DPI with original image DPI. 0x02 specifies UnitPixel.
m_rStm.WriteFloat(static_cast<float>(maVDev->GetDPIX()) / (static_cast<float>(nPixX) / static_cast<float>(nMmX) * 25.4f));
ImplEndPlusRecord();
ImplEndCommentRecord();
}
if (pCommentAction->GetComment() == "EMF_PLUS")
{
ImplBeginCommentRecord(WIN_EMR_COMMENT_EMFPLUS);