[Dropped] Insert image without file URL

Java, C++, C#, Delphi... - Using the UNO bridges
Post Reply
UnoNewbie
Posts: 3
Joined: Sat Oct 16, 2021 2:09 pm

[Dropped] Insert image without file URL

Post by UnoNewbie »

Hi there,

this is my first post. If this is not the appropriate section, please move this post.

I am trying to build OpenOffice Draw files from Java. I need to insert images without file (because rendered at runtime in a BufferedImage). Is there a way to circumvent writing the png temporarily to disk, inserting that file into Draw, unlinking the link and then remove the temporary file? I could not find any XNameContainer.insertByName alternative to do this or to build an url that is not pointing to a file.

Code in question:

Code: Select all

      BufferedImage img; 
      //img is rendered at runtime
      //and needs to be saved to a file to give this filename as reference later on
      //for example:
      ImageIO.write(img, "png", new File("/home/me/tmpfile.png")); //I would like to circumvent this step
      //OO Uno
      XComponentContext context = Bootstrap.bootstrap();
      XMultiComponentFactory mcf = context.getServiceManager();
      Object desktop = mcf.createInstanceWithContext("com.sun.star.frame.Desktop", context);
      XComponentLoader componentLdr = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop);
      XComponent xDrawComponent = componentLdr.loadComponentFromURL("private:factory/sdraw", "_blank", 0, new com.sun.star.beans.PropertyValue[0]);
      XDrawPagesSupplier xDrawPagesSupplier = (XDrawPagesSupplier) UnoRuntime.queryInterface(XDrawPagesSupplier.class, xDrawComponent);
      Object drawPages = xDrawPagesSupplier.getDrawPages();
      XIndexAccess xIndexedDrawPages = (XIndexAccess) UnoRuntime.queryInterface(XIndexAccess.class, drawPages);
      Object drawPage = xIndexedDrawPages.getByIndex(0);
      XDrawPage xDrawPage = (XDrawPage) UnoRuntime.queryInterface(XDrawPage.class, drawPage);
      XMultiServiceFactory xDrawFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, xDrawComponent);
      Object shape = xDrawFactory.createInstance("com.sun.star.drawing.GraphicObjectShape");
      XShape xShape = (XShape) UnoRuntime.queryInterface(XShape.class, shape);
      xShape.setSize(new Size(6050, 3000));
      xShape.setPosition(new Point(2000, 1000));
      XNameContainer bitmapContainer = UnoRuntime.queryInterface(XNameContainer.class,
          xDrawFactory.createInstance("com.sun.star.drawing.BitmapTable"));
      bitmapContainer.insertByName("testimg", "file:///home/me/tmpfile.png"); //what to do here to insert img directly instead of tmpfile.png?
      XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, shape);
      Object url = bitmapContainer.getByName("testimg");
      xPropSet.setPropertyValue("GraphicURL", url);
      xDrawPage.add(xShape);
      //temp-file is not used anymore and could be deleted
Thanks for any suggestion or stating that this is impossible (means: I have to use the file-workaround).
Last edited by MrProgrammer on Wed Feb 28, 2024 7:24 pm, edited 2 times in total.
Reason: Dropped: UnoNewbie decided to use original workaround
Office 6.0.7.3 on XUbuntu 18.04
User avatar
Zizi64
Volunteer
Posts: 11358
Joined: Wed May 26, 2010 7:55 am
Location: Budapest, Hungary

Re: Inserting image without file URL

Post by Zizi64 »

I need to insert images without file
A temporary file is a file, too. You need its URL if you want to insert it into an AOO document by your macro.

And probably you can not control the another application (to save the temporary file) from an AOO macro.

Maybe you can control the Clipboard content. you can paste it into the AOO document by your macro..
Tibor Kovacs, Hungary; LO7.5.8 /Win7-10 x64Prof.
PortableApps/winPenPack: LO3.3.0-7.6.2;AOO4.1.14
Please, edit the initial post in the topic: add the word [Solved] at the beginning of the subject line - if your problem has been solved.
UnoNewbie
Posts: 3
Joined: Sat Oct 16, 2021 2:09 pm

Re: Inserting image without file URL

Post by UnoNewbie »

Thanks for your reply. :)
Yes, of course a temporary file is a file - this is what I would like to circumvent. I have a Java application with existing Java POJO BufferedImage that should be inserted on a Draw page (no need to control the other application by AOO macro).
Maybe the clipboard is helpful. Copying the POJO BufferedImage to clipboard is possible, but unfortunately I could not find the correct interfaces to insert a BitmapImage via clipboard.

Do you have any hint towards inserting into the BitmapTable via clipboard?

Thanks again and in advance.
Office 6.0.7.3 on XUbuntu 18.04
User avatar
Zizi64
Volunteer
Posts: 11358
Joined: Wed May 26, 2010 7:55 am
Location: Budapest, Hungary

Re: Inserting image without file URL

Post by Zizi64 »

BitmapImage
Never paste unoptimized BMP format images into your documents. Use the JPG or PNG file formats.
And always optimize your images before you insert them into an ODF document: Optimize the resolution (dpi), color depth, and the physical size. You can use a third party software for this task, or maybe your graphical software has such export feature.
Tibor Kovacs, Hungary; LO7.5.8 /Win7-10 x64Prof.
PortableApps/winPenPack: LO3.3.0-7.6.2;AOO4.1.14
Please, edit the initial post in the topic: add the word [Solved] at the beginning of the subject line - if your problem has been solved.
ms777
Volunteer
Posts: 177
Joined: Mon Oct 08, 2007 1:33 am

Re: Inserting image without file URL

Post by ms777 »

Hi UnoNewbie,

afaik there is no easy method for inserting a buffer as an image. As you may experience, even simple things are quite complex in UNO :-)

I wrote the below code to insert an HTML code into a writer doc. It uses some internal storage com.sun.star.embed.StorageFactory. In your case you should not use the TextOutputStream but the DataOutputStream. FilterName is "JPG - JPEG" (preserve the spaces). The principle - loading a 2nd doc from memory and copy / paste to the original doc, should also work for draw documents

Good luck,

ms777

Code: Select all

private oDoc 'must be module level
private boFinished as Boolean

sub TestInsertHTML
s = ""
s = s & "<P></P>" 
s = s & "<P>Paragraph1</P>" 
s = s & "Hello from ms777" 
s = s & "<b>Bold</b>" 
s = s & "<H1>Header 1</H1>" 
s = s & "<P>Paragraph2</P>" 
s = s & "<CENTER>Center</CENTER>" 
s = s & "<TABLE>"
s = s & "<TR><TD bgcolor=#336699>Cell 1</TD><TD bgcolor=#663399>Cell 2</TD></TR>"
s = s & "<TR><TD bgcolor=#123456>the third cell</TD><TD bgcolor=#654321>Cell 4</TD></TR>"
s = s & "</TABLE>"

oDoc   = StarDesktop.LoadComponentFromUrl("private:factory/swriter","_default",0,Array())

call InsertHTML2Writer(oDoc, s)
end sub

sub InsertHTML2Writer(oDoc as Object, sHTML as String)
'oDoc contains the writer document, into which we want to insert the HTML
oContr = oDoc.CurrentController

'create a temporary storage
oStorageFac = createUnoService("com.sun.star.embed.StorageFactory")
oStorage    = oStorageFac.createInstance
oStream     = oStorage.openStreamElement("ms777", com.sun.star.embed.ElementModes.READWRITE)

'now write the HTML String to the stream
oTextOutputStream = createUNOService ("com.sun.star.io.TextOutputStream") 
oTextOutputStream.setOutputStream(oStream)
oTextOutputStream.writeString(sHTML)


'register a global event listener, because
'we have to wait until loading has finished
oGlob = createUnoService("com.sun.star.frame.GlobalEventBroadcaster")
oListener = CreateUnoListener( "EvList_","com.sun.star.document.XEventListener" )
oGlob.addEventListener( oListener )
boFinished = false

'create the to-be-inserted doc (=doc1) from the stream
Dim aProps(2) as new com.sun.star.beans.PropertyValue
aProps(0).Name  = "FilterName"
aProps(0).Value = "HTML (StarWriter)"
aProps(1).Name  = "InputStream"
aProps(1).Value = oStream
aProps(2).Name  = "Hidden"
aProps(2).Value = true
oDoc1 = StarDesktop.loadComponentFromURL("private:stream", "_default", 0, aProps) 

'wait until loading has finished
k=100
while (k>0) and (not boFinished)
  k=k-1
  wait(50)
  wend
oGlob.removeEventListener( oListener )

'select all of doc1
oContr1 = oDoc1.CurrentController 
oVC1 = oContr1.ViewCursor
oVC1.gotoStart(false)
oVC1.gotoEnd(true)

'insert the selection of doc1 into doc
'note that it is not necessary to involve the clipboard
'for copying
oContr.insertTransferable(oContr1.Transferable)
oDoc1.close(true)

'redraw the ComponentWindow, because sometimes the changes are not
'immediately reflected
oCompWin = oContr.Frame.ComponentWindow
with com.sun.star.awt.InvalidateStyle 
  oCompWin.invalidate(.CHILDREN+.UPDATE+.NOCLIPCHILDREN)
  end with

End Sub




Sub EvList_notifyEvent( o as object ) 
  if o.EventName = "OnLoadFinished" then 
    exit sub
  endif
  oSource = o.Source
  
  if oSource <> null then
    exit sub
  endif
  
  if EqualUnoObjects(oDoc, oSource) = true then
    boFinished = true
  endif
end sub 


Sub EvList_disposing() 
End Sub 
UnoNewbie
Posts: 3
Joined: Sat Oct 16, 2021 2:09 pm

Re: Inserting image without file URL

Post by UnoNewbie »

Thanks to both Zizi64 and ms777. :-)
I will stay with my file-workaround, this seems to be quite the easiest way. Maybe I should just move towards writing an odg-file directly without UNO dependency...
Office 6.0.7.3 on XUbuntu 18.04
Post Reply