How to set image size is dynamically in poi word r

2019-06-08 13:21发布

问题:

 XWPFDocument doc= new XWPFDocument();
 InputStream a = someMethod(underConditions(inputimage));
 paragraph.createRun().addPicture(a, Document.PICTURE_TYPE_PNG, "", Units.toEMU(20), Units.toEMU(20));
 a.close();
 doc.write(new FileOutputStream("CreateWordHeaderFooter.docx"));
 doc.close();

This is simple code for add a image in poi word. But InputStream a is different under different conditions. If inputimage is small Units.toEMU(20), Units.toEMU(20) is to big, and if inputimage is big Units.toEMU(20), Units.toEMU(20) is too small. In this conditions images are distorted. So my question is how to set dynamic image size based on different image. Thanks.

回答1:

So we need determining the preferred dimensions of the images from their files. There are already much discussions on how to do that. Search keywords: java get dimension from image file. Simplest possibility is using ImageIO to read BufferedImage from the file which then has widthand height properties.

Example:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.util.Units;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Dimension;

public class CreateWordImagesPreferredSize {

 static Dimension getImageDimension(File imgFile) throws IOException {
  BufferedImage img = ImageIO.read(imgFile);
  return new Dimension(img.getWidth(), img.getHeight());
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument doc= new XWPFDocument();

  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run = paragraph.createRun();  
  run.setText("The Images:");

  String[] images = new String[]{"Koala.png", "Scannen.jpg", "Winter.bmp"};

  for (int i = 0 ; i < images.length; i++) {

   paragraph = doc.createParagraph();
   run = paragraph.createRun();

   File imgFile = new File(images[i]);
   Dimension dim = getImageDimension(imgFile);
   System.out.println(dim);

   double width = dim.getWidth();
   double height = dim.getHeight();

   double scaling = 1.0;
   if (width > 72*6) scaling = (72*6)/width; //scale width not to be greater than 6 inches

   InputStream in = new FileInputStream(imgFile);
   paragraph.createRun().addPicture(in, Document.PICTURE_TYPE_PNG, images[i], 
    Units.toEMU(width*scaling), Units.toEMU(height*scaling));
   in.close();

  }

  doc.write(new FileOutputStream("CreateWordImagesPreferredSize.docx"));
  doc.close();

 }
}

Note: I do scaling the image to be not greater than 6 inches width if its original size is greater. So it will fit into one page width. Smaller images will not be scaled.


Edit:

As from the comments, if you cannot using File but must using InputStream, then you need to know, that BufferedImage img = ImageIO.read(imgStream); of course reads from the stream. So the stream will be at its end after that. So .addPicture(imgStream,...) will need a newly opened stream then.

Example:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.util.Units;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Dimension;

public class CreateWordImagesPreferredSizeStream {

 static InputStream getInputStream(String filename) throws Exception {
  return new FileInputStream(filename);
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument doc= new XWPFDocument();

  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run = paragraph.createRun();  
  run.setText("The Images:");

  String[] images = new String[]{"Koala.png", "Scannen.jpg", "Winter.bmp"};

  for (int i = 0 ; i < images.length; i++) {

   paragraph = doc.createParagraph();
   run = paragraph.createRun();

   InputStream imgStream = getInputStream(images[i]);

   BufferedImage img = ImageIO.read(imgStream);
   double w = img.getWidth();
   double h = img.getHeight();
   imgStream.close();

   System.out.println(w);
   System.out.println(h);

   double scaling = 1.0;
   if (w > 72*6) scaling = (72*6)/w; //scale width not to be greater than 6 inches

   imgStream = getInputStream(images[i]);

   paragraph.createRun().addPicture(imgStream, Document.PICTURE_TYPE_PNG, images[i], 
    Units.toEMU(w*scaling), Units.toEMU(h*scaling));
   imgStream.close();

  }

  doc.write(new FileOutputStream("CreateWordImagesPreferredSize.docx"));
  doc.close();

 }
}


标签: apache-poi