We're sorry Aspose doesn't work properply without JavaScript enabled.

Free Support Forum - aspose.com

Extreme slowness when merging multiple images

Hi everybody,


I have attached a .zip archive containing the following files:

- a template named verbale_consegna_it.doc
- a filled template named report_mod_98_5.doc
- a .xml file containing the data for the region dpi_all
- a .xml file containing the data for the region dpi

the two region are then merged with a relation defined on the fields new String[] {“id_dipendente”, “id_azienda”, “id_sede”, “revisione_documento”}.

The problem here is that to produce that report it took more than five minutes.

Is this normal? We just migrated this report from JasperReport to mail merge, but it did not take too long before, it was filled in a matter of seconds.

Clearly, our end users will never accept such a long waiting time…

It would seem that I have found the issue, which was in our own code, sorry for placing it upon you.


Here is how we handled image merging:

public void imageFieldMerging(ImageFieldMergingArgs ifma) throws Exception {
try {
DocumentBuilder builder = new DocumentBuilder(ifma.getDocument());
builder.moveToMergeField(ifma.getDocumentFieldName());

double width = -1;
double height = -1;

// se si trova in una cella di una tabella
Cell cell = (Cell) builder.getCurrentParagraph().getAncestor(NodeType.CELL);
if (cell != null) {
CellFormat format = cell.getCellFormat();

format.setLeftPadding(0.0);
format.setRightPadding(0.0);
format.setTopPadding(0.0);
format.setBottomPadding(0.0);
format.setWrapText(false);
format.setFitText(true);

// uso dimensioni cella
width = format.getWidth();
height = cell.getParentRow().getRowFormat().getHeight();
}

// se si trova in un textbox
Shape shape = (Shape) builder.getCurrentParagraph().getAncestor(NodeType.SHAPE);
if (shape != null && shape.getShapeType() == ShapeType.TEXT_BOX) {
TextBox tb = shape.getTextBox();

tb.setInternalMarginBottom(0.0);
tb.setInternalMarginTop(0.0);
tb.setInternalMarginLeft(0.0);
tb.setInternalMarginRight(0.0);

// uso dimensioni textbox
width = shape.getWidth();
height = shape.getHeight();
}

// immagine come array di byte
byte[] bytes = (byte[]) ifma.getFieldValue();

if (width > 0) {
// ricostruisco immagine per calcolare proporzioni
BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));

// ricavo fattore di scala
int imgw = img.getWidth();
int imgh = img.getHeight();
double scale = Math.max(imgw / width, imgh / height);

// inserisce l’immagine specificando le dimensioni
builder.insertImage(img, imgw / scale, imgh / scale);
}
else {
// altrimenti inserisce immagine senza specificare dimensioni
builder.insertImage(bytes);
}
}
catch (Exception e) {
// se qualcosa va male, setta immagine a null
ifma.setImage(null);
}
}

The method checked wether the image was in a table cell or inside a shape and, if so, scaled the image according to its container’s dimensions.

Now, I have removed such resize, and all works well, however the image are distorted 'cause the new sizes, set from its container. Here is the new code:

public void imageFieldMerging(ImageFieldMergingArgs ifma) throws Exception {
try {
double width = ifma.getImageWidth().getValue();
double height = ifma.getImageHeight().getValue();

// se le dimensioni non sono già specificate
if (width < 0 && height < 0) {
DocumentBuilder builder = new DocumentBuilder(ifma.getDocument());
builder.moveToMergeField(ifma.getDocumentFieldName(), false, false);

// se si trova in una cella di una tabella
Cell cell = (Cell) builder.getCurrentParagraph().getAncestor(NodeType.CELL);
if (cell != null) {
CellFormat format = cell.getCellFormat();

format.setLeftPadding(0.0);
format.setRightPadding(0.0);
format.setTopPadding(0.0);
format.setBottomPadding(0.0);
format.setWrapText(false);
format.setFitText(true);

// uso dimensioni cella
width = format.getWidth();
height = cell.getParentRow().getRowFormat().getHeight();
}

// se si trova in un textbox
Shape shape = (Shape) builder.getCurrentParagraph().getAncestor(NodeType.SHAPE);
if (shape != null && shape.getShapeType() == ShapeType.TEXT_BOX) {
TextBox tb = shape.getTextBox();

tb.setInternalMarginBottom(0.0);
tb.setInternalMarginTop(0.0);
tb.setInternalMarginLeft(0.0);
tb.setInternalMarginRight(0.0);

// uso dimensioni textbox
width = shape.getWidth();
height = shape.getHeight();
}
}

// immagine come array di byte
ifma.setImageStream(new ByteArrayInputStream((byte[]) ifma.getFieldValue()));

// imposto le dimensioni
ifma.getImageWidth().setValue(width);
ifma.getImageHeight().setValue(height);
}
catch (Exception e) {
// se qualcosa va male, setta immagine a null
ifma.setImage(null);
}
}

As a feature request/suggestion, would it be possible for you to handle a case where one needs proportional resizing?

I would suggest something like:

ImageFieldMergingArgs.getImageWidth().setValueProportional();

and

ImageFieldMergingArgs.getImageHeight().setValueProportional();

Those two method should take the values set and the actual image size, and resize accordingly.

Perhaps you are able to implement it in a much optimized way than I am able to!

Hi Matteo,


Thanks for your inquiry. Please use the following code snippet to resize the image with proportional height/width according to table’s cell. You can use the same highlighted code snippet for TextBox shape as well. Hope this helps you. Please let us know if you have any more queries.

Document doc = new
Document(MyDir + “resizeImage.Cell.docx”);<o:p></o:p>

DocumentBuilder builder = new DocumentBuilder(doc);

Cell cell = (Cell)doc.getChild(NodeType.CELL, 0, true);

CellFormat format = cell.getCellFormat();

format.setLeftPadding(0.0);

format.setRightPadding(0.0);

format.setTopPadding(0.0);

format.setBottomPadding(0.0);

format.setWrapText(false);

format.setFitText(true);

double width = format.getWidth();

double height = cell.getParentRow().getRowFormat().getHeight();

builder.moveTo(cell.getFirstChild());

Shape image = builder.insertImage(MyDir + "Chrysanthemum.jpg");

double freePageWidth = width;

double freePageHeight = height;

// Is one of the sides of this image too big for the page?

ImageSize size = image.getImageData().getImageSize();

boolean exceedsMaxPageSize = size.getWidthPoints() > freePageWidth || size.getHeightPoints() > freePageHeight;

if (exceedsMaxPageSize)

{

// Calculate the ratio to fit the page size based on which side is longer.

boolean widthLonger = (size.getWidthPoints() > size.getHeightPoints());

double ratio = widthLonger ? freePageWidth / size.getWidthPoints() : freePageHeight / size.getHeightPoints();

// Set the new size.

image.setWidth(size.getWidthPoints() * ratio);

image.setHeight(size.getHeightPoints() * ratio);

}

doc.save(MyDir + "Out.docx");