From: Andreas Beeker Date: Wed, 12 Nov 2014 00:19:00 +0000 (+0000) Subject: Picture method to resize with different scales in width and height X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=45fb6c5b1895772ba11452ce518a95bc9df1cb28;p=poi.git Picture method to resize with different scales in width and height git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1638623 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 2c4b59f7b0..2d2eaa752e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -21,7 +21,17 @@ import java.awt.Dimension; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; -import org.apache.poi.ddf.*; +import org.apache.poi.ddf.DefaultEscherRecordFactory; +import org.apache.poi.ddf.EscherBSERecord; +import org.apache.poi.ddf.EscherBlipRecord; +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherComplexProperty; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.record.ObjRecord; @@ -29,7 +39,6 @@ import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.util.ImageUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.apache.poi.hssf.model.InternalWorkbook; /** * Represents a escher picture. Eg. A GIF, JPEG etc... @@ -44,20 +53,6 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { public static final int PICTURE_TYPE_PNG = HSSFWorkbook.PICTURE_TYPE_PNG; // PNG public static final int PICTURE_TYPE_DIB = HSSFWorkbook.PICTURE_TYPE_DIB; // Windows DIB - /** - * width of 1px in columns with default width in units of 1/256 of a character width - */ - private static final float PX_DEFAULT = 32.00f; - /** - * width of 1px in columns with overridden width in units of 1/256 of a character width - */ - private static final float PX_MODIFIED = 36.56f; - - /** - * Height of 1px of a row - */ - private static final int PX_ROW = 15; - public HSSFPicture(EscherContainerRecord spContainer, ObjRecord objRecord) { super(spContainer, objRecord); } @@ -97,6 +92,28 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { return spContainer; } + /** + * Reset the image to the dimension of the embedded image + * + *

+ * Please note, that this method works correctly only for workbooks + * with default font size (Arial 10pt for .xls). + * If the default font is changed the resized image can be streched vertically or horizontally. + *

+ */ + public void resize(){ + resize(Double.MAX_VALUE); + } + + /** + * Resize the image proportionally. + * + * @see #resize(double, double) + */ + public void resize(double scale) { + resize(scale,scale); + } + /** * Resize the image *

@@ -104,42 +121,34 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { * with default font size (Arial 10pt for .xls). * If the default font is changed the resized image can be streched vertically or horizontally. *

+ *

+ * resize(1.0,1.0) keeps the original size,
+ * resize(0.5,0.5) resize to 50% of the original,
+ * resize(2.0,2.0) resizes to 200% of the original.
+ * resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE}) resizes to the dimension of the embedded image. + *

* - * @param scale the amount by which image dimensions are multiplied relative to the original size. - * resize(1.0) sets the original size, resize(0.5) resize to 50% of the original, - * resize(2.0) resizes to 200% of the original. + * @param scaleX the amount by which the image width is multiplied relative to the original width. + * @param scaleY the amount by which the image height is multiplied relative to the original height. */ - public void resize(double scale){ - HSSFClientAnchor anchor = (HSSFClientAnchor)getAnchor(); + public void resize(double scaleX, double scaleY) { + HSSFClientAnchor anchor = getClientAnchor(); anchor.setAnchorType(2); - HSSFClientAnchor pref = getPreferredSize(scale); + HSSFClientAnchor pref = getPreferredSize(scaleX,scaleY); int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1()); int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1()); anchor.setCol2((short)col2); - anchor.setDx1(0); + // anchor.setDx1(0); anchor.setDx2(pref.getDx2()); anchor.setRow2(row2); - anchor.setDy1(0); + // anchor.setDy1(0); anchor.setDy2(pref.getDy2()); } - /** - * Reset the image to the original size. - * - *

- * Please note, that this method works correctly only for workbooks - * with default font size (Arial 10pt for .xls). - * If the default font is changed the resized image can be streched vertically or horizontally. - *

- */ - public void resize(){ - resize(1.0); - } - /** * Calculate the preferred size for this picture. * @@ -158,86 +167,30 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { * @since POI 3.0.2 */ public HSSFClientAnchor getPreferredSize(double scale){ - HSSFClientAnchor anchor = (HSSFClientAnchor)getAnchor(); - - Dimension size = getImageDimension(); - double scaledWidth = size.getWidth() * scale; - double scaledHeight = size.getHeight() * scale; - - float w = 0; - - //space in the leftmost cell - w += getColumnWidthInPixels(anchor.getCol1())*(1 - (float)anchor.getDx1()/1024); - short col2 = (short)(anchor.getCol1() + 1); - int dx2 = 0; - - while(w < scaledWidth){ - w += getColumnWidthInPixels(col2++); - } - - if(w > scaledWidth) { - //calculate dx2, offset in the rightmost cell - col2--; - double cw = getColumnWidthInPixels(col2); - double delta = w - scaledWidth; - dx2 = (int)((cw-delta)/cw*1024); - } - anchor.setCol2(col2); - anchor.setDx2(dx2); - - float h = 0; - h += (1 - (float)anchor.getDy1()/256)* getRowHeightInPixels(anchor.getRow1()); - int row2 = anchor.getRow1() + 1; - int dy2 = 0; - - while(h < scaledHeight){ - h += getRowHeightInPixels(row2++); - } - if(h > scaledHeight) { - row2--; - double ch = getRowHeightInPixels(row2); - double delta = h - scaledHeight; - dy2 = (int)((ch-delta)/ch*256); - } - anchor.setRow2(row2); - anchor.setDy2(dy2); - - return anchor; - } - - private float getColumnWidthInPixels(int column){ - - int cw = getPatriarch().getSheet().getColumnWidth(column); - float px = getPixelWidth(column); - - return cw/px; + return getPreferredSize(scale, scale); } - - private float getRowHeightInPixels(int i){ - - HSSFRow row = getPatriarch().getSheet().getRow(i); - float height; - if(row != null) height = row.getHeight(); - else height = getPatriarch().getSheet().getDefaultRowHeight(); - - return height/PX_ROW; - } - - private float getPixelWidth(int column){ - - int def = getPatriarch().getSheet().getDefaultColumnWidth()*256; - int cw = getPatriarch().getSheet().getColumnWidth(column); - - return cw == def ? PX_DEFAULT : PX_MODIFIED; + + /** + * Calculate the preferred size for this picture. + * + * @param scaleX the amount by which image width is multiplied relative to the original width. + * @param scaleY the amount by which image height is multiplied relative to the original height. + * @return HSSFClientAnchor with the preferred size for this image + * @since POI 3.11 + */ + public HSSFClientAnchor getPreferredSize(double scaleX, double scaleY){ + ImageUtils.setPreferredSize(this, scaleX, scaleY); + return getClientAnchor(); } /** - * Return the dimension of this image + * Return the dimension of the embedded image in pixel * - * @return image dimension + * @return image dimension in pixels */ public Dimension getImageDimension(){ - EscherBSERecord bse = getPatriarch().getSheet()._book.getBSERecord(getPictureIndex()); + InternalWorkbook iwb = getPatriarch().getSheet().getWorkbook().getWorkbook(); + EscherBSERecord bse = iwb.getBSERecord(getPictureIndex()); byte[] data = bse.getBlipRecord().getPicturedata(); int type = bse.getBlipTypeWin32(); return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type); @@ -250,7 +203,8 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { */ public HSSFPictureData getPictureData(){ InternalWorkbook iwb = getPatriarch().getSheet().getWorkbook().getWorkbook(); - EscherBlipRecord blipRecord = iwb.getBSERecord(getPictureIndex()).getBlipRecord(); + EscherBSERecord bse = iwb.getBSERecord(getPictureIndex()); + EscherBlipRecord blipRecord = bse.getBlipRecord(); return new HSSFPictureData(blipRecord); } @@ -301,4 +255,22 @@ public class HSSFPicture extends HSSFSimpleShape implements Picture { ObjRecord obj = (ObjRecord) getObjRecord().cloneViaReserialise(); return new HSSFPicture(spContainer, obj); } + + /** + * @return the anchor that is used by this picture. + */ + @Override + public HSSFClientAnchor getClientAnchor() { + HSSFAnchor a = getAnchor(); + return (a instanceof HSSFClientAnchor) ? (HSSFClientAnchor)a : null; + } + + + /** + * @return the sheet which contains the picture shape + */ + @Override + public HSSFSheet getSheet() { + return getPatriarch().getSheet(); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPictureData.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPictureData.java index 93fa26f5ba..267bd2e1d6 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPictureData.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPictureData.java @@ -22,6 +22,7 @@ import org.apache.poi.ddf.EscherBitmapBlip; import org.apache.poi.ddf.EscherBlipRecord; import org.apache.poi.ddf.EscherMetafileBlip; import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.PngUtils; /** @@ -131,4 +132,33 @@ public class HSSFPictureData implements PictureData return "image/unknown"; } } + + /** + * @return the POI internal image type, -1 if not unknown image type + * + * @see Workbook#PICTURE_TYPE_DIB + * @see Workbook#PICTURE_TYPE_EMF + * @see Workbook#PICTURE_TYPE_JPEG + * @see Workbook#PICTURE_TYPE_PICT + * @see Workbook#PICTURE_TYPE_PNG + * @see Workbook#PICTURE_TYPE_WMF + */ + public int getPictureType() { + switch (blip.getRecordId()) { + case EscherMetafileBlip.RECORD_ID_WMF: + return Workbook.PICTURE_TYPE_WMF; + case EscherMetafileBlip.RECORD_ID_EMF: + return Workbook.PICTURE_TYPE_EMF; + case EscherMetafileBlip.RECORD_ID_PICT: + return Workbook.PICTURE_TYPE_PICT; + case EscherBitmapBlip.RECORD_ID_PNG: + return Workbook.PICTURE_TYPE_PNG; + case EscherBitmapBlip.RECORD_ID_JPEG: + return Workbook.PICTURE_TYPE_JPEG; + case EscherBitmapBlip.RECORD_ID_DIB: + return Workbook.PICTURE_TYPE_DIB; + default: + return -1; + } + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index ce09d8012d..e7ed838ecc 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -76,6 +76,16 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { private static final POILogger log = POILogFactory.getLogger(HSSFSheet.class); private static final int DEBUG = POILogger.DEBUG; + /** + * width of 1px in columns with default width in units of 1/256 of a character width + */ + private static final float PX_DEFAULT = 32.00f; + /** + * width of 1px in columns with overridden width in units of 1/256 of a character width + */ + private static final float PX_MODIFIED = 36.56f; + + /** * Used for compile-time optimization. This is the initial size for the collection of * rows. It is currently set to 20. If you generate larger sheets you may benefit @@ -555,6 +565,14 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet { return _sheet.getColumnWidth(columnIndex); } + public float getColumnWidthInPixels(int column){ + int cw = getColumnWidth(column); + int def = getDefaultColumnWidth()*256; + float px = (cw == def ? PX_DEFAULT : PX_MODIFIED); + + return cw/px; + } + /** * get the default column width for the sheet (if the columns do not define their own width) in * characters diff --git a/src/java/org/apache/poi/ss/usermodel/Picture.java b/src/java/org/apache/poi/ss/usermodel/Picture.java index c79260c6ee..58ad448125 100644 --- a/src/java/org/apache/poi/ss/usermodel/Picture.java +++ b/src/java/org/apache/poi/ss/usermodel/Picture.java @@ -16,6 +16,9 @@ ==================================================================== */ package org.apache.poi.ss.usermodel; +import java.awt.Dimension; + + /** * Repersents a picture in a SpreadsheetML document * @@ -24,33 +27,61 @@ package org.apache.poi.ss.usermodel; public interface Picture { /** - * Reset the image to the original size. + * Reset the image to the dimension of the embedded image * - *

- * Please note, that this method works correctly only for workbooks - * with default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). - * If the default font is changed the resized image can be streched vertically or horizontally. - *

+ * @see #resize(double, double) */ void resize(); /** - * Reset the image to the original size. + * Resize the image proportionally. * + * @see #resize(double, double) + */ + void resize(double scale); + + /** + * Resize the image. *

* Please note, that this method works correctly only for workbooks - * with default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). - * If the default font is changed the resize() procedure can be 'off'. + * with the default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). + * If the default font is changed the resized image can be streched vertically or horizontally. + *

+ *

+ * resize(1.0,1.0) keeps the original size,
+ * resize(0.5,0.5) resize to 50% of the original,
+ * resize(2.0,2.0) resizes to 200% of the original.
+ * resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE}) resizes to the dimension of the embedded image. *

* - * @param scale the amount by which image dimensions are multiplied relative to the original size. - * resize(1.0) sets the original size, resize(0.5) resize to 50% of the original, - * resize(2.0) resizes to 200% of the original. + * @param scaleX the amount by which the image width is multiplied relative to the original width. + * @param scaleY the amount by which the image height is multiplied relative to the original height. */ - void resize(double scale); + void resize(double scaleX, double scaleY); + /** + * Calculate the preferred size for this picture. + * + * @return XSSFClientAnchor with the preferred size for this image + */ ClientAnchor getPreferredSize(); + /** + * Calculate the preferred size for this picture. + * + * @param scaleX the amount by which image width is multiplied relative to the original width. + * @param scaleY the amount by which image height is multiplied relative to the original height. + * @return ClientAnchor with the preferred size for this image + */ + ClientAnchor getPreferredSize(double scaleX, double scaleY); + + /** + * Return the dimension of the embedded image in pixel + * + * @return image dimension in pixels + */ + Dimension getImageDimension(); + /** * Return picture data for this picture * @@ -58,4 +89,14 @@ public interface Picture { */ PictureData getPictureData(); + /** + * @return the anchor that is used by this picture + */ + ClientAnchor getClientAnchor(); + + + /** + * @return the sheet which contains the picture + */ + Sheet getSheet(); } diff --git a/src/java/org/apache/poi/ss/usermodel/PictureData.java b/src/java/org/apache/poi/ss/usermodel/PictureData.java index 954337829d..67d3cefcd1 100644 --- a/src/java/org/apache/poi/ss/usermodel/PictureData.java +++ b/src/java/org/apache/poi/ss/usermodel/PictureData.java @@ -37,4 +37,16 @@ public interface PictureData { * Returns the mime type for the image */ String getMimeType(); + + /** + * @return the POI internal image type, 0 if unknown image type + * + * @see Workbook#PICTURE_TYPE_DIB + * @see Workbook#PICTURE_TYPE_EMF + * @see Workbook#PICTURE_TYPE_JPEG + * @see Workbook#PICTURE_TYPE_PICT + * @see Workbook#PICTURE_TYPE_PNG + * @see Workbook#PICTURE_TYPE_WMF + */ + int getPictureType(); } \ No newline at end of file diff --git a/src/java/org/apache/poi/ss/usermodel/Sheet.java b/src/java/org/apache/poi/ss/usermodel/Sheet.java index 57c8785c6c..d1bd67416a 100644 --- a/src/java/org/apache/poi/ss/usermodel/Sheet.java +++ b/src/java/org/apache/poi/ss/usermodel/Sheet.java @@ -186,11 +186,26 @@ public interface Sheet extends Iterable { * using the default font (first font in the workbook) *

* - * @param columnIndex - the column to set (0-based) + * @param columnIndex - the column to get (0-based) * @return width - the width in units of 1/256th of a character width */ int getColumnWidth(int columnIndex); + /** + * get the width in pixel + * + *

+ * Please note, that this method works correctly only for workbooks + * with the default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). + * If the default font is changed the column width can be streched + *

+ * + * @param columnIndex - the column to set (0-based) + * @return width in pixels + */ + float getColumnWidthInPixels(int columnIndex); + + /** * Set the default column width for the sheet (if the columns do not define their own width) * in characters @@ -214,7 +229,7 @@ public interface Sheet extends Iterable { * @return default row height measured in twips (1/20 of a point) */ short getDefaultRowHeight(); - + /** * Get the default row height for the sheet (if the rows do not define their own height) in * points. @@ -922,7 +937,7 @@ public interface Sheet extends Iterable { public DataValidationHelper getDataValidationHelper(); - /** + /** * Returns the list of DataValidation in the sheet. * @return list of DataValidation in the sheet */ diff --git a/src/java/org/apache/poi/ss/util/ImageUtils.java b/src/java/org/apache/poi/ss/util/ImageUtils.java index 76ebc0370c..b470824519 100644 --- a/src/java/org/apache/poi/ss/util/ImageUtils.java +++ b/src/java/org/apache/poi/ss/util/ImageUtils.java @@ -16,21 +16,32 @@ ==================================================================== */ package org.apache.poi.ss.util; -import org.w3c.dom.NodeList; -import org.w3c.dom.Element; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; +import static org.apache.poi.util.Units.EMU_PER_PIXEL; -import javax.imageio.ImageReader; -import javax.imageio.ImageIO; -import javax.imageio.stream.ImageInputStream; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.awt.*; -import java.awt.image.BufferedImage; import java.util.Iterator; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Picture; +import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row; +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.Units; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + /** * @author Yegor Kozlov */ @@ -60,8 +71,8 @@ public class ImageUtils { try { //read the image using javax.imageio.* ImageInputStream iis = ImageIO.createImageInputStream( is ); - Iterator i = ImageIO.getImageReaders( iis ); - ImageReader r = (ImageReader) i.next(); + Iterator i = ImageIO.getImageReaders( iis ); + ImageReader r = i.next(); r.setInput( iis ); BufferedImage img = r.read(0); @@ -113,4 +124,154 @@ public class ImageUtils { return new int[]{hdpi, vdpi}; } + /** + * Calculate and set the preferred size (anchor) for this picture. + * + * @param scaleX the amount by which image width is multiplied relative to the original width. + * @param scaleY the amount by which image height is multiplied relative to the original height. + * @return the new Dimensions of the scaled picture in EMUs + */ + public static Dimension setPreferredSize(Picture picture, double scaleX, double scaleY){ + ClientAnchor anchor = picture.getClientAnchor(); + boolean isHSSF = (anchor instanceof HSSFClientAnchor); + PictureData data = picture.getPictureData(); + Sheet sheet = picture.getSheet(); + + // in pixel + Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType()); + // in emus + Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture); + 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; + + //space in the leftmost cell + w = sheet.getColumnWidthInPixels(col2++); + if (isHSSF) { + w *= 1 - anchor.getDx1()/1024d; + } else { + w -= anchor.getDx1()/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()/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); + + Dimension dim = new Dimension( + (int)Math.round(scaledWidth*EMU_PER_PIXEL), + (int)Math.round(scaledHeight*EMU_PER_PIXEL) + ); + + return dim; + } + + /** + * Calculates the dimensions in EMUs for the anchor of the given picture + * + * @param picture the picture containing the anchor + * @return the dimensions in EMUs + */ + public static Dimension getDimensionFromAnchor(Picture picture) { + ClientAnchor anchor = picture.getClientAnchor(); + 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()/EMU_PER_PIXEL; + } + + while(col2 < anchor.getCol2()){ + w += sheet.getColumnWidthInPixels(col2++); + } + + if (isHSSF) { + w += sheet.getColumnWidthInPixels(col2) * anchor.getDx2()/1024d; + } else { + w += anchor.getDx2()/EMU_PER_PIXEL; + } + + double h = 0; + int row2 = anchor.getRow1(); + + h = getRowHeightInPixels(sheet,row2++); + if (isHSSF) { + h *= 1 - anchor.getDy1()/256d; + } else { + h -= anchor.getDy1()/EMU_PER_PIXEL; + } + + while(row2 < anchor.getRow2()){ + h += getRowHeightInPixels(sheet,row2++); + } + + if (isHSSF) { + h += getRowHeightInPixels(sheet,row2) * anchor.getDy2()/256; + } else { + h += anchor.getDy2()/EMU_PER_PIXEL; + } + + return new Dimension((int)w*EMU_PER_PIXEL, (int)h*EMU_PER_PIXEL); + } + + + private static double getRowHeightInPixels(Sheet sheet, int rowNum) { + Row r = sheet.getRow(rowNum); + double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints(); + return Units.toEMU(points)/EMU_PER_PIXEL; + } } diff --git a/src/java/org/apache/poi/util/Units.java b/src/java/org/apache/poi/util/Units.java new file mode 100644 index 0000000000..91584b2ad5 --- /dev/null +++ b/src/java/org/apache/poi/util/Units.java @@ -0,0 +1,43 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.util; + +/** + * @author Yegor Kozlov + */ +public class Units { + public static final int EMU_PER_PIXEL = 9525; + public static final int EMU_PER_POINT = 12700; + + /** + * Converts points to EMUs + * @param points points + * @return emus + */ + public static int toEMU(double points){ + return (int)Math.round(EMU_PER_POINT*points); + } + + /** + * Converts EMUs to points + * @param emu emu + * @return points + */ + public static double toPoints(long emu){ + return (double)emu/EMU_PER_POINT; + } +} diff --git a/src/ooxml/java/org/apache/poi/util/Units.java b/src/ooxml/java/org/apache/poi/util/Units.java deleted file mode 100644 index 3a400399c7..0000000000 --- a/src/ooxml/java/org/apache/poi/util/Units.java +++ /dev/null @@ -1,33 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.util; - -/** - * @author Yegor Kozlov - */ -public class Units { - public static final int EMU_PER_PIXEL = 9525; - public static final int EMU_PER_POINT = 12700; - - public static int toEMU(double value){ - return (int)Math.round(EMU_PER_POINT*value); - } - - public static double toPoints(long emu){ - return (double)emu/EMU_PER_POINT; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java index d676eb599e..2700e16785 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java @@ -264,6 +264,19 @@ public class SXSSFSheet implements Sheet, Cloneable return _sh.getColumnWidth(columnIndex); } + /** + * Get the actual column width in pixels + * + *

+ * Please note, that this method works correctly only for workbooks + * with the default font size (Calibri 11pt for .xlsx). + *

+ */ + @Override + public float getColumnWidthInPixels(int columnIndex) { + return _sh.getColumnWidthInPixels(columnIndex); + } + /** * Set the default column width for the sheet (if the columns do not define their own width) * in characters diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java index 47402bdc35..1d87faceee 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java @@ -20,15 +20,14 @@ package org.apache.poi.xssf.usermodel; import java.awt.Dimension; import java.io.IOException; -import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.ImageUtils; +import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.apache.poi.util.Internal; import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualPictureProperties; @@ -40,7 +39,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPicture; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPictureNonVisual; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol; /** * Represents a picture shape in a SpreadsheetML drawing. @@ -57,7 +55,7 @@ public final class XSSFPicture extends XSSFShape implements Picture { * * This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial) */ - private static float DEFAULT_COLUMN_WIDTH = 9.140625f; + // private static float DEFAULT_COLUMN_WIDTH = 9.140625f; /** * A default instance of CTShape used for creating new shapes. @@ -140,44 +138,56 @@ public final class XSSFPicture extends XSSFShape implements Picture { } /** - * Reset the image to the original size. + * Reset the image to the dimension of the embedded image * - *

- * Please note, that this method works correctly only for workbooks - * with the default font size (Calibri 11pt for .xlsx). - * If the default font is changed the resized image can be streched vertically or horizontally. - *

+ * @see #resize(double, double) */ public void resize(){ - resize(1.0); + resize(Double.MAX_VALUE); } /** - * Reset the image to the original size. + * Resize the image proportionally. + * + * @see #resize(double, double) + */ + public void resize(double scale) { + resize(scale, scale); + } + + /** + * Resize the image relatively to its current size. *

* Please note, that this method works correctly only for workbooks * with the default font size (Calibri 11pt for .xlsx). * If the default font is changed the resized image can be streched vertically or horizontally. *

+ *

+ * resize(1.0,1.0) keeps the original size,
+ * resize(0.5,0.5) resize to 50% of the original,
+ * resize(2.0,2.0) resizes to 200% of the original.
+ * resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE}) resizes to the dimension of the embedded image. + *

* - * @param scale the amount by which image dimensions are multiplied relative to the original size. - * resize(1.0) sets the original size, resize(0.5) resize to 50% of the original, - * resize(2.0) resizes to 200% of the original. + * @param scaleX the amount by which the image width is multiplied relative to the original width, + * when set to {@link java.lang.Double#MAX_VALUE} the width of the embedded image is used + * @param scaleY the amount by which the image height is multiplied relative to the original height, + * when set to {@link java.lang.Double#MAX_VALUE} the height of the embedded image is used */ - public void resize(double scale){ - XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); + public void resize(double scaleX, double scaleY){ + XSSFClientAnchor anchor = getClientAnchor(); - XSSFClientAnchor pref = getPreferredSize(scale); + XSSFClientAnchor pref = getPreferredSize(scaleX,scaleY); int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1()); int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1()); anchor.setCol2(col2); - anchor.setDx1(0); + // anchor.setDx1(0); anchor.setDx2(pref.getDx2()); anchor.setRow2(row2); - anchor.setDy1(0); + // anchor.setDy1(0); anchor.setDy2(pref.getDy2()); } @@ -197,71 +207,22 @@ public final class XSSFPicture extends XSSFShape implements Picture { * @return XSSFClientAnchor with the preferred size for this image */ public XSSFClientAnchor getPreferredSize(double scale){ - XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); - - XSSFPictureData data = getPictureData(); - Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType()); - double scaledWidth = size.getWidth() * scale; - double scaledHeight = size.getHeight() * scale; - - float w = 0; - int col2 = anchor.getCol1(); - int dx2 = 0; - - for (;;) { - w += getColumnWidthInPixels(col2); - if(w > scaledWidth) break; - col2++; - } - - if(w > scaledWidth) { - double cw = getColumnWidthInPixels(col2 ); - double delta = w - scaledWidth; - dx2 = (int)(EMU_PER_PIXEL*(cw-delta)); - } - anchor.setCol2(col2); - anchor.setDx2(dx2); - - double h = 0; - int row2 = anchor.getRow1(); - int dy2 = 0; - - for (;;) { - h += getRowHeightInPixels(row2); - if(h > scaledHeight) break; - row2++; - } - - if(h > scaledHeight) { - double ch = getRowHeightInPixels(row2); - double delta = h - scaledHeight; - dy2 = (int)(EMU_PER_PIXEL*(ch-delta)); - } - anchor.setRow2(row2); - anchor.setDy2(dy2); - - CTPositiveSize2D size2d = ctPicture.getSpPr().getXfrm().getExt(); - size2d.setCx((long)(scaledWidth*EMU_PER_PIXEL)); - size2d.setCy((long)(scaledHeight*EMU_PER_PIXEL)); - - return anchor; - } - - private float getColumnWidthInPixels(int columnIndex){ - XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); - - CTCol col = sheet.getColumnHelper().getColumn(columnIndex, false); - double numChars = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth(); - - return (float)numChars*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH; + return getPreferredSize(scale, scale); } - - private float getRowHeightInPixels(int rowIndex){ - XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); - - XSSFRow row = sheet.getRow(rowIndex); - float height = row != null ? row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints(); - return height*PIXEL_DPI/POINT_DPI; + + /** + * Calculate the preferred size for this picture. + * + * @param scaleX the amount by which image width is multiplied relative to the original width. + * @param scaleY the amount by which image height is multiplied relative to the original height. + * @return XSSFClientAnchor with the preferred size for this image + */ + public XSSFClientAnchor getPreferredSize(double scaleX, double scaleY){ + Dimension dim = ImageUtils.setPreferredSize(this, scaleX, scaleY); + CTPositiveSize2D size2d = ctPicture.getSpPr().getXfrm().getExt(); + size2d.setCx((int)dim.getWidth()); + size2d.setCy((int)dim.getHeight()); + return getClientAnchor(); } /** @@ -283,6 +244,16 @@ public final class XSSFPicture extends XSSFShape implements Picture { } } + /** + * Return the dimension of the embedded image in pixel + * + * @return image dimension in pixels + */ + public Dimension getImageDimension() { + XSSFPictureData picData = getPictureData(); + return getImageDimension(picData.getPackagePart(), picData.getPictureType()); + } + /** * Return picture data for this shape * @@ -297,4 +268,20 @@ public final class XSSFPicture extends XSSFShape implements Picture { return ctPicture.getSpPr(); } + /** + * @return the anchor that is used by this shape. + */ + @Override + public XSSFClientAnchor getClientAnchor() { + XSSFAnchor a = getAnchor(); + return (a instanceof XSSFClientAnchor) ? (XSSFClientAnchor)a : null; + } + + /** + * @return the sheet which contains the picture shape + */ + @Override + public XSSFSheet getSheet() { + return (XSSFSheet)getDrawing().getParent(); + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index ac72c76803..a5a8b311b6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -704,6 +704,22 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return (int)(width*256); } + /** + * Get the actual column width in pixels + * + *

+ * Please note, that this method works correctly only for workbooks + * with the default font size (Calibri 11pt for .xlsx). + *

+ */ + @Override + public float getColumnWidthInPixels(int columnIndex) { + int styleIdx = getColumnHelper().getColDefaultStyle(columnIndex); + CellStyle cs = getWorkbook().getStylesSource().getStyleAt(styleIdx); + float widthIn256 = getColumnWidth(columnIndex); + return (float)(widthIn256/256.0*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH); + } + /** * Get the default column width for the sheet (if the columns do not define their own width) in * characters. @@ -730,6 +746,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return (short)(getDefaultRowHeightInPoints() * 20); } + /** * Get the default row height for the sheet measued in point size (if the rows do not define their own height). * 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 f6b05586e6..5415502b12 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPicture.java @@ -18,13 +18,25 @@ package org.apache.poi.xssf.usermodel; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.List; +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFPicture; +import org.apache.poi.hssf.usermodel.HSSFShape; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.BaseTestPicture; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; +import org.junit.Ignore; +import org.junit.Test; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.STEditAs; @@ -37,12 +49,21 @@ public final class TestXSSFPicture extends BaseTestPicture { super(XSSFITestDataProvider.instance); } - public void testResize() { - baseTestResize(new XSSFClientAnchor(0, 0, 504825, 85725, (short)0, 0, (short)1, 8)); + @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(); } - public void testCreate(){ + @Test + public void create() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet(); XSSFDrawing drawing = sheet.createDrawingPatriarch(); @@ -70,6 +91,8 @@ public final class TestXSSFPicture extends BaseTestPicture { CTTwoCellAnchor ctShapeHolder = drawing.getCTDrawing().getTwoCellAnchorArray(0); // STEditAs.ABSOLUTE corresponds to ClientAnchor.DONT_MOVE_AND_RESIZE assertEquals(STEditAs.ABSOLUTE, ctShapeHolder.getEditAs()); + + wb.close(); } /** @@ -77,7 +100,8 @@ public final class TestXSSFPicture extends BaseTestPicture { * * See Bugzilla 50458 */ - public void testShapeId(){ + @Test + public void incrementShapeId() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet(); XSSFDrawing drawing = sheet.createDrawingPatriarch(); @@ -93,12 +117,15 @@ public final class TestXSSFPicture extends BaseTestPicture { jpegIdx = wb.addPicture(jpegData, XSSFWorkbook.PICTURE_TYPE_JPEG); XSSFPicture shape2 = drawing.createPicture(anchor, jpegIdx); assertEquals(2, shape2.getCTPicture().getNvPicPr().getCNvPr().getId()); + wb.close(); } /** * same image refrerred by mulitple sheets */ - public void testMultiRelationShips(){ + @SuppressWarnings("resource") + @Test + public void multiRelationShips() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); byte[] pic1Data = "test jpeg data".getBytes(); @@ -140,6 +167,7 @@ public final class TestXSSFPicture extends BaseTestPicture { XSSFPicture shape44 = (XSSFPicture)drawing2.getShapes().get(1); assertArrayEquals(shape4.getPictureData().getData(), shape44.getPictureData().getData()); + wb.close(); } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java index 132a45af5c..7a1ae1f1b6 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPicture.java @@ -18,7 +18,10 @@ package org.apache.poi.hssf.usermodel; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.util.List; @@ -32,6 +35,8 @@ import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.PictureData; import org.apache.poi.ss.usermodel.Workbook; +import org.junit.Test; +import org.junit.Ignore; /** * Test HSSFPicture. @@ -44,14 +49,23 @@ public final class TestHSSFPicture extends BaseTestPicture { super(HSSFITestDataProvider.instance); } - public void testResize() { - baseTestResize(new HSSFClientAnchor(0, 0, 848, 240, (short)0, 0, (short)1, 9)); + @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(); } - + /** * Bug # 45829 reported ArithmeticException (/ by zero) when resizing png with zero DPI. */ - public void test45829() { + @Test + public void bug45829() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh1 = wb.createSheet(); HSSFPatriarch p1 = sh1.createDrawingPatriarch(); @@ -60,10 +74,14 @@ public final class TestHSSFPicture extends BaseTestPicture { int idx1 = wb.addPicture( pictureData, HSSFWorkbook.PICTURE_TYPE_PNG ); HSSFPicture pic = p1.createPicture(new HSSFClientAnchor(), idx1); pic.resize(); + + wb.close(); } - public void testAddPictures(){ + @SuppressWarnings("resource") + @Test + public void addPictures() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet("Pictures"); @@ -154,9 +172,13 @@ public final class TestHSSFPicture extends BaseTestPicture { 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(); } - public void testBSEPictureRef(){ + @SuppressWarnings("unused") + @Test + public void bsePictureRef() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet("Pictures"); @@ -180,9 +202,12 @@ public final class TestHSSFPicture extends BaseTestPicture { HSSFShapeGroup gr = dr.createGroup(new HSSFClientAnchor()); gr.createPicture(new HSSFChildAnchor(), idx1); assertEquals(bse.getRef(), 3); + + wb.close(); } - public void testReadExistingImage(){ + @Test + public void readExistingImage(){ HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls"); HSSFSheet sheet = wb.getSheet("picture"); HSSFPatriarch drawing = sheet.getDrawingPatriarch(); @@ -192,7 +217,9 @@ public final class TestHSSFPicture extends BaseTestPicture { assertEquals(picture.getFileName(), "test"); } - public void testSetGetProperties(){ + @SuppressWarnings("resource") + @Test + public void setGetProperties() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet("Pictures"); @@ -214,9 +241,12 @@ public final class TestHSSFPicture extends BaseTestPicture { p1 = (HSSFPicture) dr.getChildren().get(0); assertEquals(p1.getFileName(), "aaa"); + wb.close(); } - public void test49658() throws IOException { + @SuppressWarnings("resource") + @Test + public void bug49658() throws IOException { // test if inserted EscherMetafileBlip will be read again HSSFWorkbook wb = new HSSFWorkbook(); @@ -262,6 +292,7 @@ public final class TestHSSFPicture extends BaseTestPicture { pictureDataOut = wb.getAllPictures().get(2).getData(); assertArrayEquals(wmfNoHeader, pictureDataOut); + wb.close(); } } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java index b19513759d..22247ebdf7 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestPicture.java @@ -17,14 +17,19 @@ package org.apache.poi.ss.usermodel; -import junit.framework.TestCase; +import static org.junit.Assert.assertEquals; + +import java.awt.Dimension; +import java.io.FileOutputStream; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.util.ImageUtils; +import org.apache.poi.util.Units; /** * @author Yegor Kozlov */ -public abstract class BaseTestPicture extends TestCase { +public abstract class BaseTestPicture { private final ITestDataProvider _testDataProvider; @@ -32,26 +37,32 @@ public abstract class BaseTestPicture extends TestCase { _testDataProvider = testDataProvider; } - public void baseTestResize(ClientAnchor referenceAnchor) { - Workbook wb = _testDataProvider.createWorkbook(); - Sheet sh1 = wb.createSheet(); - Drawing p1 = sh1.createDrawingPatriarch(); - CreationHelper factory = wb.getCreationHelper(); - - byte[] pictureData = _testDataProvider.getTestDataFileContent("logoKarmokar4.png"); - int idx1 = wb.addPicture( pictureData, Workbook.PICTURE_TYPE_PNG ); - Picture picture = p1.createPicture(factory.createClientAnchor(), idx1); - picture.resize(); - ClientAnchor anchor1 = picture.getPreferredSize(); - - //assert against what would BiffViewer print if we insert the image in xls and dump the file - assertEquals(referenceAnchor.getCol1(), anchor1.getCol1()); - assertEquals(referenceAnchor.getRow1(), anchor1.getRow1()); - assertEquals(referenceAnchor.getCol2(), anchor1.getCol2()); - assertEquals(referenceAnchor.getRow2(), anchor1.getRow2()); - assertEquals(referenceAnchor.getDx1(), anchor1.getDx1()); - assertEquals(referenceAnchor.getDy1(), anchor1.getDy1()); - assertEquals(referenceAnchor.getDx2(), anchor1.getDx2()); - assertEquals(referenceAnchor.getDy2(), anchor1.getDy2()); + 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()); + assertEquals("the column x-offset differs", inpCA.getDx1(), cmpCA.getDx1(), 1); + 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); + assertEquals("the image width differs", imgDim.getWidth(), inpDim.getWidth()/emuPX, 1); } + } diff --git a/test-data/spreadsheet/resize_compare.xls b/test-data/spreadsheet/resize_compare.xls new file mode 100644 index 0000000000..c41cc4b15d Binary files /dev/null and b/test-data/spreadsheet/resize_compare.xls differ diff --git a/test-data/spreadsheet/resize_compare.xlsx b/test-data/spreadsheet/resize_compare.xlsx new file mode 100644 index 0000000000..7fb4437fe8 Binary files /dev/null and b/test-data/spreadsheet/resize_compare.xlsx differ