2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package org
.apache
.poi
.hssf
.usermodel
;
19 import org
.apache
.poi
.ddf
.EscherBSERecord
;
20 import org
.apache
.poi
.util
.POILogFactory
;
21 import org
.apache
.poi
.util
.POILogger
;
22 import org
.w3c
.dom
.Element
;
23 import org
.w3c
.dom
.NodeList
;
25 import javax
.imageio
.ImageIO
;
26 import javax
.imageio
.ImageReader
;
27 import javax
.imageio
.stream
.ImageInputStream
;
28 import java
.awt
.image
.BufferedImage
;
30 import java
.io
.ByteArrayInputStream
;
31 import java
.io
.IOException
;
32 import java
.util
.Iterator
;
35 * Represents a escher picture. Eg. A GIF, JPEG etc...
37 * @author Glen Stampoultzis
38 * @author Yegor Kozlov (yegor at apache.org)
40 public class HSSFPicture
41 extends HSSFSimpleShape
43 public static final int PICTURE_TYPE_EMF
= HSSFWorkbook
.PICTURE_TYPE_EMF
; // Windows Enhanced Metafile
44 public static final int PICTURE_TYPE_WMF
= HSSFWorkbook
.PICTURE_TYPE_WMF
; // Windows Metafile
45 public static final int PICTURE_TYPE_PICT
= HSSFWorkbook
.PICTURE_TYPE_PICT
; // Macintosh PICT
46 public static final int PICTURE_TYPE_JPEG
= HSSFWorkbook
.PICTURE_TYPE_JPEG
; // JFIF
47 public static final int PICTURE_TYPE_PNG
= HSSFWorkbook
.PICTURE_TYPE_PNG
; // PNG
48 public static final int PICTURE_TYPE_DIB
= HSSFWorkbook
.PICTURE_TYPE_DIB
; // Windows DIB
51 * width of 1px in columns with default width in units of 1/256 of a character width
53 private static final float PX_DEFAULT
= 32.00f
;
55 * width of 1px in columns with overridden width in units of 1/256 of a character width
57 private static final float PX_MODIFIED
= 36.56f
;
60 * Height of 1px of a row
62 private static final int PX_ROW
= 15;
65 HSSFPatriarch patriarch
;
67 private static final POILogger log
= POILogFactory
.getLogger(HSSFPicture
.class);
70 * Constructs a picture object.
72 HSSFPicture( HSSFShape parent
, HSSFAnchor anchor
)
74 super( parent
, anchor
);
75 setShapeType(OBJECT_TYPE_PICTURE
);
78 public int getPictureIndex()
83 public void setPictureIndex( int pictureIndex
)
85 this.pictureIndex
= pictureIndex
;
89 * Reset the image to the original size.
94 HSSFClientAnchor anchor
= (HSSFClientAnchor
)getAnchor();
95 anchor
.setAnchorType(2);
97 HSSFClientAnchor pref
= getPreferredSize();
99 int row2
= anchor
.getRow1() + (pref
.getRow2() - pref
.getRow1());
100 int col2
= anchor
.getCol1() + (pref
.getCol2() - pref
.getCol1());
102 anchor
.setCol2((short)col2
);
104 anchor
.setDx2(pref
.getDx2());
106 anchor
.setRow2(row2
);
108 anchor
.setDy2(pref
.getDy2());
112 * Calculate the preferred size for this picture.
114 * @return HSSFClientAnchor with the preferred size for this image
117 public HSSFClientAnchor
getPreferredSize(){
118 HSSFClientAnchor anchor
= (HSSFClientAnchor
)getAnchor();
120 Dimension size
= getImageDimension();
124 //space in the leftmost cell
125 w
+= getColumnWidthInPixels(anchor
.col1
)*(1 - anchor
.dx1
/1024);
126 short col2
= (short)(anchor
.col1
+ 1);
129 while(w
< size
.width
){
130 w
+= getColumnWidthInPixels(col2
++);
134 //calculate dx2, offset in the rightmost cell
136 float cw
= getColumnWidthInPixels(col2
);
137 float delta
= w
- size
.width
;
138 dx2
= (int)((cw
-delta
)/cw
*1024);
144 h
+= (1 - anchor
.dy1
/256)* getRowHeightInPixels(anchor
.row1
);
145 int row2
= anchor
.row1
+ 1;
148 while(h
< size
.height
){
149 h
+= getRowHeightInPixels(row2
++);
151 if(h
> size
.height
) {
153 float ch
= getRowHeightInPixels(row2
);
154 float delta
= h
- size
.height
;
155 dy2
= (int)((ch
-delta
)/ch
*256);
163 private float getColumnWidthInPixels(short column
){
165 short cw
= patriarch
.sheet
.getColumnWidth(column
);
166 float px
= getPixelWidth(column
);
171 private float getRowHeightInPixels(int i
){
173 HSSFRow row
= patriarch
.sheet
.getRow(i
);
175 if(row
!= null) height
= row
.getHeight();
176 else height
= patriarch
.sheet
.getDefaultRowHeight();
178 return height
/PX_ROW
;
181 private float getPixelWidth(short column
){
183 int def
= patriarch
.sheet
.getDefaultColumnWidth()*256;
184 short cw
= patriarch
.sheet
.getColumnWidth(column
);
186 return cw
== def ? PX_DEFAULT
: PX_MODIFIED
;
190 * The metadata of PNG and JPEG can contain the width of a pixel in millimeters.
191 * Return the the "effective" dpi calculated as <code>25.4/HorizontalPixelSize</code>
192 * and <code>25.4/VerticalPixelSize</code>. Where 25.4 is the number of mm in inch.
194 * @return array of two elements: <code>{horisontalPdi, verticalDpi}</code>.
195 * {96, 96} is the default.
197 protected int[] getResolution(ImageReader r
) throws IOException
{
198 int hdpi
=96, vdpi
=96;
199 double mm2inch
= 25.4;
202 Element node
= (Element
)r
.getImageMetadata(0).getAsTree("javax_imageio_1.0");
203 lst
= node
.getElementsByTagName("HorizontalPixelSize");
204 if(lst
!= null && lst
.getLength() == 1) hdpi
= (int)(mm2inch
/Float
.parseFloat(((Element
)lst
.item(0)).getAttribute("value")));
206 lst
= node
.getElementsByTagName("VerticalPixelSize");
207 if(lst
!= null && lst
.getLength() == 1) vdpi
= (int)(mm2inch
/Float
.parseFloat(((Element
)lst
.item(0)).getAttribute("value")));
209 return new int[]{hdpi
, vdpi
};
213 * Return the dimension of this image
215 * @return image dimension
217 public Dimension
getImageDimension(){
218 EscherBSERecord bse
= patriarch
.sheet
.book
.getBSERecord(pictureIndex
);
219 byte[] data
= bse
.getBlipRecord().getPicturedata();
220 int type
= bse
.getBlipTypeWin32();
221 Dimension size
= new Dimension();
224 //we can calculate the preferred size only for JPEG and PNG
225 //other formats like WMF, EMF and PICT are not supported in Java
226 case HSSFWorkbook
.PICTURE_TYPE_JPEG
:
227 case HSSFWorkbook
.PICTURE_TYPE_PNG
:
228 case HSSFWorkbook
.PICTURE_TYPE_DIB
:
230 //read the image using javax.imageio.*
231 ImageInputStream iis
= ImageIO
.createImageInputStream( new ByteArrayInputStream(data
) );
232 Iterator i
= ImageIO
.getImageReaders( iis
);
233 ImageReader r
= (ImageReader
) i
.next();
235 BufferedImage img
= r
.read(0);
237 int[] dpi
= getResolution(r
);
238 size
.width
= img
.getWidth()*96/dpi
[0];
239 size
.height
= img
.getHeight()*96/dpi
[1];
241 } catch (IOException e
){
242 //silently return if ImageIO failed to read the image
243 log
.log(POILogger
.WARN
, e
);