Bug 121536 - Embedding external (links) images programmatically no longer works
Summary: Embedding external (links) images programmatically no longer works
Status: RESOLVED WORKSFORME
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Writer (show other bugs)
Version:
(earliest affected)
6.1.0.3 release
Hardware: All All
: medium normal
Assignee: Not Assigned
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-11-20 04:38 UTC by Simon
Modified: 2018-11-24 14:14 UTC (History)
1 user (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Simon 2018-11-20 04:38:27 UTC
Before 6.1.0.3, it was possible to embed all external (linked) images into a document programmatically using the following function: 

  public static void convertLinkedImagesToEmbeded(XComponent document) throws Exception {

    XTextGraphicObjectsSupplier graphicObjSupplier =
        (XTextGraphicObjectsSupplier)
            UnoRuntime.queryInterface(XTextGraphicObjectsSupplier.class, document);
    XNameAccess nameAccess = graphicObjSupplier.getGraphicObjects();
    String[] names = nameAccess.getElementNames();
    for (int i = 0; i < names.length; i++) {
      Any xImageAny = (Any) nameAccess.getByName(names[i]);
      Object xImageObject = xImageAny.getObject();
      XTextContent xImage = (XTextContent) xImageObject;
      XServiceInfo xInfo = (XServiceInfo) UnoRuntime.queryInterface(XServiceInfo.class, xImage);
      if (xInfo.supportsService("com.sun.star.text.TextGraphicObject")) {
        XPropertySet xPropSet =
            (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xImage);
        String name = xPropSet.getPropertyValue("LinkDisplayName").toString();
        String graphicURL = xPropSet.getPropertyValue("GraphicURL").toString();
        // only ones that are not embedded
        if (graphicURL.indexOf("vnd.sun.") == -1) {
          XMultiServiceFactory multiServiceFactory =
              (XMultiServiceFactory)
                  UnoRuntime.queryInterface(XMultiServiceFactory.class, document);
          XNameContainer xBitmapContainer =
              (XNameContainer)
                  UnoRuntime.queryInterface(
                      XNameContainer.class,
                      multiServiceFactory.createInstance("com.sun.star.drawing.BitmapTable"));
          if (!xBitmapContainer.hasByName(name)) {
            xBitmapContainer.insertByName(name, graphicURL);
            String newGraphicURL = xBitmapContainer.getByName(name).toString();
            xPropSet.setPropertyValue("GraphicURL", newGraphicURL);
          }
        }
      }
    }
  }

I have read a lot about the image handling rework and I know that the GraphicURL property can no longer be used for that but I couldn't find a way to make the function work again. All the examples available out there that show how to programmatically break links use the property GraphicURL and the documentation only tell us to use Graphic instead of GraphicURL, but that doesn't work in this particular case. After several hours of trying to make it work, give up!

So, is it still possible to programatically embed linked images since 6.1.0.3+ ?? What changes should I make to the function above to support both the 6.1.0.3+ and previous versions ?

Many thanks.
Comment 1 Oliver Brinzing 2018-11-20 11:27:56 UTC
maybe this can help you:

extract and link all pictures from a writer document
https://bugs.documentfoundation.org/show_bug.cgi?id=119872
Comment 2 Simon 2018-11-23 04:45:29 UTC
Thanks a million Oliver. 

What I was trying to do is the opposite of your example, but it helped me a lot! I don't like being force to check the product and version but it works. Thanks again.

Here's my new function:

  private static void convertLinkedImagesToEmbeded(
      final XComponentContext context, final XComponent document) throws Exception {

    // Create a GraphicProvider.
    final XGraphicProvider graphicProvider =
        UnoRuntime.queryInterface(
            XGraphicProvider.class,
            context
                .getServiceManager()
                .createInstanceWithContext("com.sun.star.graphic.GraphicProvider", context));
    final XIndexAccess indexAccess =
        UnoRuntime.queryInterface(
            XIndexAccess.class,
            UnoRuntime.queryInterface(XTextGraphicObjectsSupplier.class, document)
                .getGraphicObjects());
    for (int i = 0; i < indexAccess.getCount(); i++) {
      final Any xImageAny = (Any) indexAccess.getByIndex(i);
      final Object xImageObject = xImageAny.getObject();
      final XTextContent xImage = (XTextContent) xImageObject;
      final XServiceInfo xInfo = UnoRuntime.queryInterface(XServiceInfo.class, xImage);
      if (xInfo.supportsService("com.sun.star.text.TextGraphicObject")) {
        final XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, xImage);
        if (is LibreOffice and Version >= 6.1) { ***
          final XGraphic xGraphic =
              (XGraphic)
                  AnyConverter.toObject(XGraphic.class, xPropSet.getPropertyValue("Graphic"));
          // Only ones that are not embedded
          final XPropertySet xGraphixPropSet = UnoRuntime.queryInterface(XPropertySet.class, xGraphic);
          boolean linked = (boolean) xGraphixPropSet.getPropertyValue("Linked");
          if (linked) {
            // Since 6.1, we must use "Graphic" instead of "GraphicURL"
            final PropertyValue[] props =
                new PropertyValue[] {new PropertyValue(), new PropertyValue()};
            props[0].Name = "URL";
            props[0].Value = xGraphixPropSet.getPropertyValue("OriginURL").toString();
            props[1].Name = "LoadAsLink";
            props[1].Value = false;
            xPropSet.setPropertyValue("Graphic", graphicProvider.queryGraphic(props));
          }
        } else {
          final String name = xPropSet.getPropertyValue("LinkDisplayName").toString();
          final String graphicURL = xPropSet.getPropertyValue("GraphicURL").toString();
          // Only ones that are not embedded
          if (graphicURL.indexOf("vnd.sun.") == -1) {
            // Creating bitmap container service
            final XNameContainer bitmapContainer =
                UnoRuntime.queryInterface(
                    XNameContainer.class,
                    UnoRuntime.queryInterface(XMultiServiceFactory.class, document)
                        .createInstance("com.sun.star.drawing.BitmapTable"));
            if (!bitmapContainer.hasByName(name)) {
              bitmapContainer.insertByName(name, graphicURL);
              xPropSet.setPropertyValue("GraphicURL", bitmapContainer.getByName(name).toString());
            }
          }
        }
      }
    }
  }

*** I didn't show how to check the product and version, the function would have been too long, but I've been inspired by the Utilities made by Dr. Andrew Davison that can be found here:
http://fivedots.coe.psu.ac.th/~ad/jlop
Comment 3 Oliver Brinzing 2018-11-24 14:14:18 UTC
(In reply to Simon from comment #2)
> Thanks a million Oliver. 

:-)

setting the issue to resolved/worksforme