Reputation: 320
I am trying to resize an EMF
image after inserting it into an XSSFWorkbook
.
There is support resizing PNG
, JPEG
and DIB
images.
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;
}
Is there any way we can workaround this problem?
Upvotes: 0
Views: 889
Reputation: 61945
Apache poi
not provides to get image dimensions from Picture
of type Workbook.PICTURE_TYPE_EMF
. The used ImageUtils
method getImageDimension
only is able to get dimensions from JPEG, PNG and DIB pictures,
But apache poi
provides org.apache.poi.hemf.usermodel.HemfPicture
. So
import org.apache.poi.hemf.usermodel.HemfPicture;
...
HemfPicture hemfPicture = new HemfPicture(new ByteArrayInputStream(imgData));
System.out.println(hemfPicture.getSize());
...
will print the correct dimensions.
But then it lacks a possibility to set those dimensions to the anchor. There is a method scaleCell
in ImageUtils
but not public accessible. So only way would be to copy source code of that method into your code.
Following complete example does that. It uses methos scaleCell
having same code as in ImageUtils
. The method resizeHemfPicture
resizes the Picture
to the HemfPicture
dimension.
This is tested and works using apache poi 5.0.0
and Java 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();
}
}
Upvotes: 1