sw/qa/filter/md/data/embedded-image.md |    1 +
 sw/qa/filter/md/md.cxx                 |   23 +++++++++++++++++++++++
 sw/source/filter/md/swmd.cxx           |   18 +++++++++++++++++-
 3 files changed, 41 insertions(+), 1 deletion(-)

New commits:
commit 169e1f3b914ac590b3719b8129b4f0913d4da228
Author:     Miklos Vajna <[email protected]>
AuthorDate: Wed Oct 1 08:35:21 2025 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Wed Oct 1 11:40:34 2025 +0200

    sw markdown filter: import images with 'data:' URLs
    
    Open the bugdoc which contains a data:image/png;base64,... image, the
    result in Writer is a placeholder image with bad size.
    
    Checking what the HTML import does,
    sw::DocumentContentOperationsManager::InsertGraphic() doesn't get this
    'data:' URL, instead SwHTMLParser::InsertImage() checks for
    INetProtocol::Data and in that case initializes the Graphic and clears
    the URL.
    
    Fix the problem by handling this similar in
    SwMarkdownParser::InsertImage(): we can feed the 'data:' URL into an
    unloaded graphic, set its size and clear the URL.
    
    The export side of this is still missing.
    
    Change-Id: Iea4f6531dfa190e4bc3af14239f97ec9fcad4ae8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191709
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/sw/qa/filter/md/data/embedded-image.md 
b/sw/qa/filter/md/data/embedded-image.md
new file mode 100644
index 000000000000..d0b83e416fa5
--- /dev/null
+++ b/sw/qa/filter/md/data/embedded-image.md
@@ -0,0 +1 @@
+A 
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC/ElEQVR4nO2bPWgTYRjHf+nF2KuxpYMg+DEIForgJtTFwU3cdKqgS6UKCh0cioOTWUQsuggKKroICoIgflC0pUMpuIhL/QDFNqUhqdAqba4f9hzsoY2tzfXe93kueP815Lnn98ubu/eeS1K+7/v8x6nTbkA7iQDtBrSTCNBuQDuJAO0GtJMIkD7geL7E7Z7HzM8tSB96xaQlD1bIl8h13OPbaJny9Cyd3UfYkBFt4a+IrYBCvsTFJXiAofsfuHnpkfpKEBFQCR8kDhKsC/hz2a8UbQlWBQTwU6vAB9GUYE1AtfBBtCRYERAWPoiGBOMCCmMT5E6Ghw8iLcGogMLYBLmOu0yNrA8+iKQEowI+vcsz+SUafBApCcYEFItF9h3YQ+fVQ5iaMkpIMCbA8zyGh4fZf3BvTUkw+hUol8s1J8H4VaDWJFjZB9SSBGs7wVqRYPVeoBYkWL8bjLsEkXlAnCWITYTiKkF0KBpHCeJT4UoJGJYwNzcf6n2qzwVSKdMVw9sUn0m7rktraytDfW+50fXMmIS29t10dh8NPWYXXQFxgwfBFRDAv3wxwJ1z/WScjUbqRoEHoRUQwPc+76f71GXGvI/4Bs5+UeFBQMBv+D7On74CwPeFSb7OjkeqawIeLAtYDt+z7LVx7zPej+l11TUFDxYF/AsewMdnZOY9i/5iqLpt7S3G4MGSgLXgg3iLM5RmR6uu+wve7BNl41eBteAbnM1k0024ThbXyZKpq6+qrg14MCygEj6dypBNN7HJacR1stQ7DdSlnNB1bcEDpEz9VLZYLNLc3MxA72uudT1c+nSjX+ttwoNBAQCDr95w/cwTgzs8u/Bg+CS4q2UbTTtdI7Uk4MGwgK3bt3Dh1gkad0STIAUPFi6DUSVIw
 
oOlfcB6JUjDg8WdYFgJGvBg+V6gWgla8CBwN7iWBE14EJoHrCZBGx4ER2KVEtqO6cOD4Z1gNSnkSzx9MMjxs4fV4UFBQNyS/F9AuwHtJAK0G9BOIkC7Ae0kArQb0M5PVUf6O5GvKMMAAAAASUVORK5CYII=)
 Z
diff --git a/sw/qa/filter/md/md.cxx b/sw/qa/filter/md/md.cxx
index 217d212a90f8..847ad0bf5ad1 100644
--- a/sw/qa/filter/md/md.cxx
+++ b/sw/qa/filter/md/md.cxx
@@ -27,6 +27,7 @@
 #include <ndtxt.hxx>
 #include <fmturl.hxx>
 #include <textcontentcontrol.hxx>
+#include <fmtfsize.hxx>
 
 namespace
 {
@@ -817,6 +818,28 @@ CPPUNIT_TEST_FIXTURE(Test, testTastListItemsMdExport)
     CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testEmbeddedImageMdImport)
+{
+    // Given a document with an embedded image:
+    // When importing that document:
+    setImportFilterName("Markdown");
+    createSwDoc("embedded-image.md");
+
+    // Then make sure the embedded image gets imported, with the correct size:
+    SwDocShell* pDocShell = getSwDocShell();
+    SwDoc* pDoc = pDocShell->GetDoc();
+    sw::FrameFormats<sw::SpzFrameFormat*>& rFlys = *pDoc->GetSpzFrameFormats();
+    CPPUNIT_ASSERT(!rFlys.empty());
+    sw::SpzFrameFormat& rFly = *rFlys[0];
+    const SwFormatFrameSize& rSize = rFly.GetFrameSize();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 960
+    // - Actual  : 500 (MD_MIN_IMAGE_WIDTH_IN_TWIPS)
+    // i.e. the image wasn't imported, had the default minimal size.
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(960), rSize.GetWidth());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(960), rSize.GetHeight());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/filter/md/swmd.cxx b/sw/source/filter/md/swmd.cxx
index 22d494d54e92..ccccdd2cb141 100644
--- a/sw/source/filter/md/swmd.cxx
+++ b/sw/source/filter/md/swmd.cxx
@@ -632,6 +632,17 @@ void SwMarkdownParser::InsertImage(const MDImage& rImg)
 
     Graphic aGraphic;
     INetURLObject aGraphicURL(sGrfNm);
+    if (aGraphicURL.GetProtocol() == INetProtocol::Data)
+    {
+        // 'data:' URL: read that here, initialize aGraphic anc clear sGrfNm.
+        std::unique_ptr<SvMemoryStream> pStream = aGraphicURL.getData();
+        if (pStream)
+        {
+            GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+            aGraphic = rFilter.ImportUnloadedGraphic(*pStream);
+            sGrfNm.clear();
+        }
+    }
 
     if (!sGrfNm.isEmpty())
     {
@@ -639,13 +650,18 @@ void SwMarkdownParser::InsertImage(const MDImage& rImg)
     }
 
     Size aGrfSz(0, 0);
-    if (allowAccessLink(*m_xDoc) && !aGraphicURL.IsExoticProtocol())
+    if (allowAccessLink(*m_xDoc) && !aGraphicURL.IsExoticProtocol() && 
!sGrfNm.isEmpty())
     {
         GraphicDescriptor aDescriptor(aGraphicURL);
         if (aDescriptor.Detect(true))
             aGrfSz
                 = o3tl::convert(aDescriptor.GetSizePixel(), o3tl::Length::px, 
o3tl::Length::twip);
     }
+    else if (aGraphic.GetType() == GraphicType::Bitmap)
+    {
+        // We have an unloaded graphic in aGraphic, read its size.
+        aGrfSz = o3tl::convert(aGraphic.GetSizePixel(), o3tl::Length::px, 
o3tl::Length::twip);
+    }
 
     tools::Long nWidth = 0;
     tools::Long nHeight = 0;

Reply via email to