调整XSSFWorkbook中EMF图像的大小



在将EMF图像插入XSSFWorkbook后,我正在尝试调整其大小。支持调整PNGJPEGDIB图像的大小。

private void addNormalFigure(XSSFSheet sheet, byte[] imgData){
XSSFWorkbook w = sheet.getWorkbook();
int picIdx = w.addPicture(imgData, Workbook.PICTURE_TYPE_EMF);
CreationHelper helper = w.getCreationHelper();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
// Column : A
anchor.setCol1(0);
// Row : 4
anchor.setRow1(4);
Picture pic = drawing.createPicture(anchor, picIdx);
double height = 2.0;
double width = 2.0;
// sets the anchor.col2 to 0 and anchor.row2 to 0
pic.getImageDimension().setSize(inchToPixel(width), inchToPixel(height));
// pic.resize(); -> this too sets the anchor.col2 to 0 and anchor.row2 to 0
}
private double inchToPixel(double in) {
return in * 96.0;
}

我们有没有办法解决这个问题?

Apache poi不提供从Workbook.PICTURE_TYPE_EMF类型的Picture获取图像维度。所使用的ImageUtils方法getImageDimension只能从JPEG、PNG和DIB图片中获取尺寸,

apache poi提供了org.apache.poi.hemf.usermodel.HemfPicture。所以

import org.apache.poi.hemf.usermodel.HemfPicture;
...
HemfPicture hemfPicture = new HemfPicture(new ByteArrayInputStream(imgData));
System.out.println(hemfPicture.getSize()); 
...

将打印正确的尺寸。

但是,它缺乏将这些维度设置为锚的可能性。ImageUtils中有一个方法scaleCell,但不能公开访问。所以,唯一的方法是将该方法的源代码复制到代码中。

以下完整的示例可以做到这一点。它使用与CCD_ 16中代码相同的方法CCD_。方法resizeHemfPicturePicture的大小调整为HemfPicture维度。

这是使用apache poi 5.0.0Java 12进行测试和工作的。

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import org.apache.poi.ss.util.ImageUtils;
import org.apache.poi.hemf.usermodel.HemfPicture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.awt.Dimension;
import java.io.FileInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
class CreateExcelEMFPicture {

public static double getRowHeightInPixels(Sheet sheet, int rowNum) {
Row r = sheet.getRow(rowNum);
double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints();
return Units.toEMU(points)/(double)Units.EMU_PER_PIXEL;
}
private static void scaleCell(final double targetSize,
final int startCell,
final int startD,
Consumer<Integer> endCell,
Consumer<Integer> endD,
final int hssfUnits,
Function<Integer,Number> nextSize) { 
if (targetSize < 0) {
throw new IllegalArgumentException("target size < 0");
}
int cellIdx = startCell;
double dim, delta;
for (double totalDim = 0, remDim;; cellIdx++, totalDim += remDim) {
dim = nextSize.apply(cellIdx).doubleValue();
remDim = dim;
if (cellIdx == startCell) {
if (hssfUnits > 0) {
remDim *= 1 - startD/(double)hssfUnits;
} else {
remDim -= startD/(double)Units.EMU_PER_PIXEL;
}
}
delta = targetSize - totalDim;
if (delta < remDim) {
break;
}
}
double endDval;
if (hssfUnits > 0) {
endDval = delta/dim * (double)hssfUnits;
} else {
endDval = delta * Units.EMU_PER_PIXEL;
}
if (cellIdx == startCell) {
endDval += startD;
}
endCell.accept(cellIdx);
endD.accept((int)Math.rint(endDval));
}
static void resizeHemfPicture(Picture picture, HemfPicture hemfPicture) {
ClientAnchor anchor = picture.getClientAnchor();
boolean isHSSF = (anchor instanceof HSSFClientAnchor);
double height = hemfPicture.getSize().getHeight();
double width = hemfPicture.getSize().getWidth();
Sheet sheet = picture.getSheet();
int WIDTH_UNITS = 1024;
int HEIGHT_UNITS = 256;
scaleCell(width, anchor.getCol1(), anchor.getDx1(), anchor::setCol2, anchor::setDx2, isHSSF ? WIDTH_UNITS : 0, sheet::getColumnWidthInPixels);
scaleCell(height, anchor.getRow1(), anchor.getDy1(), anchor::setRow2, anchor::setDy2, isHSSF ? HEIGHT_UNITS : 0, (row) -> getRowHeightInPixels(sheet, row));
}
public static void main(String[] args) throws Exception{
Workbook workbook = new XSSFWorkbook(); String filePath = "./CreateExcelEMFPicture.xlsx";
//Workbook workbook = new HSSFWorkbook(); String filePath = "./CreateExcelEMFPicture.xls";
CreationHelper helper = workbook.getCreationHelper();
//add picture data to this workbook.
FileInputStream is = new FileInputStream("./image.emf");
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_EMF);
is.close();
HemfPicture hemfPicture = new HemfPicture(new ByteArrayInputStream(bytes));
System.out.println(hemfPicture.getSize()); // returns correct dimension

Sheet sheet = workbook.createSheet("Sheet1");
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(0);
anchor.setRow1(4); 
Picture picture = drawing.createPicture(anchor, pictureIdx);
System.out.println(picture.getImageDimension()); // 0, 0
System.out.println(ImageUtils.getDimensionFromAnchor(picture)); // 0, 0
//picture.resize(); //will not work
resizeHemfPicture(picture, hemfPicture);
System.out.println(ImageUtils.getDimensionFromAnchor(picture)); // correct dimension
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}

最新更新