Dynamically Include Images in Word Document | Set Image Size (Width Height) & Keep the Aspect Ratio during Mail Merge Java

Hallo
I want to dynamically include Images in the documents. The images should never exceed some limit in size. The data source is an automatically generated xml file.
I put an «image(80pt;50pt):ImagePath» in my template and an implementation of the IFieldMergingCallback interface.

    class ShapeSetFieldMergingCallback implements IFieldMergingCallback {
    	public void fieldMerging(FieldMergingArgs args) throws Exception {
    		// Implementation is not required.
    	}
    	public void imageFieldMerging(ImageFieldMergingArgs args) throws Exception {
    		Shape shape = new Shape(args.getDocument(), ShapeType.IMAGE);
    		shape.setAspectRatioLocked(true);
    		String imageFileName = args.getFieldValue().toString();
    		shape.getImageData().setImage(imageFileName);
    		double imageWidth = shape.getImageData().getImageSize().getWidthPoints();
    		double imageHeight = shape.getImageData().getImageSize().getHeightPoints();
    		double targetWidth = args.getImageWidth().getValue();
    		targetWidth = (targetWidth<0)? imageWidth:targetWidth;
    		double targetHeight = args.getImageHeight().getValue();
    		targetHeight = (targetHeight<0)? imageWidth:targetHeight;
    		if (targetHeight / imageHeight > targetWidth / imageWidth) {
    			targetHeight = imageHeight * targetWidth / imageWidth;
    		} else {
    			targetWidth = imageWidth * targetHeight / imageHeight;
    		}
    		shape.setWidth(targetWidth);
    		shape.setHeight(targetHeight);
    		shape.setWrapType(WrapType.SQUARE);
    		shape.setAllowOverlap(false);
    		args.setShape(shape);
    	}
    }

But now the images overlap my footer. This seems rather complicated for such a simple task.
I just want the normal behaviour of image fields with the images keeping the aspect ratio.

Best,
Peter

@p.binnig,

Please ZIP and attach the following resources here for testing:

  • Your simplified template Word document
  • The Image file that you want to insert in template document
  • Aspose.Words for Java 21.2 generated output DOCX and PDF files showing the undesired behavior
  • Your expected DOCX & PDF files showing the desired output. You can create these documents by using MS Word.
  • Please also create a standalone simple Java application (source code without compilation errors) that helps us to reproduce your current problem on our end and attach it here for testing. Please do not include Aspose.Words JAR files in it to reduce the file size.

As soon as you get these pieces of information ready, we will start further investigation into your particular scenario/issue and provide you more information.

I included an example application and two PDF files one (“overlapping_footer.pdf”) with the right aspect ratio but the image overlapping the footer and one with the wrong aspect ration but the right page brake and the image on the second page. I also included an example Word file where the aspect ratio is correct and the image is on the second page as well as the template file, the image and the data XML file.
While building the example I realised that the problem only exists if the image is embedded in a table.
TestApp.zip (130.8 KB)

@p.binnig,

To avoid this problem, you can lock the aspect ratio of Image and keep Table from breaking across Pages.

File xmlFile = new File("C:\\temp\\TestApp\\data.xml");
Document doc = new Document("C:\\temp\\TestApp\\template.docx");

Table table = doc.getFirstSection().getBody().getTables().get(0);
for (Cell cell : (Iterable<Cell>) table.getChildNodes(NodeType.CELL, true))
{
    // Call this method if table's cell is created on the fly
    // Newly created cell does not have paragraph inside
    cell.ensureMinimum();
    for (Paragraph para : (Iterable<Paragraph>) cell.getParagraphs())
    if (!(cell.getParentRow().isLastRow() && para.isEndOfCell()))
        para.getParagraphFormat().setKeepWithNext(true);
}

doc.getMailMerge().setFieldMergingCallback(new ShapeSetFieldMergingCallback());
DataSet dataSet = new DataSet();
InputStream inputStream = new FileInputStream(xmlFile);
dataSet.readXml(inputStream);
doc.getMailMerge().setUseNonMergeFields(true);
doc.getMailMerge().setUseWholeParagraphAsRegion(false);
doc.getMailMerge().executeWithRegions(dataSet);
doc.save("C:\\temp\\TestApp\\out.docx");
doc.save("C:\\temp\\TestApp\\out.pdf");

public static class ShapeSetFieldMergingCallback implements IFieldMergingCallback {

    public void fieldMerging(FieldMergingArgs args) throws Exception {
        // Implementation is not required.
    }

    public void imageFieldMerging(ImageFieldMergingArgs args) throws Exception {
        Shape shape = new Shape(args.getDocument(), ShapeType.IMAGE);
        shape.setAspectRatioLocked(true);
        String imageFileName = args.getFieldValue().toString();
        shape.getImageData().setImage(imageFileName);

        double imageWidth = shape.getImageData().getImageSize().getWidthPoints();
        double imageHeight = shape.getImageData().getImageSize().getHeightPoints();
        double targetWidth = args.getImageWidth().getValue();
        targetWidth = (targetWidth < 0) ? imageWidth : targetWidth;
        double targetHeight = args.getImageHeight().getValue();
        targetHeight = (targetHeight < 0) ? imageWidth : targetHeight;
        if (targetHeight / imageHeight > targetWidth / imageWidth) {
            targetHeight = imageHeight * targetWidth / imageWidth;
        } else {
            targetWidth = imageWidth * targetHeight / imageHeight;
        }
        shape.setWidth(targetWidth);
        shape.setHeight(targetHeight);
        shape.setWrapType(WrapType.SQUARE);
        shape.setAllowOverlap(false);
        shape.setAspectRatioLocked(true);
        args.setShape(shape);
    }
}