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;
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...
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);
}
return spContainer;
}
+ /**
+ * Reset the image to the dimension of the embedded image
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ 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
* <p>
* with default font size (Arial 10pt for .xls).
* If the default font is changed the resized image can be streched vertically or horizontally.
* </p>
+ * <p>
+ * <code>resize(1.0,1.0)</code> keeps the original size,<br/>
+ * <code>resize(0.5,0.5)</code> resize to 50% of the original,<br/>
+ * <code>resize(2.0,2.0)</code> resizes to 200% of the original.<br/>
+ * <code>resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE})</code> resizes to the dimension of the embedded image.
+ * </p>
*
- * @param scale the amount by which image dimensions are multiplied relative to the original size.
- * <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
- * <code>resize(2.0)</code> 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.
- *
- * <p>
- * 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.
- * </p>
- */
- public void resize(){
- resize(1.0);
- }
-
/**
* Calculate the preferred size for this 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);
*/
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);
}
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();
+ }
}
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;
/**
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;
+ }
+ }
}
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
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
==================================================================== */
package org.apache.poi.ss.usermodel;
+import java.awt.Dimension;
+
+
/**
* Repersents a picture in a SpreadsheetML document
*
public interface Picture {
/**
- * Reset the image to the original size.
+ * Reset the image to the dimension of the embedded image
*
- * <p>
- * 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.
- * </p>
+ * @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.
* <p>
* 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.
+ * </p>
+ * <p>
+ * <code>resize(1.0,1.0)</code> keeps the original size,<br/>
+ * <code>resize(0.5,0.5)</code> resize to 50% of the original,<br/>
+ * <code>resize(2.0,2.0)</code> resizes to 200% of the original.<br/>
+ * <code>resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE})</code> resizes to the dimension of the embedded image.
* </p>
*
- * @param scale the amount by which image dimensions are multiplied relative to the original size.
- * <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
- * <code>resize(2.0)</code> 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
*
*/
PictureData getPictureData();
+ /**
+ * @return the anchor that is used by this picture
+ */
+ ClientAnchor getClientAnchor();
+
+
+ /**
+ * @return the sheet which contains the picture
+ */
+ Sheet getSheet();
}
* 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
* using the default font (first font in the workbook)
* </p>
*
- * @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
+ *
+ * <p>
+ * 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
+ * </p>
+ *
+ * @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
* @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.
public DataValidationHelper getDataValidationHelper();
- /**
+ /**
* Returns the list of DataValidation in the sheet.
* @return list of DataValidation in the sheet
*/
==================================================================== */\r
package org.apache.poi.ss.util;\r
\r
-import org.w3c.dom.NodeList;\r
-import org.w3c.dom.Element;\r
-import org.apache.poi.ss.usermodel.Workbook;\r
-import org.apache.poi.util.POILogger;\r
-import org.apache.poi.util.POILogFactory;\r
+import static org.apache.poi.util.Units.EMU_PER_PIXEL;\r
\r
-import javax.imageio.ImageReader;\r
-import javax.imageio.ImageIO;\r
-import javax.imageio.stream.ImageInputStream;\r
+import java.awt.Dimension;\r
+import java.awt.image.BufferedImage;\r
+import java.io.ByteArrayInputStream;\r
import java.io.IOException;\r
import java.io.InputStream;\r
-import java.awt.*;\r
-import java.awt.image.BufferedImage;\r
import java.util.Iterator;\r
\r
+import javax.imageio.ImageIO;\r
+import javax.imageio.ImageReader;\r
+import javax.imageio.stream.ImageInputStream;\r
+\r
+import org.apache.poi.hssf.usermodel.HSSFClientAnchor;\r
+import org.apache.poi.ss.usermodel.ClientAnchor;\r
+import org.apache.poi.ss.usermodel.Picture;\r
+import org.apache.poi.ss.usermodel.PictureData;\r
+import org.apache.poi.ss.usermodel.Row;\r
+import org.apache.poi.ss.usermodel.Sheet;\r
+import org.apache.poi.ss.usermodel.Workbook;\r
+import org.apache.poi.util.POILogFactory;\r
+import org.apache.poi.util.POILogger;\r
+import org.apache.poi.util.Units;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.NodeList;\r
+\r
/**\r
* @author Yegor Kozlov\r
*/\r
try {\r
//read the image using javax.imageio.*\r
ImageInputStream iis = ImageIO.createImageInputStream( is );\r
- Iterator i = ImageIO.getImageReaders( iis );\r
- ImageReader r = (ImageReader) i.next();\r
+ Iterator<ImageReader> i = ImageIO.getImageReaders( iis );\r
+ ImageReader r = i.next();\r
r.setInput( iis );\r
BufferedImage img = r.read(0);\r
\r
return new int[]{hdpi, vdpi};\r
}\r
\r
+ /**\r
+ * Calculate and set the preferred size (anchor) for this picture.\r
+ *\r
+ * @param scaleX the amount by which image width is multiplied relative to the original width.\r
+ * @param scaleY the amount by which image height is multiplied relative to the original height.\r
+ * @return the new Dimensions of the scaled picture in EMUs\r
+ */\r
+ public static Dimension setPreferredSize(Picture picture, double scaleX, double scaleY){\r
+ ClientAnchor anchor = picture.getClientAnchor();\r
+ boolean isHSSF = (anchor instanceof HSSFClientAnchor);\r
+ PictureData data = picture.getPictureData();\r
+ Sheet sheet = picture.getSheet();\r
+ \r
+ // in pixel\r
+ Dimension imgSize = getImageDimension(new ByteArrayInputStream(data.getData()), data.getPictureType());\r
+ // in emus\r
+ Dimension anchorSize = ImageUtils.getDimensionFromAnchor(picture);\r
+ final double scaledWidth = (scaleX == Double.MAX_VALUE)\r
+ ? imgSize.getWidth() : anchorSize.getWidth()/EMU_PER_PIXEL * scaleX;\r
+ final double scaledHeight = (scaleY == Double.MAX_VALUE)\r
+ ? imgSize.getHeight() : anchorSize.getHeight()/EMU_PER_PIXEL * scaleY;\r
+\r
+ double w = 0;\r
+ int col2 = anchor.getCol1();\r
+ int dx2 = 0;\r
+\r
+ //space in the leftmost cell\r
+ w = sheet.getColumnWidthInPixels(col2++);\r
+ if (isHSSF) {\r
+ w *= 1 - anchor.getDx1()/1024d;\r
+ } else {\r
+ w -= anchor.getDx1()/EMU_PER_PIXEL;\r
+ }\r
+ \r
+ while(w < scaledWidth){\r
+ w += sheet.getColumnWidthInPixels(col2++);\r
+ }\r
+ \r
+ if(w > scaledWidth) {\r
+ //calculate dx2, offset in the rightmost cell\r
+ double cw = sheet.getColumnWidthInPixels(--col2);\r
+ double delta = w - scaledWidth;\r
+ if (isHSSF) {\r
+ dx2 = (int)((cw-delta)/cw*1024);\r
+ } else {\r
+ dx2 = (int)((cw-delta)*EMU_PER_PIXEL);\r
+ }\r
+ if (dx2 < 0) dx2 = 0;\r
+ }\r
+ anchor.setCol2(col2);\r
+ anchor.setDx2(dx2);\r
+\r
+ double h = 0;\r
+ int row2 = anchor.getRow1();\r
+ int dy2 = 0;\r
+ \r
+ h = getRowHeightInPixels(sheet,row2++);\r
+ if (isHSSF) {\r
+ h *= 1 - anchor.getDy1()/256d;\r
+ } else {\r
+ h -= anchor.getDy1()/EMU_PER_PIXEL;\r
+ }\r
+\r
+ while(h < scaledHeight){\r
+ h += getRowHeightInPixels(sheet,row2++);\r
+ }\r
+ \r
+ if(h > scaledHeight) {\r
+ double ch = getRowHeightInPixels(sheet,--row2);\r
+ double delta = h - scaledHeight;\r
+ if (isHSSF) {\r
+ dy2 = (int)((ch-delta)/ch*256);\r
+ } else {\r
+ dy2 = (int)((ch-delta)*EMU_PER_PIXEL);\r
+ }\r
+ if (dy2 < 0) dy2 = 0;\r
+ }\r
+\r
+ anchor.setRow2(row2);\r
+ anchor.setDy2(dy2);\r
+\r
+ Dimension dim = new Dimension(\r
+ (int)Math.round(scaledWidth*EMU_PER_PIXEL),\r
+ (int)Math.round(scaledHeight*EMU_PER_PIXEL)\r
+ );\r
+ \r
+ return dim;\r
+ }\r
+\r
+ /**\r
+ * Calculates the dimensions in EMUs for the anchor of the given picture\r
+ *\r
+ * @param picture the picture containing the anchor\r
+ * @return the dimensions in EMUs\r
+ */\r
+ public static Dimension getDimensionFromAnchor(Picture picture) {\r
+ ClientAnchor anchor = picture.getClientAnchor();\r
+ boolean isHSSF = (anchor instanceof HSSFClientAnchor);\r
+ Sheet sheet = picture.getSheet();\r
+\r
+ double w = 0;\r
+ int col2 = anchor.getCol1();\r
+\r
+ //space in the leftmost cell\r
+ w = sheet.getColumnWidthInPixels(col2++);\r
+ if (isHSSF) {\r
+ w *= 1 - anchor.getDx1()/1024d;\r
+ } else {\r
+ w -= anchor.getDx1()/EMU_PER_PIXEL;\r
+ }\r
+ \r
+ while(col2 < anchor.getCol2()){\r
+ w += sheet.getColumnWidthInPixels(col2++);\r
+ }\r
+ \r
+ if (isHSSF) {\r
+ w += sheet.getColumnWidthInPixels(col2) * anchor.getDx2()/1024d;\r
+ } else {\r
+ w += anchor.getDx2()/EMU_PER_PIXEL;\r
+ }\r
+\r
+ double h = 0;\r
+ int row2 = anchor.getRow1();\r
+ \r
+ h = getRowHeightInPixels(sheet,row2++);\r
+ if (isHSSF) {\r
+ h *= 1 - anchor.getDy1()/256d;\r
+ } else {\r
+ h -= anchor.getDy1()/EMU_PER_PIXEL;\r
+ }\r
+\r
+ while(row2 < anchor.getRow2()){\r
+ h += getRowHeightInPixels(sheet,row2++);\r
+ }\r
+ \r
+ if (isHSSF) {\r
+ h += getRowHeightInPixels(sheet,row2) * anchor.getDy2()/256;\r
+ } else {\r
+ h += anchor.getDy2()/EMU_PER_PIXEL;\r
+ }\r
+\r
+ return new Dimension((int)w*EMU_PER_PIXEL, (int)h*EMU_PER_PIXEL);\r
+ }\r
+ \r
+ \r
+ private static double getRowHeightInPixels(Sheet sheet, int rowNum) {\r
+ Row r = sheet.getRow(rowNum);\r
+ double points = (r == null) ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints();\r
+ return Units.toEMU(points)/EMU_PER_PIXEL;\r
+ }\r
}\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.util;\r
+\r
+/**\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Units {\r
+ public static final int EMU_PER_PIXEL = 9525;\r
+ public static final int EMU_PER_POINT = 12700;\r
+\r
+ /**\r
+ * Converts points to EMUs\r
+ * @param points points\r
+ * @return emus\r
+ */\r
+ public static int toEMU(double points){\r
+ return (int)Math.round(EMU_PER_POINT*points);\r
+ }\r
+\r
+ /**\r
+ * Converts EMUs to points\r
+ * @param emu emu\r
+ * @return points\r
+ */\r
+ public static double toPoints(long emu){\r
+ return (double)emu/EMU_PER_POINT;\r
+ }\r
+}\r
+++ /dev/null
-/* ====================================================================\r
- Licensed to the Apache Software Foundation (ASF) under one or more\r
- contributor license agreements. See the NOTICE file distributed with\r
- this work for additional information regarding copyright ownership.\r
- The ASF licenses this file to You under the Apache License, Version 2.0\r
- (the "License"); you may not use this file except in compliance with\r
- the License. You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-==================================================================== */\r
-package org.apache.poi.util;\r
-\r
-/**\r
- * @author Yegor Kozlov\r
- */\r
-public class Units {\r
- public static final int EMU_PER_PIXEL = 9525;\r
- public static final int EMU_PER_POINT = 12700;\r
-\r
- public static int toEMU(double value){\r
- return (int)Math.round(EMU_PER_POINT*value);\r
- }\r
-\r
- public static double toPoints(long emu){\r
- return (double)emu/EMU_PER_POINT;\r
- }\r
-}\r
return _sh.getColumnWidth(columnIndex);
}
+ /**
+ * Get the actual column width in pixels
+ *
+ * <p>
+ * Please note, that this method works correctly only for workbooks
+ * with the default font size (Calibri 11pt for .xlsx).
+ * </p>
+ */
+ @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
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;
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.
*
* 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.
}
/**
- * Reset the image to the original size.
+ * Reset the image to the dimension of the embedded image
*
- * <p>
- * 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.
- * </p>
+ * @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.
* <p>
* 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.
* </p>
+ * <p>
+ * <code>resize(1.0,1.0)</code> keeps the original size,<br/>
+ * <code>resize(0.5,0.5)</code> resize to 50% of the original,<br/>
+ * <code>resize(2.0,2.0)</code> resizes to 200% of the original.<br/>
+ * <code>resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE})</code> resizes to the dimension of the embedded image.
+ * </p>
*
- * @param scale the amount by which image dimensions are multiplied relative to the original size.
- * <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
- * <code>resize(2.0)</code> 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());
}
* @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();
}
/**
}
}
+ /**
+ * 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
*
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();
+ }
}
return (int)(width*256);
}
+ /**
+ * Get the actual column width in pixels
+ *
+ * <p>
+ * Please note, that this method works correctly only for workbooks
+ * with the default font size (Calibri 11pt for .xlsx).
+ * </p>
+ */
+ @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.
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).
*
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;
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<XSSFShape> 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();
CTTwoCellAnchor ctShapeHolder = drawing.getCTDrawing().getTwoCellAnchorArray(0);
// STEditAs.ABSOLUTE corresponds to ClientAnchor.DONT_MOVE_AND_RESIZE
assertEquals(STEditAs.ABSOLUTE, ctShapeHolder.getEditAs());
+
+ wb.close();
}
/**
*
* See Bugzilla 50458
*/
- public void testShapeId(){
+ @Test
+ public void incrementShapeId() throws IOException {
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
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();
XSSFPicture shape44 = (XSSFPicture)drawing2.getShapes().get(1);
assertArrayEquals(shape4.getPictureData().getData(), shape44.getPictureData().getData());
+ wb.close();
}
}
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;
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 <code>HSSFPicture</code>.
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<HSSFShape> 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();
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");
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");
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();
assertEquals(picture.getFileName(), "test");
}
- public void testSetGetProperties(){
+ @SuppressWarnings("resource")
+ @Test
+ public void setGetProperties() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet("Pictures");
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();
pictureDataOut = wb.getAllPictures().get(2).getData();
assertArrayEquals(wmfNoHeader, pictureDataOut);
+ wb.close();
}
}
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;
_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);
}
+
}