Replace embedded picture by a linked picture in Impress macro

First of all, I think it has noting to do with my question but just in case that is libreoffice version I’m using.
Version: 7.4.7.2 / LibreOffice Community
Build ID: 40(Build:2)
CPU threads: 28; OS: Linux 6.1; UI render: default; VCL: kf5 (cairo+wayland)
Locale: fr-CA (fr_CA.UTF-8); UI: fr-FR
Debian package version: 4:7.4.7-1+deb12u10
Calc: threaded

I’ve created a very big slide show with many pictures and animations. It’s big because the pictures are embedded and not linked. Sometime the pictures are inserted with no alteration. But many time the pictures are crop, resize, rotated and animated. To shrink the document, I want to write a macro that will save the picture of each slide and reinsert it (replace) as link. To summarize, the expected result is noting seems to append in the document, but the pictures are linked, not integrated and the impress file is much more smaller.

I did manage to write a macro doing the job. The one bellow is a very simplify version to illustrate the problem. As is, it do the job for a 1 slide document with a single picture embedded in it. It work perfectly if the picture is not altered (no crop, rotation, resizing). The picture go from embedded state to linked state and the animations are preserved. But if alteration had been done (crop, resize…) the replacement is done but the resulting picture is deformed. My understanding is the picture is saved with the alterations (seem ok for me) but those same alteration are reapplied on it in the replacement process. Someone has an idea to correct the problem. Maybe a way to save the genuine picture (without alteration), or a way to reimport it in such a way the alterations will not be reapplied. The first option seem less good because for example if in a specific picture I managed to isolate only one person in a group it result in a smaller picture, the one I just need. But maybe the only way will be to keep the entire genuine picture.

The sample macro is the following on. I join the demo file to test it
Demo.odp (256.6 KB)

Sub Main

Dim oDoc As Object, oPages As Object, oPage As Object
Dim oShape As Object, oExporter As Object, oProvider As Object
Dim fullURL As String
Dim args(1) As New com.sun.star.beans.PropertyValue


'STEP 1 : Get the embedded Picture in the slide (the only object in the slide)
oPage = ThisComponent.getDrawPages().getByIndex(0) 'get the slide
oShape = oPage.getByIndex(0)  'get the image in the slide (the unique object in the specific slide)
fullURL = CurDir  & "/image.png" & fileName


'STEP 2 : Save the embedded picture as is
oExporter = createUnoService("com.sun.star.drawing.GraphicExportFilter")
oExporter.setSourceDocument(oShape)
args(0).Name = "URL"
args(0).Value = "file://" & fullURL
args(1).Name = "MediaType"
args(1).Value = "image/png"
oExporter.filter(args())

'STEP 3 : Replace the embedded picture by a linked one 
'         without disturbing the animation
oProvider = createUnoService("com.sun.star.graphic.GraphicProvider")
args(0).Name = "URL"
args(0).Value = "file://"& fullURL
args(1).Name = "LoadAsLink"
args(1).Value = True
oShape.Graphic =  oProvider.queryGraphic(args()) 'replace embedded picture by its linked version without loosing animations

End Sub

There is already an extension which seems (partially?) to do what you like:
# Extract embedded images and replace embedded images with linked images: PicExtract
on

Could it be helpful for you?

The description look very interesting. It seem very simple if it effectively preserve animation. But I can’t figure how to use it. I’ve install the extension, restart office, but no new menu item, no button, nothing. I’ve try in Impress, Calc, and Writer with the same result. Any clue?

⇒ Tools ⇒ Macros ⇒ Run Macros ⇒ My_Macros ⇒ PicExtract ⇒ PicExtract ……

Very sorry, but it don’t seem able to work with Impress (visual basic error). I traced back the problem to the fact that Impress is a collection of DrawPage object and the extension expect a document with only one DrawPage (oDoc.DrawPage). It’s why it works in Writer as the extension is design for. I also doubt it will support animation preservation, a concept absent from Writer, even I manage a way to adapt the code to Impress.

for each dp in oDoc.DrawPages

next dp

I know that. It’s exactly my point. Base on that it mean I should revise all the PicExtract extension code to adapt to a multiple DrawPage document. Loops must be set at right place. And probably many other adaptation must be set in place. So the PicExtract extension maybe could be an inspiration, but clearly does not fit the situation. Ant as I say earlier, we can doubt it will treat the animation problem.

Try replace step 2 with:

    stream = oShape.GraphicStream
    oSimpleFileAccess = createUnoService("com.sun.star.ucb.SimpleFileAccess")
    oSimpleFileAccess.WriteFile("file://" & fullURL, stream)
1 Like

Thank you elmau. I’ve integrated your solution in my full version (with all require loops) and it works perfectly.

That close this subject

I’m still looking for a solution on my side. When using the Impress function “save” (Right-clic on the image and Save) Impress offer to save the modified or the original picture. With the original one, no alteration are save. The following first image is exported from my code. The second one manually with Impress save operation.

And if I use the replace part of my code with that manually exported picture it work. Obviously, save the original picture is possible, but at that point, I still do not know how to do it in a macro.

What kind of programmer are you?

Sub Main()
If ThisComponent.supportsService("com.sun.star.text.TextDocument") then
    extractPictures(ThisComponent.DrawPage)
else
    for each dp in ThisComponent.DrawPages
        extractPictures(dp)
    next dp
end if
End Sub

Sub extractPictures(oPage)
    oShape = oPage.getByIndex(0)
... and so on...

fxxx Sorry this was for other post