如何在poi word run.addPicture()中动态设置图片大小?

How to set image size is dynamically in poi word run.addPicture()?

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();

这是在poi word中添加图片的简单代码。但是InputStream a在不同的情况下是不同的。如果 inputimageUnits.toEMU(20), Units.toEMU(20) 太大,如果 inputimageUnits.toEMU(20), Units.toEMU(20) 太小。在这种情况下图像会失真。

所以我的问题是:如何根据不同的图片设置动态图片大小?

所以我们需要从文件中确定图像的首选尺寸。已经有很多关于如何做到这一点的讨论。搜索关键字:java get dimension from image file。最简单的可能性是使用 ImageIO 从文件中读取 BufferedImage,然后该文件具有 widthheight 属性。

示例:

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();

  }

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

注意:如果图像的原始尺寸更大,我会将图像缩放到不大于 6 英寸的宽度。所以它将适合一个页面宽度。较小的图像将不会被缩放。


编辑:

根据评论,如果您不能使用 File 而必须使用 InputStream,那么您需要知道,BufferedImage img = ImageIO.read(imgStream); 当然是从流中读取的。所以在那之后流将结束。所以 .addPicture(imgStream,...) 需要一个新打开的流。

示例:

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();

  }

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