}\r
\r
// Get the document's embedded files.\r
- List<XSLFPictureData> images = ppt.getAllPictures();\r
+ List<XSLFPictureData> images = ppt.getPictureData();\r
for (XSLFPictureData data : images) {\r
PackagePart p = data.getPackagePart();\r
\r
assertNotNull(slide.getCurrentUserAtom());
assertNotNull(slide.getEmbeddedObjects());
assertNotNull(slide.getUnderlyingBytes());
- assertNotNull(slide.getPictures());
+ assertNotNull(slide.getPictureData());
Record[] records = slide.getRecords();
assertNotNull(records);
for(Record record : records) {
package org.apache.poi.stress;\r
\r
import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertTrue;\r
\r
import java.awt.Dimension;\r
import java.awt.Graphics2D;\r
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
import org.apache.poi.sl.SlideShowFactory;\r
import org.apache.poi.sl.draw.Drawable;\r
+import org.apache.poi.sl.usermodel.PictureData;\r
import org.apache.poi.sl.usermodel.Shape;\r
import org.apache.poi.sl.usermodel.ShapeContainer;\r
import org.apache.poi.sl.usermodel.Slide;\r
renderSlides(ss);\r
\r
readContent(ss);\r
+ readPictures(ss);\r
\r
// write out the file\r
ByteArrayOutputStream out = writeToArray(ss);\r
}\r
}\r
\r
+ private void readPictures(SlideShow<?,?> ss) {\r
+ for (PictureData pd : ss.getPictureData()) {\r
+ Dimension dim = pd.getImageDimension();\r
+ assertTrue(dim.getHeight() >= 0);\r
+ assertTrue(dim.getWidth() >= 0);\r
+ }\r
+ }\r
+ \r
private void renderSlides(SlideShow<?,?> ss) {\r
Dimension pgsize = ss.getPageSize();\r
\r
package org.apache.poi.sl.usermodel;
+import java.awt.Dimension;
import java.io.IOException;
public interface PictureData {
* @param data picture data
*/
void setData(byte[] data) throws IOException;
-}
+
+ /**
+ * Gets the checksum - the checksum can be of various length -
+ * mostly it's 8 (XSLF) or 16 (HSLF) bytes long.
+ * @return the checksum
+ */
+ byte[] getChecksum();
+
+ /**
+ * Return the original image dimensions
+ * (for formats supported by BufferedImage).
+ *
+ * Will return a Dimension with zero width/height if the format unsupported.
+ */
+ Dimension getImageDimension();
+}
\ No newline at end of file
*/
Dimension getPageSize();
+ /**
+ * Returns all Pictures of this slideshow.
+ * The returned {@link List} is unmodifiable.
+ * @return a {@link List} of {@link PictureData}.
+ */
+ List<? extends PictureData> getPictureData();
+
/**
* Adds a picture to the workbook.
*
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.apache.poi.util.Beta;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.PackageHelper;
static final OPCPackage empty() {
InputStream is = XMLSlideShow.class.getResourceAsStream("empty.pptx");
if (is == null) {
- throw new RuntimeException("Missing resource 'empty.pptx'");
+ throw new POIXMLException("Missing resource 'empty.pptx'");
}
try {
return OPCPackage.open(is);
} catch (Exception e){
throw new POIXMLException(e);
+ } finally {
+ try {
+ is.close();
+ } catch (Exception e) {
+ throw new POIXMLException(e);
+ }
}
}
);
}
- /**
- * Returns all Pictures, which are referenced from the document itself.
- * @return a {@link List} of {@link PackagePart}.
- * The returned {@link List} is unmodifiable.
- */
- public List<XSLFPictureData> getAllPictures() {
+ @Override
+ public List<XSLFPictureData> getPictureData() {
if(_pictures == null){
List<PackagePart> mediaParts = getPackage().getPartsByName(Pattern.compile("/ppt/media/.*?"));
_pictures = new ArrayList<XSLFPictureData>(mediaParts.size());
*/
XSLFPictureData findPictureData(byte[] pictureData){
long checksum = IOUtils.calculateChecksum(pictureData);
- for(XSLFPictureData pic : getAllPictures()){
- if(pic.getChecksum() == checksum) {
+ byte cs[] = new byte[LittleEndianConsts.LONG_SIZE];
+ LittleEndian.putLong(cs,0,checksum);
+
+ for(XSLFPictureData pic : getPictureData()){
+ if(Arrays.equals(pic.getChecksum(), cs)) {
return pic;
}
}
package org.apache.poi.xslf.usermodel;
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import javax.imageio.ImageIO;
+
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
+import org.apache.poi.hslf.blip.EMF;
+import org.apache.poi.hslf.blip.PICT;
+import org.apache.poi.hslf.blip.WMF;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.Beta;
import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
/**
* Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type
*/
@Beta
public final class XSLFPictureData extends POIXMLDocumentPart implements PictureData {
+ private static final POILogger logger = POILogFactory.getLogger(XSLFPictureData.class);
+
private Long checksum = null;
+
+ // original image dimensions (for formats supported by BufferedImage)
+ private Dimension _origSize = null;
private int index = -1;
/**
return getPackagePart().getPartName().getExtension();
}
- long getChecksum(){
- if(checksum == null){
- try {
- checksum = IOUtils.calculateChecksum(getInputStream());
- } catch (IOException e) {
- throw new POIXMLException("Unable to calulate checksum", e);
+ @Override
+ public byte[] getChecksum() {
+ cacheProperties();
+ byte cs[] = new byte[LittleEndianConsts.LONG_SIZE];
+ LittleEndian.putLong(cs,0,checksum);
+ return cs;
+ }
+
+ @Override
+ public Dimension getImageDimension() {
+ cacheProperties();
+ return _origSize;
+ }
+
+ /**
+ * Determine and cache image properties
+ */
+ protected void cacheProperties() {
+ if (_origSize == null || checksum == null) {
+ byte data[] = getData();
+ checksum = IOUtils.calculateChecksum(data);
+
+ switch (getType()) {
+ case EMF:
+ _origSize = new EMF.NativeHeader(data, 0).getSize();
+ break;
+ case WMF:
+ // wmf files in pptx usually have their placeable header
+ // stripped away, so this returns only the dummy size
+ _origSize = new WMF.NativeHeader(data, 0).getSize();
+ break;
+ case PICT:
+ _origSize = new PICT.NativeHeader(data, 0).getSize();
+ break;
+ default:
+ try {
+ BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
+ _origSize = (img == null) ? new Dimension() : new Dimension(img.getWidth(), img.getHeight());
+ } catch (IOException e) {
+ logger.log(POILogger.WARN, "Can't determine image dimensions", e);
+ // failed to get information, set dummy size
+ _origSize = new Dimension(200,200);
+ }
+ break;
}
}
- return checksum;
}
/**
os.close();
// recalculate now since we already have the data bytes available anyhow
checksum = IOUtils.calculateChecksum(data);
+
+ _origSize = null; // need to recalculate image size
}
@Override
\r
package org.apache.poi.xslf.usermodel;\r
\r
+import java.awt.Dimension;\r
import java.awt.Insets;\r
-import java.awt.geom.Rectangle2D;\r
-import java.awt.image.BufferedImage;\r
+import java.awt.Rectangle;\r
import java.net.URI;\r
-\r
-import javax.imageio.ImageIO;\r
import javax.xml.namespace.QName;\r
\r
import org.apache.poi.POIXMLException;\r
\r
/**\r
* Resize this picture to the default size.\r
+ *\r
* For PNG and JPEG resizes the image to 100%,\r
- * for other types sets the default size of 200x200 pixels.\r
+ * for other types sets the default size to 200x200 pixels.\r
*/\r
public void resize() {\r
- try {\r
- BufferedImage img = ImageIO.read(getPictureData().getInputStream());\r
- setAnchor(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));\r
+ Dimension dim = getPictureData().getImageDimension();\r
+ if (dim.width > 0 && dim.height > 0)\r
+ {\r
+ setAnchor(new Rectangle(0, 0, dim.width, dim.height));\r
}\r
- catch (Exception e) {\r
- //default size is 200x200\r
- setAnchor(new java.awt.Rectangle(50, 50, 200, 200));\r
+ else\r
+ {\r
+ // unsupported/unknown formats\r
+ setAnchor(new Rectangle(50, 50, 200, 200));\r
}\r
}\r
- \r
+\r
/**\r
* Is this an internal picture (image data included within\r
* the PowerPoint file), or an external linked picture\r
@Test
@SuppressWarnings("deprecation")
public void bug51187() throws Exception {
- XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("51187.pptx");
+ XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("51187.pptx");
- assertEquals(1, ss.getSlides().size());
+ assertEquals(1, ss1.getSlides().size());
// Check the relations on it
// Note - rId3 is a self reference
- PackagePart slidePart = ss._getXSLFSlideShow().getSlidePart(
- ss._getXSLFSlideShow().getSlideReferences().getSldIdArray(0)
+ PackagePart slidePart = ss1._getXSLFSlideShow().getSlidePart(
+ ss1._getXSLFSlideShow().getSlideReferences().getSldIdArray(0)
);
assertEquals("/ppt/slides/slide1.xml", slidePart.getPartName().toString());
assertEquals("/ppt/slideLayouts/slideLayout12.xml", slidePart.getRelationship("rId1").getTargetURI().toString());
assertEquals("/ppt/media/image1.png", slidePart.getRelationship("rId4").getTargetURI().toString());
// Save and re-load
- ss = XSLFTestDataSamples.writeOutAndReadBack(ss);
- assertEquals(1, ss.getSlides().size());
+ XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss1);
+ ss1.close();
+ assertEquals(1, ss2.getSlides().size());
- slidePart = ss._getXSLFSlideShow().getSlidePart(
- ss._getXSLFSlideShow().getSlideReferences().getSldIdArray(0)
+ slidePart = ss2._getXSLFSlideShow().getSlidePart(
+ ss2._getXSLFSlideShow().getSlideReferences().getSldIdArray(0)
);
assertEquals("/ppt/slides/slide1.xml", slidePart.getPartName().toString());
assertEquals("/ppt/slideLayouts/slideLayout12.xml", slidePart.getRelationship("rId1").getTargetURI().toString());
// TODO Fix this
assertEquals("/ppt/slides/slide1.xml", slidePart.getRelationship("rId3").getTargetURI().toString());
assertEquals("/ppt/media/image1.png", slidePart.getRelationship("rId4").getTargetURI().toString());
+
+ ss2.close();
}
/**
* Slide relations with anchors in them
*/
@Test
- public void tika705() {
+ public void tika705() throws Exception {
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx");
// Should have one slide
}
}
}
+ ss.close();
}
/**
slide = ss.getSlides().get(3);
assertContains("POI can read this", getSlideText(slide));
+
+ ss.close();
}
/**
assertEquals(2, internalPictures);
assertEquals(1, externalPictures);
+ ppt.close();
}
@Test
slide.draw(graphics);
ImageIO.write(imgActual, "PNG", new File("bug54542.png"));
+ ss.close();
}
protected String getSlideText(XSLFSlide slide) {
ss.setSlideOrder(slide, 0);
ss.setSlideOrder(slide, 2);
validateSlides(ss, true, "Slide1","Slide2","New slide");
+ ss.close();
}
/**
// Slide starts with just layout relation
XSLFSlide slide = ss.getSlides().get(0);
- assertEquals(0, ss.getAllPictures().size());
+ assertEquals(0, ss.getPictureData().size());
assertEquals(1, slide.getShapes().size());
assertEquals(1, slide.getRelations().size());
for (int i=0; i<10; i++) {
XSLFPictureData data = ss.addPicture(pics[i], PictureType.JPEG);
assertEquals(i, data.getIndex());
- assertEquals(i+1, ss.getAllPictures().size());
+ assertEquals(i+1, ss.getPictureData().size());
XSLFPictureShape shape = slide.createPicture(data);
assertNotNull(shape.getPictureData());
for (int i=10; i<15; i++) {
XSLFPictureData data = ss.addPicture(pics[i], PictureType.JPEG);
assertEquals(i, data.getIndex());
- assertEquals(i+1, ss.getAllPictures().size());
+ assertEquals(i+1, ss.getPictureData().size());
XSLFPictureShape shape = slide.createPicture(data);
assertNotNull(shape.getPictureData());
// Add a duplicate, check the right one is picked
XSLFPictureData data = ss.addPicture(pics[3], PictureType.JPEG);
assertEquals(3, data.getIndex());
- assertEquals(15, ss.getAllPictures().size());
+ assertEquals(15, ss.getPictureData().size());
XSLFPictureShape shape = slide.createPicture(data);
assertNotNull(shape.getPictureData());
// Add another duplicate
data = ss2.addPicture(pics[5], PictureType.JPEG);
assertEquals(5, data.getIndex());
- assertEquals(15, ss2.getAllPictures().size());
+ assertEquals(15, ss2.getPictureData().size());
shape = slide.createPicture(data);
assertNotNull(shape.getPictureData());
ss.close();
}
- private void validateSlides(XMLSlideShow ss, boolean saveAndReload, String... slideTexts) {
+ private void validateSlides(XMLSlideShow ss, boolean saveAndReload, String... slideTexts) throws IOException {
if (saveAndReload) {
- ss = XSLFTestDataSamples.writeOutAndReadBack(ss);
+ XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss);
+ validateSlides(ss, slideTexts);
+ ss2.close();
+ } else {
+ validateSlides(ss, slideTexts);
}
-
+ }
+
+ private void validateSlides(XMLSlideShow ss, String... slideTexts) throws IOException {
assertEquals(slideTexts.length, ss.getSlides().size());
for (int i = 0; i < slideTexts.length; i++) {
assertContains(getSlideText(slide), slideTexts[i]);
}
}
+
private void assertRelationEquals(XSLFRelation expected, POIXMLDocumentPart relation) {
assertEquals(expected.getContentType(), relation.getPackagePart().getContentType());
assertEquals(expected.getFileName(expected.getFileNameIndex(relation)), relation.getPackagePart().getPartName().getName());
public class TestXSLFPictureShape {\r
\r
@Test\r
- public void testCreate() {\r
- XMLSlideShow ppt = new XMLSlideShow();\r
- assertEquals(0, ppt.getAllPictures().size());\r
+ public void testCreate() throws Exception {\r
+ XMLSlideShow ppt1 = new XMLSlideShow();\r
+ assertEquals(0, ppt1.getPictureData().size());\r
byte[] data1 = new byte[100];\r
for(int i = 0;i < 100;i++) { data1[i] = (byte)i; }\r
- XSLFPictureData pdata1 = ppt.addPicture(data1, PictureType.JPEG);\r
+ XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG);\r
assertEquals(0, pdata1.getIndex());\r
- assertEquals(1, ppt.getAllPictures().size());\r
+ assertEquals(1, ppt1.getPictureData().size());\r
\r
- XSLFSlide slide = ppt.createSlide();\r
+ XSLFSlide slide = ppt1.createSlide();\r
XSLFPictureShape shape1 = slide.createPicture(pdata1);\r
assertNotNull(shape1.getPictureData());\r
assertArrayEquals(data1, shape1.getPictureData().getData());\r
\r
byte[] data2 = new byte[200];\r
for(int i = 0;i < 200;i++) { data2[i] = (byte)i; }\r
- XSLFPictureData pdata2 = ppt.addPicture(data2, PictureType.PNG);\r
+ XSLFPictureData pdata2 = ppt1.addPicture(data2, PictureType.PNG);\r
XSLFPictureShape shape2 = slide.createPicture(pdata2);\r
assertNotNull(shape2.getPictureData());\r
assertEquals(1, pdata2.getIndex());\r
- assertEquals(2, ppt.getAllPictures().size());\r
+ assertEquals(2, ppt1.getPictureData().size());\r
assertArrayEquals(data2, shape2.getPictureData().getData());\r
\r
- ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
- List<XSLFPictureData> pics = ppt.getAllPictures();\r
+ XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);\r
+ ppt1.close();\r
+ List<XSLFPictureData> pics = ppt2.getPictureData();\r
assertEquals(2, pics.size());\r
assertArrayEquals(data1, pics.get(0).getData());\r
assertArrayEquals(data2, pics.get(1).getData());\r
\r
- List<XSLFShape> shapes = ppt.getSlides().get(0).getShapes();\r
+ List<XSLFShape> shapes = ppt2.getSlides().get(0).getShapes();\r
assertArrayEquals(data1, ((XSLFPictureShape) shapes.get(0)).getPictureData().getData());\r
assertArrayEquals(data2, ((XSLFPictureShape) shapes.get(1)).getPictureData().getData());\r
+ ppt2.close();\r
}\r
\r
@Test\r
- public void testCreateMultiplePictures() {\r
- XMLSlideShow ppt = new XMLSlideShow();\r
- XSLFSlide slide1 = ppt.createSlide();\r
+ public void testCreateMultiplePictures() throws Exception {\r
+ XMLSlideShow ppt1 = new XMLSlideShow();\r
+ XSLFSlide slide1 = ppt1.createSlide();\r
XSLFGroupShape group1 = slide1.createGroup();\r
\r
\r
// first add 20 images to the slide\r
for (int i = 0; i < 20; i++, pictureIndex++) {\r
byte[] data = new byte[]{(byte)pictureIndex};\r
- XSLFPictureData elementData = ppt.addPicture(data, PictureType.PNG);\r
+ XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG);\r
assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19\r
XSLFPictureShape picture = slide1.createPicture(elementData);\r
// POI saves images as image1.png, image2.png, etc.\r
// and then add next 20 images to a group\r
for (int i = 0; i < 20; i++, pictureIndex++) {\r
byte[] data = new byte[]{(byte)pictureIndex};\r
- XSLFPictureData elementData = ppt.addPicture(data, PictureType.PNG);\r
+ XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG);\r
XSLFPictureShape picture = group1.createPicture(elementData);\r
// POI saves images as image1.png, image2.png, etc.\r
assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19\r
\r
// serialize, read back and check that all images are there\r
\r
- ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
+ XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);\r
+ ppt1.close();\r
// pictures keyed by file name\r
Map<String, XSLFPictureData> pics = new HashMap<String, XSLFPictureData>();\r
- for(XSLFPictureData p : ppt.getAllPictures()){\r
+ for(XSLFPictureData p : ppt2.getPictureData()){\r
pics.put(p.getFileName(), p);\r
}\r
assertEquals(40, pics.size());\r
assertEquals(fileName, data.getFileName());\r
assertArrayEquals(data1, data.getData());\r
}\r
+ ppt2.close();\r
}\r
\r
@Test\r
- public void testImageCaching() {\r
+ public void testImageCaching() throws Exception {\r
XMLSlideShow ppt = new XMLSlideShow();\r
byte[] img1 = new byte[]{1,2,3};\r
byte[] img2 = new byte[]{3,4,5};\r
XSLFSlide slide2 = ppt.createSlide();\r
assertNotNull(slide2);\r
\r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testMerge() {\r
+ public void testMerge() throws Exception {\r
XMLSlideShow ppt1 = new XMLSlideShow();\r
byte[] data1 = new byte[100];\r
XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG);\r
XSLFPictureShape shape1 = slide1.createPicture(pdata1);\r
CTPicture ctPic1 = (CTPicture)shape1.getXmlObject();\r
ctPic1.getNvPicPr().getNvPr().addNewCustDataLst().addNewTags().setId("rId99");\r
-\r
+ \r
XMLSlideShow ppt2 = new XMLSlideShow();\r
\r
XSLFSlide slide2 = ppt2.createSlide().importContent(slide1);\r
CTPicture ctPic2 = (CTPicture)shape2.getXmlObject();\r
assertFalse(ctPic2.getNvPicPr().getNvPr().isSetCustDataLst());\r
\r
+ ppt1.close();\r
+ ppt2.close();\r
}\r
}
\ No newline at end of file
package org.apache.poi.hslf.blip;
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-
-import java.io.IOException;
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
/**
* Represents a bitmap picture data: JPEG or PNG.
setRawData(out.toByteArray());
}
+
+ public Dimension getImageDimension() {
+ try {
+ BufferedImage bi = ImageIO.read(new ByteArrayInputStream(getData()));
+ return new Dimension(bi.getWidth(), bi.getHeight());
+ } catch (IOException e) {
+ return new Dimension(200,200);
+ }
+ }
}
package org.apache.poi.hslf.blip;
+import java.awt.Dimension;
+import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.InflaterInputStream;
import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.Units;
/**
*/
public final class EMF extends Metafile {
+ public static class NativeHeader {
+ // rectangular inclusive-inclusive bounds, in device units, of the smallest
+ // rectangle that can be drawn around the image stored in the metafile.
+ private final Rectangle deviceBounds;
+
+ private final static String EMF_SIGNATURE = " EMF"; // 0x464D4520 (LE)
+
+ public NativeHeader(byte data[], int offset) {
+ int type = (int)LittleEndian.getUInt(data, offset); offset += 4;
+ if (type != 1) {
+ throw new HSLFException("Invalid EMF picture");
+ }
+ // ignore header size
+ offset += 4;
+ int left = LittleEndian.getInt(data, offset); offset += 4;
+ int top = LittleEndian.getInt(data, offset); offset += 4;
+ int right = LittleEndian.getInt(data, offset); offset += 4;
+ int bottom = LittleEndian.getInt(data, offset); offset += 4;
+ deviceBounds = new Rectangle(left, top, right-left, bottom-top);
+ // ignore frame bounds
+ offset += 16;
+ String signature = new String(data, offset, EMF_SIGNATURE.length(), LocaleUtil.CHARSET_1252);
+ if (!EMF_SIGNATURE.equals(signature)) {
+ throw new HSLFException("Invalid EMF picture");
+ }
+ }
+
+ public Dimension getSize() {
+ return deviceBounds.getSize();
+ }
+ }
+
@Override
public byte[] getData(){
try {
public void setData(byte[] data) throws IOException {
byte[] compressed = compress(data, 0, data.length);
+ NativeHeader nHeader = new NativeHeader(data, 0);
+
Header header = new Header();
header.wmfsize = data.length;
- //we don't have a EMF reader in java, have to set default image size 200x200
- header.bounds = new java.awt.Rectangle(0, 0, 200, 200);
- header.size = new java.awt.Dimension(header.bounds.width*Units.EMU_PER_POINT, header.bounds.height*Units.EMU_PER_POINT);
+ header.bounds = nHeader.deviceBounds;
+ Dimension nDim = nHeader.getSize();
+ header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
header.zipsize = compressed.length;
byte[] checksum = getChecksum(data);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(checksum);
+ if (uidInstanceCount == 2) {
+ out.write(checksum);
+ }
header.write(out);
out.write(compressed);
package org.apache.poi.hslf.blip;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-
-import java.awt.*;
-import java.io.*;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream;
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.Units;
+
/**
* Represents a metafile picture which can be one of the following types: EMF, WMF, or PICT.
* A metafile is stored compressed using the ZIP deflate/inflate algorithm.
}
}
- protected byte[] compress(byte[] bytes, int offset, int length) throws IOException {
+ protected static byte[] compress(byte[] bytes, int offset, int length) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
DeflaterOutputStream deflater = new DeflaterOutputStream( out );
deflater.write(bytes, offset, length);
deflater.close();
return out.toByteArray();
}
+
+
+ public Dimension getImageDimension() {
+ int prefixLen = 16*uidInstanceCount;
+ Header header = new Header();
+ header.read(getRawData(), prefixLen);
+ return new Dimension(
+ (int)Math.round(Units.toPoints((long)header.size.getWidth())),
+ (int)Math.round(Units.toPoints((long)header.size.getHeight()))
+ );
+ }
}
package org.apache.poi.hslf.blip;
+import java.awt.Dimension;
+import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
* Represents Macintosh PICT picture data.
*/
public final class PICT extends Metafile {
+ public static class NativeHeader {
+ /**
+ * skip the first 512 bytes - they are MAC specific crap
+ */
+ public static final int PICT_HEADER_OFFSET = 512;
+
+ public static final double DEFAULT_RESOLUTION = Units.POINT_DPI;
+
+ private static final byte V2_HEADER[] = {
+ 0x00, 0x11, // v2 version opcode
+ 0x02, (byte)0xFF, // version number of new picture
+ 0x0C, 0x00, // header opcode
+ (byte)0xFF, (byte)0xFE, 0x00, 0x00 // pic size dummy
+ };
+
+ public final Rectangle bounds;
+ public final double hRes, vRes;
+
+ public NativeHeader(byte data[], int offset) {
+ // http://mirrors.apple2.org.za/apple.cabi.net/Graphics/PICT.and_QT.INFO/PICT.file.format.TI.txt
+
+ // low order 16 bits of picture size - can be ignored
+ offset += 2;
+ // rectangular bounding box of picture, at 72 dpi
+ // rect : 8 bytes (top, left, bottom, right: integer)
+ int y1 = readUnsignedShort(data, offset); offset += 2;
+ int x1 = readUnsignedShort(data, offset); offset += 2;
+ int y2 = readUnsignedShort(data, offset); offset += 2;
+ int x2 = readUnsignedShort(data, offset); offset += 2;
+
+ // check for version 2 ... otherwise we don't read any further
+ boolean isV2 = true;
+ for (byte b : V2_HEADER) {
+ if (b != data[offset++]) {
+ isV2 = false;
+ break;
+ }
+ }
+
+ if (isV2) {
+ // 4 bytes - fixed, horizontal resolution (dpi) of source data
+ hRes = readFixedPoint(data, offset); offset += 4;
+ // 4 bytes - fixed, vertical resolution (dpi) of source data
+ vRes = readFixedPoint(data, offset); offset += 4;
+ } else {
+ hRes = DEFAULT_RESOLUTION;
+ vRes = DEFAULT_RESOLUTION;
+ }
+
+ bounds = new Rectangle(x1,y1,x2-x1,y2-y1);
+ }
+
+ public Dimension getSize() {
+ int height = (int)Math.round(bounds.height*DEFAULT_RESOLUTION/vRes);
+ int width = (int)Math.round(bounds.width*DEFAULT_RESOLUTION/hRes);
+ return new Dimension(width, height);
+ }
+
+ private static int readUnsignedShort(byte data[], int offset) {
+ int b0 = data[offset] & 0xFF;
+ int b1 = data[offset+1] & 0xFF;
+ return b0 << 8 | b1;
+ }
+ private static double readFixedPoint(byte data[], int offset) {
+ int b0 = data[offset] & 0xFF;
+ int b1 = data[offset+1] & 0xFF;
+ int b2 = data[offset+2] & 0xFF;
+ int b3 = data[offset+3] & 0xFF;
+ int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+ return i / (double)0x10000;
+ }
+ }
+
@Override
public byte[] getData(){
byte[] rawdata = getRawData();
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(macheader);
int pos = CHECKSUM_SIZE*uidInstanceCount;
- byte[] pict;
- try {
- pict = read(rawdata, pos);
- } catch (IOException e){
- //weird MAC behaviour.
- //if failed to read right after the checksum - skip 16 bytes and try again
- pict = read(rawdata, pos + 16);
- }
+ byte[] pict = read(rawdata, pos);
out.write(pict);
return out.toByteArray();
} catch (IOException e){
@Override
public void setData(byte[] data) throws IOException {
- int pos = 512; //skip the first 512 bytes - they are MAC specific crap
- byte[] compressed = compress(data, pos, data.length-pos);
-
+ // skip the first 512 bytes - they are MAC specific crap
+ final int nOffset = NativeHeader.PICT_HEADER_OFFSET;
+ NativeHeader nHeader = new NativeHeader(data, nOffset);
+
Header header = new Header();
- header.wmfsize = data.length - 512;
- //we don't have a PICT reader in java, have to set default image size 200x200
- header.bounds = new java.awt.Rectangle(0, 0, 200, 200);
- header.size = new java.awt.Dimension(header.bounds.width*Units.EMU_PER_POINT,
- header.bounds.height*Units.EMU_PER_POINT);
+ header.wmfsize = data.length - nOffset;
+ byte[] compressed = compress(data, nOffset, header.wmfsize);
header.zipsize = compressed.length;
+ header.bounds = nHeader.bounds;
+ Dimension nDim = nHeader.getSize();
+ header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
byte[] checksum = getChecksum(data);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(checksum);
-
- out.write(new byte[16]); //16-byte prefix which is safe to ignore
+ if (uidInstanceCount == 2) {
+ out.write(checksum);
+ }
header.write(out);
out.write(compressed);
package org.apache.poi.hslf.blip;
+import java.awt.Dimension;
+import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
header.read(rawdata, CHECKSUM_SIZE*uidInstanceCount);
is.skip(header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
- AldusHeader aldus = new AldusHeader();
- aldus.left = header.bounds.x;
- aldus.top = header.bounds.y;
- aldus.right = header.bounds.x + header.bounds.width;
- aldus.bottom = header.bounds.y + header.bounds.height;
+ NativeHeader aldus = new NativeHeader(header.bounds);
aldus.write(out);
InflaterInputStream inflater = new InflaterInputStream( is );
@Override
public void setData(byte[] data) throws IOException {
int pos = 0;
- AldusHeader aldus = new AldusHeader();
- aldus.read(data, pos);
- pos += aldus.getSize();
+ NativeHeader nHeader = new NativeHeader(data, pos);
+ pos += nHeader.getLength();
byte[] compressed = compress(data, pos, data.length-pos);
Header header = new Header();
- header.wmfsize = data.length - aldus.getSize();
- header.bounds = new java.awt.Rectangle((short)aldus.left, (short)aldus.top, (short)aldus.right-(short)aldus.left, (short)aldus.bottom-(short)aldus.top);
- //coefficient to translate from WMF dpi to 96pdi
- int coeff = 96*Units.EMU_PER_POINT/aldus.inch;
- header.size = new java.awt.Dimension(header.bounds.width*coeff, header.bounds.height*coeff);
+ header.wmfsize = data.length - nHeader.getLength();
+ header.bounds = new Rectangle((short)nHeader.left, (short)nHeader.top, (short)nHeader.right-(short)nHeader.left, (short)nHeader.bottom-(short)nHeader.top);
+ Dimension nDim = nHeader.getSize();
+ header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
header.zipsize = compressed.length;
byte[] checksum = getChecksum(data);
* <li>short Checksum; Checksum value for previous 10 shorts
* </ul>
*/
- public class AldusHeader{
+ @SuppressWarnings("unused")
+ public static class NativeHeader {
public static final int APMHEADER_KEY = 0x9AC6CDD7;
+ private static POILogger logger = POILogFactory.getLogger(NativeHeader.class);
- public int handle;
- public int left, top, right, bottom;
- public int inch = 72; //default resolution is 72 dpi
- public int reserved;
- public int checksum;
+ private final int handle;
+ private final int left, top, right, bottom;
- public void read(byte[] data, int offset){
- int pos = offset;
+ /**
+ * The number of logical units per inch used to represent the image.
+ * This value can be used to scale an image. By convention, an image is
+ * considered to be recorded at 1440 logical units (twips) per inch.
+ * Thus, a value of 720 specifies that the image SHOULD be rendered at
+ * twice its normal size, and a value of 2880 specifies that the image
+ * SHOULD be rendered at half its normal size.
+ */
+ private final int inch;
+ private final int reserved;
+ private int checksum;
+
+ public NativeHeader(Rectangle dim) {
+ handle = 0;
+ left = dim.x;
+ top = dim.y;
+ right = dim.x + dim.width;
+ bottom = dim.y + dim.height;
+ inch = Units.POINT_DPI; //default resolution is 72 dpi
+ reserved = 0;
+ }
+
+ public NativeHeader(byte[] data, int pos) {
int key = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE; //header key
- if (key != APMHEADER_KEY) throw new HSLFException("Not a valid WMF file");
+ if (key != APMHEADER_KEY) {
+ logger.log(POILogger.WARN, "WMF file doesn't contain a placeable header - ignore parsing");
+ handle = 0;
+ left = 0;
+ top = 0;
+ right = 200;
+ bottom = 200;
+ inch = Units.POINT_DPI; //default resolution is 72 dpi
+ reserved = 0;
+ return;
+ }
handle = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
- left = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
- top = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
- right = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
- bottom = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
+ left = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
+ top = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
+ right = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
+ bottom = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
inch = LittleEndian.getUShort(data, pos); pos += LittleEndian.SHORT_SIZE;
reserved = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE;
* The checksum is calculated by XORing each short value to an initial value of 0:
*/
public int getChecksum(){
- int checksum = 0;
- checksum ^= (APMHEADER_KEY & 0x0000FFFF);
- checksum ^= ((APMHEADER_KEY & 0xFFFF0000) >> 16);
- checksum ^= left;
- checksum ^= top;
- checksum ^= right;
- checksum ^= bottom;
- checksum ^= inch;
- return checksum;
+ int cs = 0;
+ cs ^= (APMHEADER_KEY & 0x0000FFFF);
+ cs ^= ((APMHEADER_KEY & 0xFFFF0000) >> 16);
+ cs ^= left;
+ cs ^= top;
+ cs ^= right;
+ cs ^= bottom;
+ cs ^= inch;
+ return cs;
}
public void write(OutputStream out) throws IOException {
out.write(header);
}
- public int getSize(){
+ public Dimension getSize() {
+ //coefficient to translate from WMF dpi to 72dpi
+ double coeff = ((double)Units.POINT_DPI)/inch;
+ return new Dimension((int)Math.round((right-left)*coeff), (int)Math.round((bottom-top)*coeff));
+ }
+
+ public int getLength(){
return 22;
}
}
package org.apache.poi.hslf.extractor;
-import org.apache.poi.hslf.usermodel.*;
-import org.apache.poi.sl.usermodel.PictureData.PictureType;
-
-import java.io.IOException;
import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
+import org.apache.poi.sl.usermodel.PictureData.PictureType;
/**
* Utility to extract pictures from a PowerPoint file.
HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl(args[0]));
//extract all pictures contained in the presentation
- HSLFPictureData[] pdata = ppt.getPictureData();
- for (int i = 0; i < pdata.length; i++) {
- HSLFPictureData pict = pdata[i];
+ List<HSLFPictureData> pdata = ppt.getPictureData();
+ for (int i = 0; i < pdata.size(); i++) {
+ HSLFPictureData pict = pdata.get(i);
// picture data
byte[] data = pict.getData();
if (p == null) return null;
HSLFSlideShow ppt = shape.getSheet().getSlideShow();
- HSLFPictureData[] pict = ppt.getPictureData();
+ List<HSLFPictureData> pict = ppt.getPictureData();
Document doc = ppt.getDocumentRecord();
EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
logger.log(POILogger.WARN, "no reference to picture data found ");
} else {
EscherBSERecord bse = (EscherBSERecord)lst.get(idx - 1);
- for ( int i = 0; i < pict.length; i++ ) {
- if (pict[i].getOffset() == bse.getOffset()){
- return pict[i];
+ for (HSLFPictureData pd : pict) {
+ if (pd.getOffset() == bse.getOffset()){
+ return pd;
}
}
}
*/
public abstract class HSLFPictureData implements PictureData {
- protected POILogger logger = POILogFactory.getLogger(this.getClass());
-
/**
* Size of the image checksum calculated using MD5 algorithm.
*/
return uid;
}
-
+ @Override
+ public byte[] getChecksum() {
+ return getChecksum(getData());
+ }
+
/**
* Compute 16-byte checksum of this picture using MD5 algorithm.
*/
LittleEndian.putUShort(data, 0, pt.nativeId + 0xF018);
out.write(data);
- byte[] rawdata = getRawData();
+ byte[] rd = getRawData();
data = new byte[LittleEndian.INT_SIZE];
- LittleEndian.putInt(data, 0, rawdata.length);
+ LittleEndian.putInt(data, 0, rd.length);
out.write(data);
- out.write(rawdata);
+ out.write(rd);
}
/**
package org.apache.poi.hslf.usermodel;
+import java.awt.Dimension;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.util.List;
-import javax.imageio.ImageIO;
-
import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherComplexProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
-import org.apache.poi.hslf.blip.Bitmap;
import org.apache.poi.hslf.record.Document;
import org.apache.poi.sl.usermodel.PictureShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
/**
* Resize this picture to the default size.
* For PNG and JPEG resizes the image to 100%,
- * for other types sets the default size of 200x200 pixels.
+ * for other types, if the size can't be determined it will be 200x200 pixels.
*/
public void setDefaultSize(){
- HSLFPictureData pict = getPictureData();
- if (pict instanceof Bitmap){
- BufferedImage img = null;
- try {
- img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
- }
- catch (IOException e){}
- catch (NegativeArraySizeException ne) {}
-
- if(img != null) {
- // Valid image, set anchor from it
- setAnchor(new Rectangle2D.Double(0, 0, Units.pixelToPoints(img.getWidth()), Units.pixelToPoints(img.getHeight())));
- } else {
- // Invalid image, go with the default metafile size
- setAnchor(new Rectangle2D.Double(0, 0, 200, 200));
- }
- } else {
- //default size of a metafile picture is 200x200
- setAnchor(new Rectangle2D.Double(50, 50, 200, 200));
- }
+ Dimension dim = getPictureData().getImageDimension();
+ Rectangle2D origRect = getAnchor2D();
+ double x = origRect.getX();
+ double y = origRect.getY();
+ double w = Units.pixelToPoints((int)dim.getWidth());
+ double h = Units.pixelToPoints((int)dim.getHeight());
+ setAnchor(new Rectangle2D.Double(x, y, w, h));
}
@Override
public HSLFPictureData getPictureData(){
HSLFSlideShow ppt = getSheet().getSlideShow();
- HSLFPictureData[] pict = ppt.getPictureData();
+ List<HSLFPictureData> pict = ppt.getPictureData();
EscherBSERecord bse = getEscherBSERecord();
if (bse == null){
logger.log(POILogger.ERROR, "no reference to picture data found ");
} else {
- for ( int i = 0; i < pict.length; i++ ) {
- if (pict[i].getOffset() == bse.getOffset()){
- return pict[i];
+ for (HSLFPictureData pd : pict) {
+ if (pd.getOffset() == bse.getOffset()){
+ return pd;
}
}
logger.log(POILogger.ERROR, "no picture found for our BSE offset " + bse.getOffset());
import org.apache.poi.hslf.model.HeadersFooters;
import org.apache.poi.hslf.model.MovieShape;
import org.apache.poi.hslf.model.PPFont;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.Document;
+import org.apache.poi.hslf.record.DocumentAtom;
+import org.apache.poi.hslf.record.ExAviMovie;
+import org.apache.poi.hslf.record.ExControl;
+import org.apache.poi.hslf.record.ExEmbed;
+import org.apache.poi.hslf.record.ExEmbedAtom;
+import org.apache.poi.hslf.record.ExHyperlink;
+import org.apache.poi.hslf.record.ExHyperlinkAtom;
+import org.apache.poi.hslf.record.ExMCIMovie;
+import org.apache.poi.hslf.record.ExObjList;
+import org.apache.poi.hslf.record.ExObjListAtom;
+import org.apache.poi.hslf.record.ExOleObjAtom;
+import org.apache.poi.hslf.record.ExOleObjStg;
+import org.apache.poi.hslf.record.ExVideoContainer;
+import org.apache.poi.hslf.record.FontCollection;
+import org.apache.poi.hslf.record.FontEntityAtom;
+import org.apache.poi.hslf.record.HeadersFootersContainer;
+import org.apache.poi.hslf.record.PersistPtrHolder;
+import org.apache.poi.hslf.record.PositionDependentRecord;
+import org.apache.poi.hslf.record.PositionDependentRecordContainer;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordContainer;
+import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
+import org.apache.poi.hslf.record.SlidePersistAtom;
+import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.sl.usermodel.MasterSheet;
return _titleMasters;
}
- /**
- * Returns the data of all the pictures attached to the SlideShow
- */
- public HSLFPictureData[] getPictureData() {
- return _hslfSlideShow.getPictures();
+ @Override
+ public List<HSLFPictureData> getPictureData() {
+ return _hslfSlideShow.getPictureData();
}
/**
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
// Embedded objects stored in storage records in the document stream, lazily populated.
private HSLFObjectData[] _objects;
- /**
- * Returns the directory in the underlying POIFSFileSystem for the
- * document that is open.
- */
- protected DirectoryNode getPOIFSDirectory() {
- return directory;
- }
+ /**
+ * Returns the directory in the underlying POIFSFileSystem for the
+ * document that is open.
+ */
+ protected DirectoryNode getPOIFSDirectory() {
+ return directory;
+ }
/**
* Constructs a Powerpoint document from fileName. Parses the document
* @param fileName The name of the file to read.
* @throws IOException if there is a problem while parsing the document.
*/
- public HSLFSlideShowImpl(String fileName) throws IOException
- {
- this(new FileInputStream(fileName));
+ @SuppressWarnings("resource")
+ public HSLFSlideShowImpl(String fileName) throws IOException {
+ this(new POIFSFileSystem(new File(fileName)));
}
/**
* @param inputStream the source of the data
* @throws IOException if there is a problem while parsing the document.
*/
- public HSLFSlideShowImpl(InputStream inputStream) throws IOException {
+ @SuppressWarnings("resource")
+ public HSLFSlideShowImpl(InputStream inputStream) throws IOException {
//do Ole stuff
this(new POIFSFileSystem(inputStream));
}
* @param filesystem the POIFS FileSystem to read from
* @throws IOException if there is a problem while parsing the document.
*/
- public HSLFSlideShowImpl(POIFSFileSystem filesystem) throws IOException
- {
+ public HSLFSlideShowImpl(POIFSFileSystem filesystem) throws IOException {
this(filesystem.getRoot());
}
- /**
- * Constructs a Powerpoint document from a POIFS Filesystem. Parses the
- * document and places all the important stuff into data structures.
- *
- * @param filesystem the POIFS FileSystem to read from
- * @throws IOException if there is a problem while parsing the document.
- */
- public HSLFSlideShowImpl(NPOIFSFileSystem filesystem) throws IOException
- {
- this(filesystem.getRoot());
- }
+ /**
+ * Constructs a Powerpoint document from a POIFS Filesystem. Parses the
+ * document and places all the important stuff into data structures.
+ *
+ * @param filesystem the POIFS FileSystem to read from
+ * @throws IOException if there is a problem while parsing the document.
+ */
+ public HSLFSlideShowImpl(NPOIFSFileSystem filesystem) throws IOException {
+ this(filesystem.getRoot());
+ }
- /**
- * Constructs a Powerpoint document from a specific point in a
- * POIFS Filesystem. Parses the document and places all the
- * important stuff into data structures.
- *
- * @deprecated Use {@link #HSLFSlideShowImpl(DirectoryNode)} instead
- * @param dir the POIFS directory to read from
- * @param filesystem the POIFS FileSystem to read from
- * @throws IOException if there is a problem while parsing the document.
- */
- @Deprecated
- public HSLFSlideShowImpl(DirectoryNode dir, POIFSFileSystem filesystem) throws IOException
- {
- this(dir);
- }
+ /**
+ * Constructs a Powerpoint document from a specific point in a
+ * POIFS Filesystem. Parses the document and places all the
+ * important stuff into data structures.
+ *
+ * @deprecated Use {@link #HSLFSlideShowImpl(DirectoryNode)} instead
+ * @param dir the POIFS directory to read from
+ * @param filesystem the POIFS FileSystem to read from
+ * @throws IOException if there is a problem while parsing the document.
+ */
+ @Deprecated
+ public HSLFSlideShowImpl(DirectoryNode dir, POIFSFileSystem filesystem) throws IOException {
+ this(dir);
+ }
/**
* Constructs a Powerpoint document from a specific point in a
public static final HSLFSlideShowImpl create() {
InputStream is = HSLFSlideShowImpl.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt");
if (is == null) {
- throw new RuntimeException("Missing resource 'empty.ppt'");
+ throw new HSLFException("Missing resource 'empty.ppt'");
}
try {
- return new HSLFSlideShowImpl(is);
+ try {
+ return new HSLFSlideShowImpl(is);
+ } finally {
+ is.close();
+ }
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new HSLFException(e);
}
}
* Find and read in pictures contained in this presentation.
* This is lazily called as and when we want to touch pictures.
*/
- @SuppressWarnings("unused")
private void readPictures() throws IOException {
_pictures = new ArrayList<HSLFPictureData>();
// Dummy write out, so the position winds on properly
record.writeOut(cos);
}
+ cos.close();
assert(usr != null && ptr != null);
// Update our cached copy of the bytes that make up the PPT stream
_docstream = new byte[baos.size()];
System.arraycopy(baos.getBuf(), 0, _docstream, 0, baos.size());
+ baos.close();
// Write the PPT stream into the POIFS layer
ByteArrayInputStream bais = new ByteArrayInputStream(_docstream);
new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures"
);
writtenEntries.add("Pictures");
+ pict.close();
}
// If requested, write out any other streams we spot
// Send the POIFSFileSystem object out to the underlying stream
outFS.writeFilesystem(out);
+ outFS.close();
}
/**
public CurrentUserAtom getCurrentUserAtom() { return currentUser; }
/**
- * Return array of pictures contained in this presentation
+ * Return list of pictures contained in this presentation
*
- * @return array with the read pictures or <code>null</code> if the
+ * @return list with the read pictures or an empty list if the
* presentation doesn't contain pictures.
*/
- public HSLFPictureData[] getPictures() {
+ public List<HSLFPictureData> getPictureData() {
if(_pictures == null) {
try {
readPictures();
}
}
- return _pictures.toArray(new HSLFPictureData[_pictures.size()]);
+ return Collections.unmodifiableList(_pictures);
}
/**
import java.awt.geom.Rectangle2D;
import java.io.*;
+import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.usermodel.*;
public void testOleEmbedding2003() throws Exception {
HSLFSlideShowImpl slideShow = new HSLFSlideShowImpl(_slTests.openResourceAsStream("ole2-embedding-2003.ppt"));
// Placeholder EMFs for clients that don't support the OLE components.
- HSLFPictureData[] pictures = slideShow.getPictures();
- assertEquals("Should be two pictures", 2, pictures.length);
+ List<HSLFPictureData> pictures = slideShow.getPictureData();
+ assertEquals("Should be two pictures", 2, pictures.size());
//assertDigestEquals("Wrong data for picture 1", "8d1fbadf4814f321bb1ccdd056e3c788", pictures[0].getData());
//assertDigestEquals("Wrong data for picture 2", "987a698e83559cf3d38a0deeba1cc63b", pictures[1].getData());
assertArrayEquals(expData, compData);
+ poiData1.close();
+ poiData2.close();
+
}
}
import java.io.ByteArrayInputStream;\r
import java.io.ByteArrayOutputStream;\r
import java.security.MessageDigest;\r
+import java.util.List;\r
\r
import org.apache.commons.codec.binary.Base64;\r
import org.apache.poi.POIDataSamples;\r
import org.apache.poi.hpsf.PropertySetFactory;\r
import org.apache.poi.hpsf.SummaryInformation;\r
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;\r
-import org.apache.poi.hslf.usermodel.*;\r
+import org.apache.poi.hslf.usermodel.HSLFPictureData;\r
+import org.apache.poi.hslf.usermodel.HSLFSlide;\r
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;\r
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;\r
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;\r
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;\r
import org.apache.poi.poifs.crypt.CryptoFunctions;\r
import org.apache.poi.poifs.crypt.EncryptionInfo;\r
NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true);\r
HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs);\r
// need to cache data (i.e. read all data) before changing the key size\r
- HSLFPictureData picsExpected[] = hss.getPictures();\r
+ List<HSLFPictureData> picsExpected = hss.getPictureData();\r
hss.getDocumentSummaryInformation();\r
EncryptionInfo ei = hss.getDocumentEncryptionAtom().getEncryptionInfo();\r
((CryptoAPIEncryptionHeader)ei.getHeader()).setKeySize(0x78);\r
\r
fs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));\r
hss = new HSLFSlideShowImpl(fs);\r
- HSLFPictureData picsActual[] = hss.getPictures();\r
+ List<HSLFPictureData> picsActual = hss.getPictureData();\r
fs.close();\r
\r
- assertEquals(picsExpected.length, picsActual.length);\r
- for (int i=0; i<picsExpected.length; i++) {\r
- assertArrayEquals(picsExpected[i].getRawData(), picsActual[i].getRawData());\r
+ assertEquals(picsExpected.size(), picsActual.size());\r
+ for (int i=0; i<picsExpected.size(); i++) {\r
+ assertArrayEquals(picsExpected.get(i).getRawData(), picsActual.get(i).getRawData());\r
}\r
}\r
\r
};\r
\r
MessageDigest md = CryptoFunctions.getMessageDigest(HashAlgorithm.sha1);\r
- HSLFPictureData pd[] = hss.getPictures();\r
+ List<HSLFPictureData> pd = hss.getPictureData();\r
int i = 0;\r
for (HSLFPictureData p : pd) {\r
byte hash[] = md.digest(p.getData());\r
assertTrue(ps.isDocumentSummaryInformation());\r
assertEquals("On-screen Show (4:3)", ps.getProperties()[1].getValue());\r
fs.close();\r
+ fs2.close();\r
}\r
}\r
assertEquals(1, ppt.getSlides().size());
- HSLFPictureData[] pict = ppt.getPictureData();
- assertEquals(2, pict.length);
- assertEquals(PictureType.JPEG, pict[0].getType());
- assertEquals(PictureType.JPEG, pict[1].getType());
+ List<HSLFPictureData> pict = ppt.getPictureData();
+ assertEquals(2, pict.size());
+ assertEquals(PictureType.JPEG, pict.get(0).getType());
+ assertEquals(PictureType.JPEG, pict.get(1).getType());
}
/**
import java.lang.reflect.Constructor;
import java.util.BitSet;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
public void macImages() throws Exception {
HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("53446.ppt"));
- HSLFPictureData[] pictures = hss.getPictures();
- assertEquals(15, pictures.length);
+ List<HSLFPictureData> pictures = hss.getPictureData();
+ assertEquals(15, pictures.size());
int[][] expectedSizes = {
null, // WMF
package org.apache.poi.hslf.usermodel;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import java.awt.Dimension;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.List;
-import junit.framework.TestCase;
-
import org.apache.poi.POIDataSamples;
-import org.apache.poi.hslf.blip.*;
+import org.apache.poi.hslf.blip.DIB;
+import org.apache.poi.hslf.blip.EMF;
+import org.apache.poi.hslf.blip.JPEG;
+import org.apache.poi.hslf.blip.PICT;
+import org.apache.poi.hslf.blip.PNG;
+import org.apache.poi.hslf.blip.WMF;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.junit.Ignore;
+import org.junit.Test;
/**
* Test adding/reading pictures
*
* @author Yegor Kozlov
*/
-public final class TestPictures extends TestCase{
+public final class TestPictures {
private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
//protected File cwd;
/**
* Test read/write Macintosh PICT
*/
+ @Test
public void testPICT() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
byte[] src_bytes = slTests.readFile("cow.pict");
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.PICT);
+ PICT.NativeHeader nHeader = new PICT.NativeHeader(src_bytes, 512);
+ final int expWidth = 197, expHeight = 137;
+ Dimension nDim = nHeader.getSize();
+ assertEquals(expWidth, nDim.getWidth(), 0);
+ assertEquals(expHeight, nDim.getHeight(), 0);
+
+ Dimension dim = data.getImageDimension();
+ assertEquals(expWidth, dim.getWidth(), 0);
+ assertEquals(expHeight, dim.getHeight(), 0);
+
HSLFPictureShape pict = new HSLFPictureShape(data);
assertEquals(data.getIndex(), pict.getPictureIndex());
slide.addShape(pict);
assertEquals(data.getIndex(), pict.getPictureIndex());
//check picture data
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
+ assertEquals(1, pictures.size());
+
+ HSLFPictureData pd = pictures.get(0);
+ dim = pd.getImageDimension();
+ assertEquals(expWidth, dim.width);
+ assertEquals(expHeight, dim.height);
+
//the Picture shape refers to the PictureData object in the Presentation
- assertEquals(pict.getPictureData(), pictures[0]);
+ assertEquals(pict.getPictureData(), pd);
- assertEquals(1, pictures.length);
- assertEquals(PictureType.PICT, pictures[0].getType());
- assertTrue(pictures[0] instanceof PICT);
+ assertEquals(1, pictures.size());
+ assertEquals(PictureType.PICT, pd.getType());
+ assertTrue(pd instanceof PICT);
//compare the content of the initial file with what is stored in the PictureData
- byte[] ppt_bytes = pictures[0].getData();
+ byte[] ppt_bytes = pd.getData();
assertEquals(src_bytes.length, ppt_bytes.length);
//in PICT the first 512 bytes are MAC specific and may not be preserved, ignore them
byte[] b1 = new byte[src_bytes.length-512];
/**
* Test read/write WMF
*/
+ @Test
public void testWMF() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
byte[] src_bytes = slTests.readFile("santa.wmf");
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.WMF);
+ WMF.NativeHeader nHeader = new WMF.NativeHeader(src_bytes, 0);
+ final int expWidth = 136, expHeight = 146;
+ Dimension nDim = nHeader.getSize();
+ assertEquals(expWidth, nDim.getWidth(), 0);
+ assertEquals(expHeight, nDim.getHeight(), 0);
+
+ Dimension dim = data.getImageDimension();
+ assertEquals(expWidth, dim.getWidth(), 0);
+ assertEquals(expHeight, dim.getHeight(), 0);
+
HSLFPictureShape pict = new HSLFPictureShape(data);
assertEquals(data.getIndex(), pict.getPictureIndex());
slide.addShape(pict);
assertEquals(data.getIndex(), pict.getPictureIndex());
//check picture data
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
+ assertEquals(1, pictures.size());
+
+ HSLFPictureData pd = pictures.get(0);
+ dim = pd.getImageDimension();
+ assertEquals(expWidth, dim.width);
+ assertEquals(expHeight, dim.height);
+
//the Picture shape refers to the PictureData object in the Presentation
- assertEquals(pict.getPictureData(), pictures[0]);
-
- assertEquals(1, pictures.length);
- assertEquals(PictureType.WMF, pictures[0].getType());
- assertTrue(pictures[0] instanceof WMF);
+ assertEquals(pict.getPictureData(), pd);
+
+ assertEquals(PictureType.WMF, pd.getType());
+ assertTrue(pd instanceof WMF);
//compare the content of the initial file with what is stored in the PictureData
- byte[] ppt_bytes = pictures[0].getData();
+ byte[] ppt_bytes = pd.getData();
assertEquals(src_bytes.length, ppt_bytes.length);
//in WMF the first 22 bytes - is a metafile header
byte[] b1 = new byte[src_bytes.length-22];
/**
* Test read/write EMF
*/
+ @Test
public void testEMF() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
byte[] src_bytes = slTests.readFile("wrench.emf");
HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.EMF);
-
+ EMF.NativeHeader nHeader = new EMF.NativeHeader(src_bytes, 0);
+ final int expWidth = 190, expHeight = 115;
+ Dimension nDim = nHeader.getSize();
+ assertEquals(expWidth, nDim.getWidth(), 0);
+ assertEquals(expHeight, nDim.getHeight(), 0);
+
+ Dimension dim = data.getImageDimension();
+ assertEquals(expWidth, dim.getWidth(), 0);
+ assertEquals(expHeight, dim.getHeight(), 0);
+
HSLFPictureShape pict = new HSLFPictureShape(data);
assertEquals(data.getIndex(), pict.getPictureIndex());
slide.addShape(pict);
assertEquals(data.getIndex(), pict.getPictureIndex());
//check picture data
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
+ assertEquals(1, pictures.size());
+
+ HSLFPictureData pd = pictures.get(0);
+ dim = pd.getImageDimension();
+ assertEquals(expWidth, dim.width);
+ assertEquals(expHeight, dim.height);
+
//the Picture shape refers to the PictureData object in the Presentation
- assertEquals(pict.getPictureData(), pictures[0]);
+ assertEquals(pict.getPictureData(), pd);
- assertEquals(1, pictures.length);
- assertEquals(PictureType.EMF, pictures[0].getType());
- assertTrue(pictures[0] instanceof EMF);
+ assertEquals(1, pictures.size());
+ assertEquals(PictureType.EMF, pd.getType());
+ assertTrue(pd instanceof EMF);
//compare the content of the initial file with what is stored in the PictureData
- byte[] ppt_bytes = pictures[0].getData();
+ byte[] ppt_bytes = pd.getData();
assertArrayEquals(src_bytes, ppt_bytes);
}
/**
* Test read/write PNG
*/
+ @Test
public void testPNG() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
assertEquals(data.getIndex(), pict.getPictureIndex());
//check picture data
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
//the Picture shape refers to the PictureData object in the Presentation
- assertEquals(pict.getPictureData(), pictures[0]);
+ assertEquals(pict.getPictureData(), pictures.get(0));
- assertEquals(1, pictures.length);
- assertEquals(PictureType.PNG, pictures[0].getType());
- assertTrue(pictures[0] instanceof PNG);
+ assertEquals(1, pictures.size());
+ assertEquals(PictureType.PNG, pictures.get(0).getType());
+ assertTrue(pictures.get(0) instanceof PNG);
//compare the content of the initial file with what is stored in the PictureData
- byte[] ppt_bytes = pictures[0].getData();
+ byte[] ppt_bytes = pictures.get(0).getData();
assertArrayEquals(src_bytes, ppt_bytes);
}
/**
* Test read/write JPEG
*/
+ @Test
public void testJPEG() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
assertEquals(data.getIndex(), pict.getPictureIndex());
//check picture data
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
//the Picture shape refers to the PictureData object in the Presentation
- assertEquals(pict.getPictureData(), pictures[0]);
+ assertEquals(pict.getPictureData(), pictures.get(0));
- assertEquals(1, pictures.length);
- assertEquals(PictureType.JPEG, pictures[0].getType());
- assertTrue(pictures[0] instanceof JPEG);
+ assertEquals(1, pictures.size());
+ assertEquals(PictureType.JPEG, pictures.get(0).getType());
+ assertTrue(pictures.get(0) instanceof JPEG);
//compare the content of the initial file with what is stored in the PictureData
- byte[] ppt_bytes = pictures[0].getData();
+ byte[] ppt_bytes = pictures.get(0).getData();
assertArrayEquals(src_bytes, ppt_bytes);
}
/**
* Test read/write DIB
*/
+ @Test
public void testDIB() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
assertEquals(data.getIndex(), pict.getPictureIndex());
//check picture data
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
//the Picture shape refers to the PictureData object in the Presentation
- assertEquals(pict.getPictureData(), pictures[0]);
+ assertEquals(pict.getPictureData(), pictures.get(0));
- assertEquals(1, pictures.length);
- assertEquals(PictureType.DIB, pictures[0].getType());
- assertTrue(pictures[0] instanceof DIB);
+ assertEquals(1, pictures.size());
+ assertEquals(PictureType.DIB, pictures.get(0).getType());
+ assertTrue(pictures.get(0) instanceof DIB);
//compare the content of the initial file with what is stored in the PictureData
- byte[] ppt_bytes = pictures[0].getData();
+ byte[] ppt_bytes = pictures.get(0).getData();
assertArrayEquals(src_bytes, ppt_bytes);
}
/**
* Read pictures in different formats from a reference slide show
*/
+ @Test
public void testReadPictures() throws Exception {
byte[] src_bytes, ppt_bytes, b1, b2;
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt"));
List<HSLFSlide> slides = ppt.getSlides();
- HSLFPictureData[] pictures = ppt.getPictureData();
- assertEquals(5, pictures.length);
+ List<HSLFPictureData> pictures = ppt.getPictureData();
+ assertEquals(5, pictures.size());
pict = (HSLFPictureShape)slides.get(0).getShapes().get(0); //the first slide contains JPEG
pdata = pict.getPictureData();
* Test that on a party corrupt powerpoint document, which has
* crazy pictures of type 0, we do our best.
*/
+ @Test
public void testZeroPictureType() throws Exception {
HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"));
// Should still have 2 real pictures
- assertEquals(2, hslf.getPictures().length);
+ assertEquals(2, hslf.getPictureData().size());
// Both are real pictures, both WMF
- assertEquals(PictureType.WMF, hslf.getPictures()[0].getType());
- assertEquals(PictureType.WMF, hslf.getPictures()[1].getType());
+ assertEquals(PictureType.WMF, hslf.getPictureData().get(0).getType());
+ assertEquals(PictureType.WMF, hslf.getPictureData().get(1).getType());
// Now test what happens when we use the SlideShow interface
HSLFSlideShow ppt = new HSLFSlideShow(hslf);
List<HSLFSlide> slides = ppt.getSlides();
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
assertEquals(12, slides.size());
- assertEquals(2, pictures.length);
+ assertEquals(2, pictures.size());
HSLFPictureShape pict;
HSLFPictureData pdata;
* YK: The test is disabled because the owner asked to delete the test file from POI svn.
* See "Please remove my file from your svn" on @poi-dev from Dec 12, 2013
*/
- public void disabled_testZeroPictureLength() throws Exception {
+ @Test
+ @Ignore
+ public void testZeroPictureLength() throws Exception {
// take the data from www instead of test directory
URL url = new URL("http://www.cs.sfu.ca/~anoop/courses/CMPT-882-Fall-2002/chris.ppt");
HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(url.openStream());
// Should still have 2 real pictures
- assertEquals(2, hslf.getPictures().length);
+ assertEquals(2, hslf.getPictureData().size());
// Both are real pictures, both WMF
- assertEquals(PictureType.WMF, hslf.getPictures()[0].getType());
- assertEquals(PictureType.WMF, hslf.getPictures()[1].getType());
+ assertEquals(PictureType.WMF, hslf.getPictureData().get(0).getType());
+ assertEquals(PictureType.WMF, hslf.getPictureData().get(1).getType());
// Now test what happens when we use the SlideShow interface
HSLFSlideShow ppt = new HSLFSlideShow(hslf);
List<HSLFSlide> slides = ppt.getSlides();
- HSLFPictureData[] pictures = ppt.getPictureData();
+ List<HSLFPictureData> pictures = ppt.getPictureData();
assertEquals(27, slides.size());
- assertEquals(2, pictures.length);
+ assertEquals(2, pictures.size());
HSLFPictureShape pict;
HSLFPictureData pdata;
data.setData(new byte[100]);
int offset = hslf.addPicture(data);
assertEquals(streamSize, offset);
- assertEquals(3, ppt.getPictureData().length);
+ assertEquals(3, ppt.getPictureData().size());
}
+ @Test
public void testGetPictureName() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt"));
HSLFSlide slide = ppt.getSlides().get(0);
assertEquals("test", p.getPictureName());
}
+ @Test
public void testSetPictureName() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();