From 9de555bfd44fc26cdac9bbffbbfb1f0d37f1f3c5 Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Mon, 16 Mar 2020 18:46:48 +0000 Subject: [PATCH] #64213 - Picture.resize(double scale) scales width wrong for small pictures and when dx1 is set git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1875266 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/poi/ss/util/ImageUtils.java | 226 +++++------ .../poi/xssf/usermodel/TestXSSFPicture.java | 163 ++++---- .../poi/hssf/usermodel/TestHSSFPicture.java | 373 +++++++++--------- .../poi/ss/usermodel/BaseTestPicture.java | 159 +++++++- 4 files changed, 521 insertions(+), 400 deletions(-) diff --git a/src/java/org/apache/poi/ss/util/ImageUtils.java b/src/java/org/apache/poi/ss/util/ImageUtils.java index ba355ebb0f..fdd8ee8965 100644 --- a/src/java/org/apache/poi/ss/util/ImageUtils.java +++ b/src/java/org/apache/poi/ss/util/ImageUtils.java @@ -24,6 +24,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; +import java.util.function.Consumer; +import java.util.function.Function; import javax.imageio.ImageIO; import javax.imageio.ImageReader; @@ -38,18 +40,26 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Removal; import org.apache.poi.util.Units; import org.w3c.dom.Element; import org.w3c.dom.NodeList; -/** - * @author Yegor Kozlov - */ -public class ImageUtils { +public final class ImageUtils { private static final POILogger logger = POILogFactory.getLogger(ImageUtils.class); + /** + * @deprecated use {@link Units#PIXEL_DPI} + */ + @Deprecated + @Removal(version = "5.0.0") public static final int PIXEL_DPI = 96; + private static final int WIDTH_UNITS = 1024; + private static final int HEIGHT_UNITS = 256; + + private ImageUtils() {} + /** * Return the dimension of this image * @@ -82,11 +92,11 @@ public class ImageUtils { //if DPI is zero then assume standard 96 DPI //since cannot divide by zero - if (dpi[0] == 0) dpi[0] = PIXEL_DPI; - if (dpi[1] == 0) dpi[1] = PIXEL_DPI; + if (dpi[0] == 0) dpi[0] = Units.PIXEL_DPI; + if (dpi[1] == 0) dpi[1] = Units.PIXEL_DPI; - size.width = img.getWidth()*PIXEL_DPI/dpi[0]; - size.height = img.getHeight()*PIXEL_DPI/dpi[1]; + size.width = img.getWidth()*Units.PIXEL_DPI/dpi[0]; + size.height = img.getHeight()*Units.PIXEL_DPI/dpi[1]; } finally { r.dispose(); } @@ -148,76 +158,25 @@ public class ImageUtils { Sheet sheet = picture.getSheet(); // in pixel - Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()); + final Dimension imgSize = (scaleX == Double.MAX_VALUE || scaleY == Double.MAX_VALUE) + ? getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()) + : new Dimension(); + // in emus - Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture); + final Dimension anchorSize = (scaleX != Double.MAX_VALUE || scaleY != Double.MAX_VALUE) + ? ImageUtils.getDimensionFromAnchor(picture) + : new Dimension(); + final double scaledWidth = (scaleX == Double.MAX_VALUE) ? imgSize.getWidth() : anchorSize.getWidth()/EMU_PER_PIXEL * scaleX; final double scaledHeight = (scaleY == Double.MAX_VALUE) ? imgSize.getHeight() : anchorSize.getHeight()/EMU_PER_PIXEL * scaleY; - double w = 0; - int col2 = anchor.getCol1(); - int dx2 = 0; + scaleCell(scaledWidth, anchor.getCol1(), anchor.getDx1(), anchor::setCol2, anchor::setDx2, + isHSSF ? WIDTH_UNITS : 0, sheet::getColumnWidthInPixels); - //space in the leftmost cell - w = sheet.getColumnWidthInPixels(col2++); - if (isHSSF) { - w *= 1d - anchor.getDx1()/1024d; - } else { - w -= anchor.getDx1()/(double)EMU_PER_PIXEL; - } - - while(w < scaledWidth){ - w += sheet.getColumnWidthInPixels(col2++); - } - - if(w > scaledWidth) { - //calculate dx2, offset in the rightmost cell - double cw = sheet.getColumnWidthInPixels(--col2); - double delta = w - scaledWidth; - if (isHSSF) { - dx2 = (int)((cw-delta)/cw*1024); - } else { - dx2 = (int)((cw-delta)*EMU_PER_PIXEL); - } - if (dx2 < 0) { - dx2 = 0; - } - } - anchor.setCol2(col2); - anchor.setDx2(dx2); - - double h = 0; - int row2 = anchor.getRow1(); - int dy2 = 0; - - h = getRowHeightInPixels(sheet,row2++); - if (isHSSF) { - h *= 1 - anchor.getDy1()/256d; - } else { - h -= anchor.getDy1()/(double)EMU_PER_PIXEL; - } - - while(h < scaledHeight){ - h += getRowHeightInPixels(sheet,row2++); - } - - if(h > scaledHeight) { - double ch = getRowHeightInPixels(sheet,--row2); - double delta = h - scaledHeight; - if (isHSSF) { - dy2 = (int)((ch-delta)/ch*256); - } else { - dy2 = (int)((ch-delta)*EMU_PER_PIXEL); - } - if (dy2 < 0) { - dy2 = 0; - } - } - - anchor.setRow2(row2); - anchor.setDy2(dy2); + scaleCell(scaledHeight, anchor.getRow1(), anchor.getDy1(), anchor::setRow2, anchor::setDy2, + isHSSF ? HEIGHT_UNITS : 0, (row) -> getRowHeightInPixels(sheet, row)); return new Dimension( (int)Math.round(scaledWidth*EMU_PER_PIXEL), @@ -236,51 +195,20 @@ public class ImageUtils { boolean isHSSF = (anchor instanceof HSSFClientAnchor); Sheet sheet = picture.getSheet(); - double w = 0; - int col2 = anchor.getCol1(); - - //space in the leftmost cell - w = sheet.getColumnWidthInPixels(col2++); - if (isHSSF) { - w *= 1 - anchor.getDx1()/1024d; - } else { - w -= anchor.getDx1()/(double)EMU_PER_PIXEL; + // default to image size (in pixel), if the anchor is only specified for Col1/Row1 + Dimension imgSize = null; + if (anchor.getCol2() < anchor.getCol1() || anchor.getRow2() < anchor.getRow1()) { + PictureData data = picture.getPictureData(); + imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()); } - while(col2 < anchor.getCol2()){ - w += sheet.getColumnWidthInPixels(col2++); - } + int w = getDimFromCell(imgSize == null ? 0 : imgSize.getWidth(), anchor.getCol1(), anchor.getDx1(), anchor.getCol2(), anchor.getDx2(), + isHSSF ? WIDTH_UNITS : 0, sheet::getColumnWidthInPixels); - if (isHSSF) { - w += anchor.getDx2()/1024d * sheet.getColumnWidthInPixels(col2); - } else { - w += anchor.getDx2()/(double)EMU_PER_PIXEL; - } + int h = getDimFromCell(imgSize == null ? 0 : imgSize.getHeight(), anchor.getRow1(), anchor.getDy1(), anchor.getRow2(), anchor.getDy2(), + isHSSF ? HEIGHT_UNITS : 0, (row) -> getRowHeightInPixels(sheet, row)); - double h = 0; - int row2 = anchor.getRow1(); - - h = getRowHeightInPixels(sheet,row2++); - if (isHSSF) { - h *= 1 - anchor.getDy1()/256d; - } else { - h -= anchor.getDy1()/(double)EMU_PER_PIXEL; - } - - while(row2 < anchor.getRow2()){ - h += getRowHeightInPixels(sheet,row2++); - } - - if (isHSSF) { - h += getRowHeightInPixels(sheet,row2) * anchor.getDy2()/256; - } else { - h += anchor.getDy2()/(double)EMU_PER_PIXEL; - } - - w *= EMU_PER_PIXEL; - h *= EMU_PER_PIXEL; - - return new Dimension((int)Math.rint(w), (int)Math.rint(h)); + return new Dimension(w, h); } @@ -289,4 +217,78 @@ public class ImageUtils { double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints(); return Units.toEMU(points)/(double)EMU_PER_PIXEL; } + + private static void scaleCell(final double targetSize, + final int startCell, + final int startD, + Consumer endCell, + Consumer endD, + final int hssfUnits, + Function 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)EMU_PER_PIXEL; + } + } + delta = targetSize - totalDim; + if (delta < remDim) { + break; + } + } + + double endDval; + if (hssfUnits > 0) { + endDval = delta/dim * (double)hssfUnits; + } else { + endDval = delta * EMU_PER_PIXEL; + } + if (cellIdx == startCell) { + endDval += startD; + } + + endCell.accept(cellIdx); + endD.accept((int)Math.rint(endDval)); + } + + private static int getDimFromCell(double imgSize, int startCell, int startD, int endCell, int endD, int hssfUnits, + Function nextSize) { + double targetSize; + if (endCell < startCell) { + targetSize = imgSize * EMU_PER_PIXEL; + } else { + targetSize = 0; + for (int cellIdx = startCell; cellIdx<=endCell; cellIdx++) { + final double dim = nextSize.apply(cellIdx).doubleValue() * EMU_PER_PIXEL; + double leadSpace = 0; + if (cellIdx == startCell) { + //space in the leftmost cell + leadSpace = (hssfUnits > 0) + ? dim * startD/(double)hssfUnits + : startD; + } + + double trailSpace = 0; + if (cellIdx == endCell) { + // space after the rightmost cell + trailSpace = (hssfUnits > 0) + ? dim * (hssfUnits-endD)/(double)hssfUnits + : dim - endD; + } + targetSize += dim - leadSpace - trailSpace; + } + } + + return (int)Math.rint(targetSize); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java index 885b3d55c7..e5599479cf 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java @@ -17,7 +17,9 @@ package org.apache.poi.xssf.usermodel; -import static org.junit.Assert.*; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.util.List; @@ -31,59 +33,56 @@ import org.junit.Test; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.STEditAs; -/** - * @author Yegor Kozlov - */ public final class TestXSSFPicture extends BaseTestPicture { public TestXSSFPicture() { super(XSSFITestDataProvider.instance); } + @Test public void resize() throws Exception { - XSSFWorkbook wb = XSSFITestDataProvider.instance.openSampleWorkbook("resize_compare.xlsx"); - XSSFDrawing dp = wb.getSheetAt(0).createDrawingPatriarch(); - List pics = dp.getShapes(); - XSSFPicture inpPic = (XSSFPicture)pics.get(0); - XSSFPicture cmpPic = (XSSFPicture)pics.get(0); - - baseTestResize(inpPic, cmpPic, 2.0, 2.0); - wb.close(); + try (XSSFWorkbook wb = XSSFITestDataProvider.instance.openSampleWorkbook("resize_compare.xlsx")) { + XSSFDrawing dp = wb.getSheetAt(0).createDrawingPatriarch(); + List pics = dp.getShapes(); + XSSFPicture inpPic = (XSSFPicture) pics.get(0); + XSSFPicture cmpPic = (XSSFPicture) pics.get(0); + + baseTestResize(inpPic, cmpPic, 2.0, 2.0); + } } @Test public void create() throws IOException { - XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet(); - XSSFDrawing drawing = sheet.createDrawingPatriarch(); + try (XSSFWorkbook wb = new XSSFWorkbook()) { + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); - byte[] jpegData = "test jpeg data".getBytes(LocaleUtil.CHARSET_1252); + byte[] jpegData = "test jpeg data".getBytes(LocaleUtil.CHARSET_1252); - List pictures = wb.getAllPictures(); - assertEquals(0, pictures.size()); + List pictures = wb.getAllPictures(); + assertEquals(0, pictures.size()); - int jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); - assertEquals(1, pictures.size()); - assertEquals("jpeg", pictures.get(jpegIdx).suggestFileExtension()); - assertArrayEquals(jpegData, pictures.get(jpegIdx).getData()); + int jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); + assertEquals(1, pictures.size()); + assertEquals("jpeg", pictures.get(jpegIdx).suggestFileExtension()); + assertArrayEquals(jpegData, pictures.get(jpegIdx).getData()); - XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 1, 1, 10, 30); - assertEquals(AnchorType.MOVE_AND_RESIZE, anchor.getAnchorType()); - anchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE); - assertEquals(AnchorType.DONT_MOVE_AND_RESIZE, anchor.getAnchorType()); + XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 1, 1, 10, 30); + assertEquals(AnchorType.MOVE_AND_RESIZE, anchor.getAnchorType()); + anchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE); + assertEquals(AnchorType.DONT_MOVE_AND_RESIZE, anchor.getAnchorType()); - XSSFPicture shape = drawing.createPicture(anchor, jpegIdx); - assertEquals(anchor, shape.getAnchor()); - assertNotNull(shape.getPictureData()); - assertArrayEquals(jpegData, shape.getPictureData().getData()); + XSSFPicture shape = drawing.createPicture(anchor, jpegIdx); + assertEquals(anchor, shape.getAnchor()); + assertNotNull(shape.getPictureData()); + assertArrayEquals(jpegData, shape.getPictureData().getData()); - CTTwoCellAnchor ctShapeHolder = drawing.getCTDrawing().getTwoCellAnchorArray(0); - // STEditAs.ABSOLUTE corresponds to ClientAnchor.DONT_MOVE_AND_RESIZE - assertEquals(STEditAs.ABSOLUTE, ctShapeHolder.getEditAs()); - - wb.close(); + CTTwoCellAnchor ctShapeHolder = drawing.getCTDrawing().getTwoCellAnchorArray(0); + // STEditAs.ABSOLUTE corresponds to ClientAnchor.DONT_MOVE_AND_RESIZE + assertEquals(STEditAs.ABSOLUTE, ctShapeHolder.getEditAs()); + } } /** @@ -93,71 +92,69 @@ public final class TestXSSFPicture extends BaseTestPicture { */ @Test public void incrementShapeId() throws IOException { - XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet(); - XSSFDrawing drawing = sheet.createDrawingPatriarch(); + try (XSSFWorkbook wb = new XSSFWorkbook()) { + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); - XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 1, 1, 10, 30); - byte[] jpegData = "picture1".getBytes(LocaleUtil.CHARSET_1252); - int jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); + XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 1, 1, 10, 30); + byte[] jpegData = "picture1".getBytes(LocaleUtil.CHARSET_1252); + int jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); - XSSFPicture shape1 = drawing.createPicture(anchor, jpegIdx); - assertEquals(1, shape1.getCTPicture().getNvPicPr().getCNvPr().getId()); + XSSFPicture shape1 = drawing.createPicture(anchor, jpegIdx); + assertEquals(1, shape1.getCTPicture().getNvPicPr().getCNvPr().getId()); - jpegData = "picture2".getBytes(LocaleUtil.CHARSET_1252); - jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); - XSSFPicture shape2 = drawing.createPicture(anchor, jpegIdx); - assertEquals(2, shape2.getCTPicture().getNvPicPr().getCNvPr().getId()); - wb.close(); + jpegData = "picture2".getBytes(LocaleUtil.CHARSET_1252); + jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); + XSSFPicture shape2 = drawing.createPicture(anchor, jpegIdx); + assertEquals(2, shape2.getCTPicture().getNvPicPr().getCNvPr().getId()); + } } /** * same image refrerred by mulitple sheets */ - @SuppressWarnings("resource") @Test public void multiRelationShips() throws IOException { - XSSFWorkbook wb = new XSSFWorkbook(); + try (XSSFWorkbook wb1 = new XSSFWorkbook()) { + byte[] pic1Data = "test jpeg data".getBytes(LocaleUtil.CHARSET_1252); + byte[] pic2Data = "test png data".getBytes(LocaleUtil.CHARSET_1252); - byte[] pic1Data = "test jpeg data".getBytes(LocaleUtil.CHARSET_1252); - byte[] pic2Data = "test png data".getBytes(LocaleUtil.CHARSET_1252); + List pictures = wb1.getAllPictures(); + assertEquals(0, pictures.size()); - List pictures = wb.getAllPictures(); - assertEquals(0, pictures.size()); + int pic1 = wb1.addPicture(pic1Data, XSSFWorkbook.PICTURE_TYPE_JPEG); + int pic2 = wb1.addPicture(pic2Data, XSSFWorkbook.PICTURE_TYPE_PNG); - int pic1 = wb.addPicture(pic1Data, XSSFWorkbook.PICTURE_TYPE_JPEG); - int pic2 = wb.addPicture(pic2Data, XSSFWorkbook.PICTURE_TYPE_PNG); + XSSFSheet sheet1 = wb1.createSheet(); + XSSFDrawing drawing1 = sheet1.createDrawingPatriarch(); + XSSFPicture shape1 = drawing1.createPicture(new XSSFClientAnchor(), pic1); + XSSFPicture shape2 = drawing1.createPicture(new XSSFClientAnchor(), pic2); - XSSFSheet sheet1 = wb.createSheet(); - XSSFDrawing drawing1 = sheet1.createDrawingPatriarch(); - XSSFPicture shape1 = drawing1.createPicture(new XSSFClientAnchor(), pic1); - XSSFPicture shape2 = drawing1.createPicture(new XSSFClientAnchor(), pic2); + XSSFSheet sheet2 = wb1.createSheet(); + XSSFDrawing drawing2 = sheet2.createDrawingPatriarch(); + XSSFPicture shape3 = drawing2.createPicture(new XSSFClientAnchor(), pic2); + XSSFPicture shape4 = drawing2.createPicture(new XSSFClientAnchor(), pic1); - XSSFSheet sheet2 = wb.createSheet(); - XSSFDrawing drawing2 = sheet2.createDrawingPatriarch(); - XSSFPicture shape3 = drawing2.createPicture(new XSSFClientAnchor(), pic2); - XSSFPicture shape4 = drawing2.createPicture(new XSSFClientAnchor(), pic1); + assertEquals(2, pictures.size()); - assertEquals(2, pictures.size()); + try (XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(wb1)) { + pictures = wb2.getAllPictures(); + assertEquals(2, pictures.size()); - wb = XSSFTestDataSamples.writeOutAndReadBack(wb); - pictures = wb.getAllPictures(); - assertEquals(2, pictures.size()); + sheet1 = wb2.getSheetAt(0); + drawing1 = sheet1.createDrawingPatriarch(); + XSSFPicture shape11 = (XSSFPicture) drawing1.getShapes().get(0); + assertArrayEquals(shape1.getPictureData().getData(), shape11.getPictureData().getData()); + XSSFPicture shape22 = (XSSFPicture) drawing1.getShapes().get(1); + assertArrayEquals(shape2.getPictureData().getData(), shape22.getPictureData().getData()); - sheet1 = wb.getSheetAt(0); - drawing1 = sheet1.createDrawingPatriarch(); - XSSFPicture shape11 = (XSSFPicture)drawing1.getShapes().get(0); - assertArrayEquals(shape1.getPictureData().getData(), shape11.getPictureData().getData()); - XSSFPicture shape22 = (XSSFPicture)drawing1.getShapes().get(1); - assertArrayEquals(shape2.getPictureData().getData(), shape22.getPictureData().getData()); - - sheet2 = wb.getSheetAt(1); - drawing2 = sheet2.createDrawingPatriarch(); - XSSFPicture shape33 = (XSSFPicture)drawing2.getShapes().get(0); - assertArrayEquals(shape3.getPictureData().getData(), shape33.getPictureData().getData()); - XSSFPicture shape44 = (XSSFPicture)drawing2.getShapes().get(1); - assertArrayEquals(shape4.getPictureData().getData(), shape44.getPictureData().getData()); - - wb.close(); + sheet2 = wb2.getSheetAt(1); + drawing2 = sheet2.createDrawingPatriarch(); + XSSFPicture shape33 = (XSSFPicture) drawing2.getShapes().get(0); + assertArrayEquals(shape3.getPictureData().getData(), shape33.getPictureData().getData()); + XSSFPicture shape44 = (XSSFPicture) drawing2.getShapes().get(1); + assertArrayEquals(shape4.getPictureData().getData(), shape44.getPictureData().getData()); + } + } } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java index 21e47f8a56..ed18bf34ee 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java @@ -35,11 +35,6 @@ import org.apache.poi.ss.usermodel.PictureData; import org.apache.poi.ss.usermodel.Workbook; import org.junit.Test; -/** - * Test HSSFPicture. - * - * @author Yegor Kozlov (yegor at apache.org) - */ public final class TestHSSFPicture extends BaseTestPicture { public TestHSSFPicture() { @@ -48,248 +43,248 @@ public final class TestHSSFPicture extends BaseTestPicture { @Test public void resize() throws Exception { - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("resize_compare.xls"); - HSSFPatriarch dp = wb.getSheetAt(0).createDrawingPatriarch(); - List pics = dp.getChildren(); - HSSFPicture inpPic = (HSSFPicture)pics.get(0); - HSSFPicture cmpPic = (HSSFPicture)pics.get(1); - - baseTestResize(inpPic, cmpPic, 2.0, 2.0); - wb.close(); + try (HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("resize_compare.xls")) { + HSSFPatriarch dp = wb.getSheetAt(0).createDrawingPatriarch(); + List pics = dp.getChildren(); + HSSFPicture inpPic = (HSSFPicture) pics.get(0); + HSSFPicture cmpPic = (HSSFPicture) pics.get(1); + + baseTestResize(inpPic, cmpPic, 2.0, 2.0); + } } - + /** * Bug # 45829 reported ArithmeticException (/ by zero) when resizing png with zero DPI. */ @Test public void bug45829() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sh1 = wb.createSheet(); - HSSFPatriarch p1 = sh1.createDrawingPatriarch(); + try (HSSFWorkbook wb = new HSSFWorkbook()) { + HSSFSheet sh1 = wb.createSheet(); + HSSFPatriarch p1 = sh1.createDrawingPatriarch(); - byte[] pictureData = HSSFTestDataSamples.getTestDataFileContent("45829.png"); - int idx1 = wb.addPicture( pictureData, HSSFWorkbook.PICTURE_TYPE_PNG ); - HSSFPicture pic = p1.createPicture(new HSSFClientAnchor(), idx1); - pic.resize(); - - wb.close(); + byte[] pictureData = HSSFTestDataSamples.getTestDataFileContent("45829.png"); + int idx1 = wb.addPicture(pictureData, HSSFWorkbook.PICTURE_TYPE_PNG); + HSSFPicture pic = p1.createPicture(new HSSFClientAnchor(), idx1); + pic.resize(); + } } - @SuppressWarnings("resource") @Test public void addPictures() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); - - HSSFSheet sh = wb.createSheet("Pictures"); - HSSFPatriarch dr = sh.createDrawingPatriarch(); - assertEquals(0, dr.getChildren().size()); - HSSFClientAnchor anchor = wb.getCreationHelper().createClientAnchor(); + try (HSSFWorkbook wb1 = new HSSFWorkbook()) { - //register a picture - byte[] data1 = new byte[]{1, 2, 3}; - int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); - assertEquals(1, idx1); - HSSFPicture p1 = dr.createPicture(anchor, idx1); - assertArrayEquals(data1, p1.getPictureData().getData()); + HSSFSheet sh = wb1.createSheet("Pictures"); + HSSFPatriarch dr = sh.createDrawingPatriarch(); + assertEquals(0, dr.getChildren().size()); + HSSFClientAnchor anchor = wb1.getCreationHelper().createClientAnchor(); - // register another one - byte[] data2 = new byte[]{4, 5, 6}; - int idx2 = wb.addPicture(data2, Workbook.PICTURE_TYPE_JPEG); - assertEquals(2, idx2); - HSSFPicture p2 = dr.createPicture(anchor, idx2); - assertEquals(2, dr.getChildren().size()); - assertArrayEquals(data2, p2.getPictureData().getData()); + //register a picture + byte[] data1 = {1, 2, 3}; + int idx1 = wb1.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); + assertEquals(1, idx1); + HSSFPicture p1 = dr.createPicture(anchor, idx1); + assertArrayEquals(data1, p1.getPictureData().getData()); - // confirm that HSSFPatriarch.getChildren() returns two picture shapes - assertArrayEquals(data1, ((HSSFPicture)dr.getChildren().get(0)).getPictureData().getData()); - assertArrayEquals(data2, ((HSSFPicture)dr.getChildren().get(1)).getPictureData().getData()); + // register another one + byte[] data2 = {4, 5, 6}; + int idx2 = wb1.addPicture(data2, Workbook.PICTURE_TYPE_JPEG); + assertEquals(2, idx2); + HSSFPicture p2 = dr.createPicture(anchor, idx2); + assertEquals(2, dr.getChildren().size()); + assertArrayEquals(data2, p2.getPictureData().getData()); - // write, read back and verify that our pictures are there - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - List lst2 = wb.getAllPictures(); - assertEquals(2, lst2.size()); - assertArrayEquals(data1, lst2.get(0).getData()); - assertArrayEquals(data2, lst2.get(1).getData()); + // confirm that HSSFPatriarch.getChildren() returns two picture shapes + assertArrayEquals(data1, ((HSSFPicture) dr.getChildren().get(0)).getPictureData().getData()); + assertArrayEquals(data2, ((HSSFPicture) dr.getChildren().get(1)).getPictureData().getData()); - // confirm that the pictures are in the Sheet's drawing - sh = wb.getSheet("Pictures"); - dr = sh.createDrawingPatriarch(); - assertEquals(2, dr.getChildren().size()); - assertArrayEquals(data1, ((HSSFPicture)dr.getChildren().get(0)).getPictureData().getData()); - assertArrayEquals(data2, ((HSSFPicture)dr.getChildren().get(1)).getPictureData().getData()); + // write, read back and verify that our pictures are there + try (HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1)) { + List lst2 = wb2.getAllPictures(); + assertEquals(2, lst2.size()); + assertArrayEquals(data1, lst2.get(0).getData()); + assertArrayEquals(data2, lst2.get(1).getData()); - // add a third picture - byte[] data3 = new byte[]{7, 8, 9}; - // picture index must increment across write-read - int idx3 = wb.addPicture(data3, Workbook.PICTURE_TYPE_JPEG); - assertEquals(3, idx3); - HSSFPicture p3 = dr.createPicture(anchor, idx3); - assertArrayEquals(data3, p3.getPictureData().getData()); - assertEquals(3, dr.getChildren().size()); - assertArrayEquals(data1, ((HSSFPicture)dr.getChildren().get(0)).getPictureData().getData()); - assertArrayEquals(data2, ((HSSFPicture)dr.getChildren().get(1)).getPictureData().getData()); - assertArrayEquals(data3, ((HSSFPicture)dr.getChildren().get(2)).getPictureData().getData()); + // confirm that the pictures are in the Sheet's drawing + sh = wb2.getSheet("Pictures"); + dr = sh.createDrawingPatriarch(); + assertEquals(2, dr.getChildren().size()); + assertArrayEquals(data1, ((HSSFPicture) dr.getChildren().get(0)).getPictureData().getData()); + assertArrayEquals(data2, ((HSSFPicture) dr.getChildren().get(1)).getPictureData().getData()); - // write and read again - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - List lst3 = wb.getAllPictures(); - // all three should be there - assertEquals(3, lst3.size()); - assertArrayEquals(data1, lst3.get(0).getData()); - assertArrayEquals(data2, lst3.get(1).getData()); - assertArrayEquals(data3, lst3.get(2).getData()); + // add a third picture + byte[] data3 = {7, 8, 9}; + // picture index must increment across write-read + int idx3 = wb2.addPicture(data3, Workbook.PICTURE_TYPE_JPEG); + assertEquals(3, idx3); + HSSFPicture p3 = dr.createPicture(anchor, idx3); + assertArrayEquals(data3, p3.getPictureData().getData()); + assertEquals(3, dr.getChildren().size()); + assertArrayEquals(data1, ((HSSFPicture) dr.getChildren().get(0)).getPictureData().getData()); + assertArrayEquals(data2, ((HSSFPicture) dr.getChildren().get(1)).getPictureData().getData()); + assertArrayEquals(data3, ((HSSFPicture) dr.getChildren().get(2)).getPictureData().getData()); - sh = wb.getSheet("Pictures"); - dr = sh.createDrawingPatriarch(); - assertEquals(3, dr.getChildren().size()); + // write and read again + try (HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2)) { + List lst3 = wb3.getAllPictures(); + // all three should be there + assertEquals(3, lst3.size()); + assertArrayEquals(data1, lst3.get(0).getData()); + assertArrayEquals(data2, lst3.get(1).getData()); + assertArrayEquals(data3, lst3.get(2).getData()); - // forth picture - byte[] data4 = new byte[]{10, 11, 12}; - int idx4 = wb.addPicture(data4, Workbook.PICTURE_TYPE_JPEG); - assertEquals(4, idx4); - dr.createPicture(anchor, idx4); - assertEquals(4, dr.getChildren().size()); - assertArrayEquals(data1, ((HSSFPicture)dr.getChildren().get(0)).getPictureData().getData()); - assertArrayEquals(data2, ((HSSFPicture)dr.getChildren().get(1)).getPictureData().getData()); - assertArrayEquals(data3, ((HSSFPicture)dr.getChildren().get(2)).getPictureData().getData()); - assertArrayEquals(data4, ((HSSFPicture)dr.getChildren().get(3)).getPictureData().getData()); + sh = wb3.getSheet("Pictures"); + dr = sh.createDrawingPatriarch(); + assertEquals(3, dr.getChildren().size()); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - List lst4 = wb.getAllPictures(); - assertEquals(4, lst4.size()); - assertArrayEquals(data1, lst4.get(0).getData()); - assertArrayEquals(data2, lst4.get(1).getData()); - assertArrayEquals(data3, lst4.get(2).getData()); - assertArrayEquals(data4, lst4.get(3).getData()); - sh = wb.getSheet("Pictures"); - dr = sh.createDrawingPatriarch(); - assertEquals(4, dr.getChildren().size()); - assertArrayEquals(data1, ((HSSFPicture)dr.getChildren().get(0)).getPictureData().getData()); - assertArrayEquals(data2, ((HSSFPicture)dr.getChildren().get(1)).getPictureData().getData()); - assertArrayEquals(data3, ((HSSFPicture)dr.getChildren().get(2)).getPictureData().getData()); - assertArrayEquals(data4, ((HSSFPicture)dr.getChildren().get(3)).getPictureData().getData()); - - wb.close(); + // forth picture + byte[] data4 = {10, 11, 12}; + int idx4 = wb3.addPicture(data4, Workbook.PICTURE_TYPE_JPEG); + assertEquals(4, idx4); + dr.createPicture(anchor, idx4); + assertEquals(4, dr.getChildren().size()); + assertArrayEquals(data1, ((HSSFPicture) dr.getChildren().get(0)).getPictureData().getData()); + assertArrayEquals(data2, ((HSSFPicture) dr.getChildren().get(1)).getPictureData().getData()); + assertArrayEquals(data3, ((HSSFPicture) dr.getChildren().get(2)).getPictureData().getData()); + assertArrayEquals(data4, ((HSSFPicture) dr.getChildren().get(3)).getPictureData().getData()); + + try (HSSFWorkbook wb4 = HSSFTestDataSamples.writeOutAndReadBack(wb3)) { + List lst4 = wb4.getAllPictures(); + assertEquals(4, lst4.size()); + assertArrayEquals(data1, lst4.get(0).getData()); + assertArrayEquals(data2, lst4.get(1).getData()); + assertArrayEquals(data3, lst4.get(2).getData()); + assertArrayEquals(data4, lst4.get(3).getData()); + sh = wb4.getSheet("Pictures"); + dr = sh.createDrawingPatriarch(); + assertEquals(4, dr.getChildren().size()); + assertArrayEquals(data1, ((HSSFPicture) dr.getChildren().get(0)).getPictureData().getData()); + assertArrayEquals(data2, ((HSSFPicture) dr.getChildren().get(1)).getPictureData().getData()); + assertArrayEquals(data3, ((HSSFPicture) dr.getChildren().get(2)).getPictureData().getData()); + assertArrayEquals(data4, ((HSSFPicture) dr.getChildren().get(3)).getPictureData().getData()); + } + } + } + } } @SuppressWarnings("unused") @Test public void bsePictureRef() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); + try (HSSFWorkbook wb = new HSSFWorkbook()) { + HSSFSheet sh = wb.createSheet("Pictures"); + HSSFPatriarch dr = sh.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(); - HSSFSheet sh = wb.createSheet("Pictures"); - HSSFPatriarch dr = sh.createDrawingPatriarch(); - HSSFClientAnchor anchor = new HSSFClientAnchor(); + InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); - InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); + //register a picture + byte[] data1 = {1, 2, 3}; + int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); + assertEquals(1, idx1); + HSSFPicture p1 = dr.createPicture(anchor, idx1); - //register a picture - byte[] data1 = new byte[]{1, 2, 3}; - int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); - assertEquals(1, idx1); - HSSFPicture p1 = dr.createPicture(anchor, idx1); + EscherBSERecord bse = wb.getWorkbook().getBSERecord(idx1); - EscherBSERecord bse = wb.getWorkbook().getBSERecord(idx1); + assertEquals(bse.getRef(), 1); + dr.createPicture(new HSSFClientAnchor(), idx1); + assertEquals(bse.getRef(), 2); - assertEquals(bse.getRef(), 1); - dr.createPicture(new HSSFClientAnchor(), idx1); - assertEquals(bse.getRef(), 2); - - HSSFShapeGroup gr = dr.createGroup(new HSSFClientAnchor()); - gr.createPicture(new HSSFChildAnchor(), idx1); - assertEquals(bse.getRef(), 3); - - wb.close(); + HSSFShapeGroup gr = dr.createGroup(new HSSFClientAnchor()); + gr.createPicture(new HSSFChildAnchor(), idx1); + assertEquals(bse.getRef(), 3); + } } @Test - public void readExistingImage(){ - HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); - HSSFSheet sheet = wb.getSheet("picture"); - HSSFPatriarch drawing = sheet.getDrawingPatriarch(); - assertEquals(1, drawing.getChildren().size()); + public void readExistingImage() throws IOException { + try (HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls")) { + HSSFSheet sheet = wb.getSheet("picture"); + HSSFPatriarch drawing = sheet.getDrawingPatriarch(); + assertEquals(1, drawing.getChildren().size()); - HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); - assertEquals(picture.getFileName(), "test"); + HSSFPicture picture = (HSSFPicture) drawing.getChildren().get(0); + assertEquals(picture.getFileName(), "test"); + } } @SuppressWarnings("resource") @Test public void setGetProperties() throws IOException { - HSSFWorkbook wb = new HSSFWorkbook(); + try (HSSFWorkbook wb1 = new HSSFWorkbook()) { - HSSFSheet sh = wb.createSheet("Pictures"); - HSSFPatriarch dr = sh.createDrawingPatriarch(); - HSSFClientAnchor anchor = new HSSFClientAnchor(); + HSSFSheet sh = wb1.createSheet("Pictures"); + HSSFPatriarch dr = sh.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(); - //register a picture - byte[] data1 = new byte[]{1, 2, 3}; - int idx1 = wb.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); - HSSFPicture p1 = dr.createPicture(anchor, idx1); + //register a picture + byte[] data1 = {1, 2, 3}; + int idx1 = wb1.addPicture(data1, Workbook.PICTURE_TYPE_JPEG); + HSSFPicture p1 = dr.createPicture(anchor, idx1); - assertEquals(p1.getFileName(), ""); - p1.setFileName("aaa"); - assertEquals(p1.getFileName(), "aaa"); + assertEquals(p1.getFileName(), ""); + p1.setFileName("aaa"); + assertEquals(p1.getFileName(), "aaa"); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheet("Pictures"); - dr = sh.getDrawingPatriarch(); + try (HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1)) { + sh = wb2.getSheet("Pictures"); + dr = sh.getDrawingPatriarch(); - p1 = (HSSFPicture) dr.getChildren().get(0); - assertEquals(p1.getFileName(), "aaa"); - wb.close(); + p1 = (HSSFPicture) dr.getChildren().get(0); + assertEquals(p1.getFileName(), "aaa"); + } + } } @SuppressWarnings("resource") @Test public void bug49658() throws IOException { // test if inserted EscherMetafileBlip will be read again - HSSFWorkbook wb = new HSSFWorkbook(); + try (HSSFWorkbook wb1 = new HSSFWorkbook()) { - byte[] pictureDataEmf = POIDataSamples.getDocumentInstance().readFile("vector_image.emf"); - int indexEmf = wb.addPicture(pictureDataEmf, HSSFWorkbook.PICTURE_TYPE_EMF); - byte[] pictureDataPng = POIDataSamples.getSpreadSheetInstance().readFile("logoKarmokar4.png"); - int indexPng = wb.addPicture(pictureDataPng, HSSFWorkbook.PICTURE_TYPE_PNG); - byte[] pictureDataWmf = POIDataSamples.getSlideShowInstance().readFile("santa.wmf"); - int indexWmf = wb.addPicture(pictureDataWmf, HSSFWorkbook.PICTURE_TYPE_WMF); + byte[] pictureDataEmf = POIDataSamples.getDocumentInstance().readFile("vector_image.emf"); + int indexEmf = wb1.addPicture(pictureDataEmf, HSSFWorkbook.PICTURE_TYPE_EMF); + byte[] pictureDataPng = POIDataSamples.getSpreadSheetInstance().readFile("logoKarmokar4.png"); + int indexPng = wb1.addPicture(pictureDataPng, HSSFWorkbook.PICTURE_TYPE_PNG); + byte[] pictureDataWmf = POIDataSamples.getSlideShowInstance().readFile("santa.wmf"); + int indexWmf = wb1.addPicture(pictureDataWmf, HSSFWorkbook.PICTURE_TYPE_WMF); - HSSFSheet sheet = wb.createSheet(); - HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); - CreationHelper ch = wb.getCreationHelper(); + HSSFSheet sheet = wb1.createSheet(); + HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); + CreationHelper ch = wb1.getCreationHelper(); - ClientAnchor anchor = ch.createClientAnchor(); - anchor.setCol1(2); - anchor.setCol2(5); - anchor.setRow1(1); - anchor.setRow2(6); - patriarch.createPicture(anchor, indexEmf); - - anchor = ch.createClientAnchor(); - anchor.setCol1(2); - anchor.setCol2(5); - anchor.setRow1(10); - anchor.setRow2(16); - patriarch.createPicture(anchor, indexPng); + ClientAnchor anchor = ch.createClientAnchor(); + anchor.setCol1(2); + anchor.setCol2(5); + anchor.setRow1(1); + anchor.setRow2(6); + patriarch.createPicture(anchor, indexEmf); - anchor = ch.createClientAnchor(); - anchor.setCol1(6); - anchor.setCol2(9); - anchor.setRow1(1); - anchor.setRow2(6); - patriarch.createPicture(anchor, indexWmf); - - - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - byte[] pictureDataOut = wb.getAllPictures().get(0).getData(); - assertArrayEquals(pictureDataEmf, pictureDataOut); + anchor = ch.createClientAnchor(); + anchor.setCol1(2); + anchor.setCol2(5); + anchor.setRow1(10); + anchor.setRow2(16); + patriarch.createPicture(anchor, indexPng); - byte[] wmfNoHeader = new byte[pictureDataWmf.length - 22]; - System.arraycopy(pictureDataWmf, 22, wmfNoHeader, 0, pictureDataWmf.length-22); - pictureDataOut = wb.getAllPictures().get(2).getData(); - assertArrayEquals(wmfNoHeader, pictureDataOut); + anchor = ch.createClientAnchor(); + anchor.setCol1(6); + anchor.setCol2(9); + anchor.setRow1(1); + anchor.setRow2(6); + patriarch.createPicture(anchor, indexWmf); - wb.close(); + + try (HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1)) { + byte[] pictureDataOut = wb2.getAllPictures().get(0).getData(); + assertArrayEquals(pictureDataEmf, pictureDataOut); + + byte[] wmfNoHeader = new byte[pictureDataWmf.length - 22]; + System.arraycopy(pictureDataWmf, 22, wmfNoHeader, 0, pictureDataWmf.length - 22); + pictureDataOut = wb2.getAllPictures().get(2).getData(); + assertArrayEquals(wmfNoHeader, pictureDataOut); + } + } } } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java index 555a232480..b7cfac9000 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java @@ -17,26 +17,34 @@ package org.apache.poi.ss.usermodel; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import java.awt.BasicStroke; +import java.awt.Color; import java.awt.Dimension; +import java.awt.Graphics2D; import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.Arrays; import javax.imageio.ImageIO; import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.util.ImageUtils; import org.apache.poi.util.Units; import org.junit.Test; -/** - * @author Yegor Kozlov - */ public abstract class BaseTestPicture { private final ITestDataProvider _testDataProvider; @@ -47,15 +55,15 @@ public abstract class BaseTestPicture { public void baseTestResize(Picture input, Picture compare, double scaleX, double scaleY) { input.resize(scaleX, scaleY); - + ClientAnchor inpCA = input.getClientAnchor(); ClientAnchor cmpCA = compare.getClientAnchor(); - + Dimension inpDim = ImageUtils.getDimensionFromAnchor(input); Dimension cmpDim = ImageUtils.getDimensionFromAnchor(compare); double emuPX = Units.EMU_PER_PIXEL; - + assertEquals("the image height differs", inpDim.getHeight(), cmpDim.getHeight(), emuPX*6); assertEquals("the image width differs", inpDim.getWidth(), cmpDim.getWidth(), emuPX*6); assertEquals("the starting column differs", inpCA.getCol1(), cmpCA.getCol1()); @@ -63,10 +71,10 @@ public abstract class BaseTestPicture { assertEquals("the column y-offset differs", inpCA.getDy1(), cmpCA.getDy1(), 1); assertEquals("the ending columns differs", inpCA.getCol2(), cmpCA.getCol2()); // can't compare row heights because of variable test heights - + input.resize(); inpDim = ImageUtils.getDimensionFromAnchor(input); - + Dimension imgDim = input.getImageDimension(); assertEquals("the image height differs", imgDim.getHeight(), inpDim.getHeight()/emuPX, 1); @@ -103,29 +111,148 @@ public abstract class BaseTestPicture { CreationHelper createHelper = wb.getCreationHelper(); final byte[] bytes = HSSFITestDataProvider.instance.getTestDataFileContent("logoKarmokar4.png"); - + row.setHeightInPoints(getImageSize(bytes).y); - + int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); - + //add a picture shape ClientAnchor anchor = createHelper.createClientAnchor(); //set top-left corner of the picture, //subsequent call of Picture#resize() will operate relative to it anchor.setCol1(0); anchor.setRow1(0); - + Picture pict = drawing.createPicture(anchor, pictureIdx); - + //auto-size picture relative to its top-left corner pict.resize(); } - + private static Point getImageSize( byte [] image) throws IOException { BufferedImage img = ImageIO.read(new ByteArrayInputStream(image)); - + assertNotNull(img); - + return new Point(img.getWidth(), img.getHeight()); } + + @Test + public void bug64213() throws IOException { + int[] input = { + 200, 50 * 256, -1, + 400, 50 * 256, -1, + 200, 50 * 256, 200, + 400, 50 * 256, 200, + 400, 50 * 256, 400, + }; + + int[] expXSSF = { + 2, 952500, 2, 0, 2, 1905000, 7, 0, + 2, 952500, 2, 0, 2, 2857500, 12, 0, + 2, 952500, 2, 0, 2, 1905000, 2, 952500, + 2, 952500, 2, 0, 2, 2857500, 3, 0, + 2, 952500, 2, 0, 2, 2857500, 2, 1905000 + }; + + int[] expHSSF = { + 2, 292, 2, 0, 2, 584, 7, 226, + 2, 292, 2, 0, 2, 877, 13, 196, + 2, 292, 2, 0, 2, 584, 2, 128, + 2, 292, 2, 0, 2, 877, 3, 0, + 2, 292, 2, 0, 2, 877, 2, 128 + }; + + int[] expected = "xls".equals(_testDataProvider.getStandardFileNameExtension()) ? expHSSF : expXSSF; + + for (int i=0; i<5; i++) { + int[] inp = Arrays.copyOfRange(input, i*3, (i+1)*3); + int[] exp = Arrays.copyOfRange(expected, i*8, (i+1)*8); + int[] act = bug64213Helper(inp[0], inp[1], inp[2]); + assertArrayEquals(exp, act); + } + } + + private int[] bug64213Helper(int imgDim, int colWidth, int rowHeight) throws IOException { + final int col1 = 2; + final int dx1Pixel = 100; + final int row1 = 2; + final float scale = 0.5f; + + try (Workbook wb = _testDataProvider.createWorkbook()) { + Sheet sheet = wb.createSheet("Sheet1"); + + final byte[] bytes = createTestImage(imgDim, imgDim); + int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); + + sheet.setColumnWidth(col1, colWidth); + float col1px = sheet.getColumnWidthInPixels(col1); + if (rowHeight > -1) { + sheet.createRow(row1).setHeightInPoints((float) Units.pixelToPoints(rowHeight)); + } + + //create an anchor with upper left cell column/startRow, only one cell anchor since bottom right depends on resizing + CreationHelper helper = wb.getCreationHelper(); + ClientAnchor anchor = helper.createClientAnchor(); + anchor.setCol1(col1); + if (wb instanceof HSSFWorkbook) { + anchor.setDx1((int)(dx1Pixel * 1024 / col1px)); + } else { + anchor.setDx1(dx1Pixel * Units.EMU_PER_PIXEL); + } + anchor.setRow1(row1); + + + //create a picture anchored to Col1 and Row1 + Drawing drawing = sheet.createDrawingPatriarch(); + Picture pict = drawing.createPicture(anchor, pictureIdx); + + //resize the picture to it's native size + pict.resize(); + + //resize the picture scaled proportional + pict.resize(scale); + + ClientAnchor anc = (ClientAnchor)pict.getAnchor(); + return new int[]{ + anc.getCol1(), anc.getDx1(), + anc.getRow1(), anc.getDy1(), + anc.getCol2(), anc.getDx2(), + anc.getRow2(), anc.getDy2() + }; + } + } + + private static byte[] createTestImage(double width, double height) throws IOException { + BufferedImage bi = new BufferedImage((int)width, (int)height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = bi.createGraphics(); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + g.scale((width-1)/width, (height-1)/height); + + g.setStroke(new BasicStroke(1)); + + double ellSize = 5/6d; + Ellipse2D ell = new Ellipse2D.Double(width * (1-ellSize)/2d, height * (1-ellSize)/2d, width * ellSize, height * ellSize); + Color[] colors = { Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW }; + Rectangle2D rect = new Rectangle2D.Double(); + for (int i=0; i<4; i++) { + rect.setRect(width/2 * (i&1),height/2 * (i>>1&1), width/2, height/2); + Area a = new Area(rect); + a.subtract(new Area(ell)); + g.setPaint(colors[i]); + g.fill(a); + g.setColor(java.awt.Color.BLACK); + g.draw(rect); + } + g.draw(ell); + + g.dispose(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(2000); + ImageIO.write(bi, "PNG", bos); + return bos.toByteArray(); + } }