#7528: Fixes in exporting images to document.

WordBuilder.java: Use media types instead of file extension for IMAGE_TYPE_MAP | Calculate image dimensions inside document according to its initial ratio and remove from page size the top, bottom, left, right margins.
This commit is contained in:
Konstantina Galouni 2022-03-21 18:19:51 +02:00
parent 835ccaab89
commit 8734d7c1ba
1 changed files with 38 additions and 15 deletions

View File

@ -47,14 +47,13 @@ import static org.apache.poi.xwpf.usermodel.Document.*;
public class WordBuilder { public class WordBuilder {
private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class); private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class);
private static final Map<String, Integer> IMAGE_TYPE_MAP = Stream.of(new Object[][] { private static final Map<String, Integer> IMAGE_TYPE_MAP = Stream.of(new Object[][] {
{".jpeg", PICTURE_TYPE_JPEG}, {"image/jpeg", PICTURE_TYPE_JPEG},
{".jpg", PICTURE_TYPE_JPEG}, {"image/png", PICTURE_TYPE_PNG},
{".png", PICTURE_TYPE_PNG}, {"image/gif", PICTURE_TYPE_GIF},
{".gif", PICTURE_TYPE_GIF}, {"image/tiff", PICTURE_TYPE_TIFF},
{".tiff", PICTURE_TYPE_TIFF}, {"image/bmp", PICTURE_TYPE_BMP},
{".bmp", PICTURE_TYPE_BMP}, {"image/wmf", PICTURE_TYPE_WMF}
{".wmf", PICTURE_TYPE_WMF} }
}
).collect(Collectors.toMap(objects -> (String)objects[0], o -> (Integer)o[1])); ).collect(Collectors.toMap(objects -> (String)objects[0], o -> (Integer)o[1]));
private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, Object, XWPFParagraph>> options = new HashMap<>(); private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, Object, XWPFParagraph>> options = new HashMap<>();
@ -158,12 +157,13 @@ public class WordBuilder {
}); });
this.options.put(ParagraphStyle.IMAGE, (mainDocumentPart, item) -> { this.options.put(ParagraphStyle.IMAGE, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph(); XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setPageBreak(true);
XWPFRun run = paragraph.createRun(); XWPFRun run = paragraph.createRun();
String imageId = ((Map<String, String>)item).get("id"); String imageId = ((Map<String, String>)item).get("id");
String fileName = ((Map<String, String>)item).get("name"); String fileName = ((Map<String, String>)item).get("name");
String fileType = ((Map<String, String>)item).get("type");
int format; int format;
String fileExtension = fileName.substring(fileName.lastIndexOf(".")); format = IMAGE_TYPE_MAP.getOrDefault(fileType, 0);
format = IMAGE_TYPE_MAP.getOrDefault(fileExtension, 0);
try { try {
FileInputStream image = new FileInputStream(environment.getProperty("file.storage") + imageId); FileInputStream image = new FileInputStream(environment.getProperty("file.storage") + imageId);
ImageInputStream iis = ImageIO.createImageInputStream(new File(environment.getProperty("file.storage") + imageId)); ImageInputStream iis = ImageIO.createImageInputStream(new File(environment.getProperty("file.storage") + imageId));
@ -171,13 +171,36 @@ public class WordBuilder {
if (readers.hasNext()) { if (readers.hasNext()) {
ImageReader reader = readers.next(); ImageReader reader = readers.next();
reader.setInput(iis); reader.setInput(iis);
int pageWidth = Math.round(mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getW().intValue() / (float)20); // dxa to points
int imageWidth = Math.round(reader.getWidth(0) * (float)0.75); // pixels to points int initialImageWidth = reader.getWidth(0);
int initialImageHeight = reader.getHeight(0);
float ratio = initialImageHeight / (float)initialImageWidth;
int marginLeftInDXA = mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getLeft().intValue();
int marginRightInDXA = mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getRight().intValue();
int pageWidthInDXA = mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getW().intValue();
int pageWidth = Math.round((pageWidthInDXA - marginLeftInDXA - marginRightInDXA) / (float)20); // /20 converts dxa to points
int imageWidth = Math.round(initialImageWidth*(float)0.75); // *0.75 converts pixels to points
int width = Math.min(imageWidth, pageWidth); int width = Math.min(imageWidth, pageWidth);
int pageHeight = Math.round(mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getH().intValue() / (float)20);
int imageHeight = Math.round(reader.getHeight(0) * (float)0.75); int marginTopInDXA = mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getTop().intValue();
int height = Math.min(imageHeight, pageHeight); int marginBottomInDXA = mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getBottom().intValue();
int pageHeightInDXA = mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getH().intValue();
int pageHeight = Math.round((pageHeightInDXA - marginTopInDXA - marginBottomInDXA) / (float)20); // /20 converts dxa to points
int imageHeight = Math.round(initialImageHeight * ((float)0.75)); // *0.75 converts pixels to points
int height = Math.round(width*ratio);
if(height > pageHeight) {
// height calculated with ratio is too large. Image may have Portrait (vertical) orientation. Recalculate image dimensions.
height = Math.min(imageHeight, pageHeight);
width = Math.round(height/ratio);
}
run.addPicture(image, format, fileName, Units.toEMU(width), Units.toEMU(height)); run.addPicture(image, format, fileName, Units.toEMU(width), Units.toEMU(height));
paragraph.setPageBreak(false);
} }
} catch (IOException | InvalidFormatException e){ } catch (IOException | InvalidFormatException e){
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);