From 0a506c7eb5a98362df3478f9b802ad923a8e0476 Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sun, 20 Sep 2015 02:25:35 +0000 Subject: [PATCH] - #58207 - Provide user access to the original image dimensions (XSLF) - same for hslf / common sl - unify method names in H/XSLF Slideshow for common sl - add/fix header information for PICT/EMF/WMF git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1704097 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xslf/usermodel/DataExtraction.java | 2 +- .../apache/poi/stress/HSLFFileHandler.java | 2 +- .../apache/poi/stress/SlideShowHandler.java | 11 ++ .../apache/poi/sl/usermodel/PictureData.java | 18 +- .../apache/poi/sl/usermodel/SlideShow.java | 7 + .../poi/xslf/usermodel/XMLSlideShow.java | 26 ++- .../poi/xslf/usermodel/XSLFPictureData.java | 70 ++++++- .../poi/xslf/usermodel/XSLFPictureShape.java | 25 +-- .../org/apache/poi/xslf/TestXSLFBugs.java | 50 +++-- .../xslf/usermodel/TestXSLFPictureShape.java | 49 +++-- .../src/org/apache/poi/hslf/blip/Bitmap.java | 20 +- .../src/org/apache/poi/hslf/blip/EMF.java | 47 ++++- .../org/apache/poi/hslf/blip/Metafile.java | 27 ++- .../src/org/apache/poi/hslf/blip/PICT.java | 106 ++++++++-- .../src/org/apache/poi/hslf/blip/WMF.java | 105 ++++++---- .../poi/hslf/extractor/ImageExtractor.java | 17 +- .../apache/poi/hslf/usermodel/HSLFFill.java | 8 +- .../poi/hslf/usermodel/HSLFPictureData.java | 14 +- .../poi/hslf/usermodel/HSLFPictureShape.java | 44 ++--- .../poi/hslf/usermodel/HSLFSlideShow.java | 35 +++- .../poi/hslf/usermodel/HSLFSlideShowImpl.java | 102 +++++----- .../poi/hslf/model/TestOleEmbedding.java | 8 +- .../hslf/record/TestDocumentEncryption.java | 20 +- .../apache/poi/hslf/usermodel/TestBugs.java | 8 +- .../poi/hslf/usermodel/TestPicture.java | 5 +- .../poi/hslf/usermodel/TestPictures.java | 181 ++++++++++++------ 26 files changed, 699 insertions(+), 308 deletions(-) diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java b/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java index df29334d9d..7a7d459947 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java @@ -58,7 +58,7 @@ public final class DataExtraction { } // Get the document's embedded files. - List images = ppt.getAllPictures(); + List images = ppt.getPictureData(); for (XSLFPictureData data : images) { PackagePart p = data.getPackagePart(); diff --git a/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java index 838bbf7269..822bf13735 100644 --- a/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java @@ -34,7 +34,7 @@ public class HSLFFileHandler extends SlideShowHandler { 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) { diff --git a/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java b/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java index c1c1302418..34830f1e01 100644 --- a/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java +++ b/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java @@ -17,6 +17,7 @@ package org.apache.poi.stress; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.awt.Dimension; import java.awt.Graphics2D; @@ -31,6 +32,7 @@ import java.util.Map; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.sl.SlideShowFactory; import org.apache.poi.sl.draw.Drawable; +import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.Slide; @@ -45,6 +47,7 @@ public abstract class SlideShowHandler extends POIFSFileHandler { renderSlides(ss); readContent(ss); + readPictures(ss); // write out the file ByteArrayOutputStream out = writeToArray(ss); @@ -98,6 +101,14 @@ public abstract class SlideShowHandler extends POIFSFileHandler { } } + private void readPictures(SlideShow ss) { + for (PictureData pd : ss.getPictureData()) { + Dimension dim = pd.getImageDimension(); + assertTrue(dim.getHeight() >= 0); + assertTrue(dim.getWidth() >= 0); + } + } + private void renderSlides(SlideShow ss) { Dimension pgsize = ss.getPageSize(); diff --git a/src/java/org/apache/poi/sl/usermodel/PictureData.java b/src/java/org/apache/poi/sl/usermodel/PictureData.java index e50149f7d5..62780773ea 100644 --- a/src/java/org/apache/poi/sl/usermodel/PictureData.java +++ b/src/java/org/apache/poi/sl/usermodel/PictureData.java @@ -17,6 +17,7 @@ package org.apache.poi.sl.usermodel; +import java.awt.Dimension; import java.io.IOException; public interface PictureData { @@ -96,4 +97,19 @@ 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 diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShow.java b/src/java/org/apache/poi/sl/usermodel/SlideShow.java index 03e63f240d..53449e76d5 100644 --- a/src/java/org/apache/poi/sl/usermodel/SlideShow.java +++ b/src/java/org/apache/poi/sl/usermodel/SlideShow.java @@ -49,7 +49,14 @@ public interface SlideShow< */ Dimension getPageSize(); + /** + * Returns all Pictures of this slideshow. + * The returned {@link List} is unmodifiable. + * @return a {@link List} of {@link PictureData}. + */ + List getPictureData(); + /** * Adds a picture to the workbook. * diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index 2cf4bda982..a327630ba8 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -21,6 +21,7 @@ import java.io.IOException; 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; @@ -42,6 +43,8 @@ import org.apache.poi.sl.usermodel.SlideShow; 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; @@ -106,12 +109,18 @@ implements SlideShow { 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); + } } } @@ -189,12 +198,8 @@ implements SlideShow { ); } - /** - * 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 getAllPictures() { + @Override + public List getPictureData() { if(_pictures == null){ List mediaParts = getPackage().getPartsByName(Pattern.compile("/ppt/media/.*?")); _pictures = new ArrayList(mediaParts.size()); @@ -472,8 +477,11 @@ implements SlideShow { */ 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; } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java index e6fc0fd4ef..b2d407d231 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java @@ -19,24 +19,41 @@ 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; /** @@ -103,15 +120,52 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture 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; } /** @@ -134,6 +188,8 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture 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 diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index 0dc14844ea..df352b57d0 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -19,12 +19,10 @@ package org.apache.poi.xslf.usermodel; +import java.awt.Dimension; import java.awt.Insets; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; +import java.awt.Rectangle; import java.net.URI; - -import javax.imageio.ImageIO; import javax.xml.namespace.QName; import org.apache.poi.POIXMLException; @@ -87,20 +85,23 @@ public class XSLFPictureShape extends XSLFSimpleShape /** * 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 sets the default size to 200x200 pixels. */ public void resize() { - try { - BufferedImage img = ImageIO.read(getPictureData().getInputStream()); - setAnchor(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight())); + Dimension dim = getPictureData().getImageDimension(); + if (dim.width > 0 && dim.height > 0) + { + setAnchor(new Rectangle(0, 0, dim.width, dim.height)); } - catch (Exception e) { - //default size is 200x200 - setAnchor(new java.awt.Rectangle(50, 50, 200, 200)); + else + { + // unsupported/unknown formats + setAnchor(new Rectangle(50, 50, 200, 200)); } } - + /** * Is this an internal picture (image data included within * the PowerPoint file), or an external linked picture diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java index cd78f6565e..0f1d14f4cb 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java @@ -58,14 +58,14 @@ public class TestXSLFBugs { @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()); @@ -74,11 +74,12 @@ public class TestXSLFBugs { 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()); @@ -86,13 +87,15 @@ public class TestXSLFBugs { // 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 @@ -132,6 +135,7 @@ public class TestXSLFBugs { } } } + ss.close(); } /** @@ -161,6 +165,8 @@ public class TestXSLFBugs { slide = ss.getSlides().get(3); assertContains("POI can read this", getSlideText(slide)); + + ss.close(); } /** @@ -197,6 +203,7 @@ public class TestXSLFBugs { assertEquals(2, internalPictures); assertEquals(1, externalPictures); + ppt.close(); } @Test @@ -225,6 +232,7 @@ public class TestXSLFBugs { slide.draw(graphics); ImageIO.write(imgActual, "PNG", new File("bug54542.png")); + ss.close(); } protected String getSlideText(XSLFSlide slide) { @@ -262,6 +270,7 @@ public class TestXSLFBugs { ss.setSlideOrder(slide, 0); ss.setSlideOrder(slide, 2); validateSlides(ss, true, "Slide1","Slide2","New slide"); + ss.close(); } /** @@ -277,7 +286,7 @@ public class TestXSLFBugs { // 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()); @@ -295,7 +304,7 @@ public class TestXSLFBugs { 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()); @@ -313,7 +322,7 @@ public class TestXSLFBugs { 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()); @@ -330,7 +339,7 @@ public class TestXSLFBugs { // 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()); @@ -357,7 +366,7 @@ public class TestXSLFBugs { // 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()); @@ -368,11 +377,17 @@ public class TestXSLFBugs { 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++) { @@ -380,6 +395,7 @@ public class TestXSLFBugs { 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()); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java index 12dde34afe..b5acb85291 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java @@ -36,44 +36,46 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; public class TestXSLFPictureShape { @Test - public void testCreate() { - XMLSlideShow ppt = new XMLSlideShow(); - assertEquals(0, ppt.getAllPictures().size()); + public void testCreate() throws Exception { + XMLSlideShow ppt1 = new XMLSlideShow(); + assertEquals(0, ppt1.getPictureData().size()); byte[] data1 = new byte[100]; for(int i = 0;i < 100;i++) { data1[i] = (byte)i; } - XSLFPictureData pdata1 = ppt.addPicture(data1, PictureType.JPEG); + XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG); assertEquals(0, pdata1.getIndex()); - assertEquals(1, ppt.getAllPictures().size()); + assertEquals(1, ppt1.getPictureData().size()); - XSLFSlide slide = ppt.createSlide(); + XSLFSlide slide = ppt1.createSlide(); XSLFPictureShape shape1 = slide.createPicture(pdata1); assertNotNull(shape1.getPictureData()); assertArrayEquals(data1, shape1.getPictureData().getData()); byte[] data2 = new byte[200]; for(int i = 0;i < 200;i++) { data2[i] = (byte)i; } - XSLFPictureData pdata2 = ppt.addPicture(data2, PictureType.PNG); + XSLFPictureData pdata2 = ppt1.addPicture(data2, PictureType.PNG); XSLFPictureShape shape2 = slide.createPicture(pdata2); assertNotNull(shape2.getPictureData()); assertEquals(1, pdata2.getIndex()); - assertEquals(2, ppt.getAllPictures().size()); + assertEquals(2, ppt1.getPictureData().size()); assertArrayEquals(data2, shape2.getPictureData().getData()); - ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt); - List pics = ppt.getAllPictures(); + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); + List pics = ppt2.getPictureData(); assertEquals(2, pics.size()); assertArrayEquals(data1, pics.get(0).getData()); assertArrayEquals(data2, pics.get(1).getData()); - List shapes = ppt.getSlides().get(0).getShapes(); + List shapes = ppt2.getSlides().get(0).getShapes(); assertArrayEquals(data1, ((XSLFPictureShape) shapes.get(0)).getPictureData().getData()); assertArrayEquals(data2, ((XSLFPictureShape) shapes.get(1)).getPictureData().getData()); + ppt2.close(); } @Test - public void testCreateMultiplePictures() { - XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide1 = ppt.createSlide(); + public void testCreateMultiplePictures() throws Exception { + XMLSlideShow ppt1 = new XMLSlideShow(); + XSLFSlide slide1 = ppt1.createSlide(); XSLFGroupShape group1 = slide1.createGroup(); @@ -81,7 +83,7 @@ public class TestXSLFPictureShape { // first add 20 images to the slide for (int i = 0; i < 20; i++, pictureIndex++) { byte[] data = new byte[]{(byte)pictureIndex}; - XSLFPictureData elementData = ppt.addPicture(data, PictureType.PNG); + XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG); assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19 XSLFPictureShape picture = slide1.createPicture(elementData); // POI saves images as image1.png, image2.png, etc. @@ -93,7 +95,7 @@ public class TestXSLFPictureShape { // and then add next 20 images to a group for (int i = 0; i < 20; i++, pictureIndex++) { byte[] data = new byte[]{(byte)pictureIndex}; - XSLFPictureData elementData = ppt.addPicture(data, PictureType.PNG); + XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG); XSLFPictureShape picture = group1.createPicture(elementData); // POI saves images as image1.png, image2.png, etc. assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19 @@ -104,10 +106,11 @@ public class TestXSLFPictureShape { // serialize, read back and check that all images are there - ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt); + XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1); + ppt1.close(); // pictures keyed by file name Map pics = new HashMap(); - for(XSLFPictureData p : ppt.getAllPictures()){ + for(XSLFPictureData p : ppt2.getPictureData()){ pics.put(p.getFileName(), p); } assertEquals(40, pics.size()); @@ -119,10 +122,11 @@ public class TestXSLFPictureShape { assertEquals(fileName, data.getFileName()); assertArrayEquals(data1, data.getData()); } + ppt2.close(); } @Test - public void testImageCaching() { + public void testImageCaching() throws Exception { XMLSlideShow ppt = new XMLSlideShow(); byte[] img1 = new byte[]{1,2,3}; byte[] img2 = new byte[]{3,4,5}; @@ -139,10 +143,11 @@ public class TestXSLFPictureShape { XSLFSlide slide2 = ppt.createSlide(); assertNotNull(slide2); + ppt.close(); } @Test - public void testMerge() { + public void testMerge() throws Exception { XMLSlideShow ppt1 = new XMLSlideShow(); byte[] data1 = new byte[100]; XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG); @@ -151,7 +156,7 @@ public class TestXSLFPictureShape { XSLFPictureShape shape1 = slide1.createPicture(pdata1); CTPicture ctPic1 = (CTPicture)shape1.getXmlObject(); ctPic1.getNvPicPr().getNvPr().addNewCustDataLst().addNewTags().setId("rId99"); - + XMLSlideShow ppt2 = new XMLSlideShow(); XSLFSlide slide2 = ppt2.createSlide().importContent(slide1); @@ -162,5 +167,7 @@ public class TestXSLFPictureShape { CTPicture ctPic2 = (CTPicture)shape2.getXmlObject(); assertFalse(ctPic2.getNvPicPr().getNvPr().isSetCustDataLst()); + ppt1.close(); + ppt2.close(); } } \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java index 416315a2f5..c25d7de84f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java @@ -17,10 +17,15 @@ 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. @@ -49,4 +54,13 @@ public abstract class Bitmap extends HSLFPictureData { 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); + } + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java index 3c814893d9..0de8cd744a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java @@ -17,6 +17,8 @@ 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; @@ -24,6 +26,8 @@ import java.io.InputStream; 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; /** @@ -31,6 +35,38 @@ 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 { @@ -59,16 +95,21 @@ public final class EMF extends Metafile { 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); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java index b9f66ff29b..74a793f5ab 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java @@ -17,13 +17,17 @@ 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. @@ -114,11 +118,22 @@ public abstract class Metafile extends HSLFPictureData { } } - 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())) + ); + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java index a21e0fe6b0..a5670a126d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java @@ -17,6 +17,8 @@ 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; @@ -29,7 +31,80 @@ import org.apache.poi.util.Units; * 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(); @@ -38,14 +113,7 @@ public final class PICT extends Metafile { 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){ @@ -71,22 +139,24 @@ public final class PICT extends Metafile { @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); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java index 14d1b2652f..bd459c1d45 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java @@ -17,6 +17,8 @@ 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; @@ -26,6 +28,7 @@ import java.util.zip.InflaterInputStream; 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; @@ -45,11 +48,7 @@ public final class WMF extends Metafile { 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 ); @@ -68,18 +67,16 @@ public final class WMF extends Metafile { @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); @@ -135,25 +132,55 @@ public final class WMF extends Metafile { *
  • short Checksum; Checksum value for previous 10 shorts * */ - 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; @@ -169,15 +196,15 @@ public final class WMF extends Metafile { * 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 { @@ -198,7 +225,13 @@ public final class WMF extends Metafile { 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; } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java b/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java index 97b822a991..4062aeb8ee 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java @@ -17,11 +17,14 @@ 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. @@ -38,9 +41,9 @@ public final class ImageExtractor { 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 pdata = ppt.getPictureData(); + for (int i = 0; i < pdata.size(); i++) { + HSLFPictureData pict = pdata.get(i); // picture data byte[] data = pict.getData(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java index 7940892e7d..5c4f1461af 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java @@ -264,7 +264,7 @@ public final class HSLFFill { if (p == null) return null; HSLFSlideShow ppt = shape.getSheet().getSlideShow(); - HSLFPictureData[] pict = ppt.getPictureData(); + List pict = ppt.getPictureData(); Document doc = ppt.getDocumentRecord(); EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); @@ -276,9 +276,9 @@ public final class HSLFFill { 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; } } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java index a2c27e51c1..0100658fe4 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java @@ -34,8 +34,6 @@ import org.apache.poi.util.*; */ public abstract class HSLFPictureData implements PictureData { - protected POILogger logger = POILogFactory.getLogger(this.getClass()); - /** * Size of the image checksum calculated using MD5 algorithm. */ @@ -116,7 +114,11 @@ public abstract class HSLFPictureData implements PictureData { return uid; } - + @Override + public byte[] getChecksum() { + return getChecksum(getData()); + } + /** * Compute 16-byte checksum of this picture using MD5 algorithm. */ @@ -141,13 +143,13 @@ public abstract class HSLFPictureData implements PictureData { 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); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java index 639545c87b..58ce1a1f22 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java @@ -17,15 +17,11 @@ 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; @@ -34,7 +30,6 @@ import org.apache.poi.ddf.EscherProperties; 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; @@ -121,43 +116,30 @@ public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape 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()); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index fd31be4365..697f10521a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -41,8 +41,33 @@ import org.apache.poi.hslf.exceptions.HSLFException; 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; @@ -486,11 +511,9 @@ public final class HSLFSlideShow implements SlideShow getPictureData() { + return _hslfSlideShow.getPictureData(); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java index 4b8b5dc2c8..80781ee14e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java @@ -19,12 +19,13 @@ package org.apache.poi.hslf.usermodel; 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; @@ -84,13 +85,13 @@ public final class HSLFSlideShowImpl extends POIDocument { // 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 @@ -99,9 +100,9 @@ public final class HSLFSlideShowImpl extends POIDocument { * @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))); } /** @@ -111,7 +112,8 @@ public final class HSLFSlideShowImpl extends POIDocument { * @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)); } @@ -123,38 +125,35 @@ public final class HSLFSlideShowImpl extends POIDocument { * @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 @@ -196,12 +195,16 @@ public final class HSLFSlideShowImpl extends POIDocument { 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); } } @@ -362,7 +365,6 @@ public final class HSLFSlideShowImpl extends POIDocument { * 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(); @@ -503,6 +505,7 @@ public final class HSLFSlideShowImpl extends POIDocument { // Dummy write out, so the position winds on properly record.writeOut(cos); } + cos.close(); assert(usr != null && ptr != null); @@ -596,6 +599,7 @@ public final class HSLFSlideShowImpl extends POIDocument { // 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); @@ -618,6 +622,7 @@ public final class HSLFSlideShowImpl extends POIDocument { new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures" ); writtenEntries.add("Pictures"); + pict.close(); } // If requested, write out any other streams we spot @@ -627,6 +632,7 @@ public final class HSLFSlideShowImpl extends POIDocument { // Send the POIFSFileSystem object out to the underlying stream outFS.writeFilesystem(out); + outFS.close(); } /** @@ -740,12 +746,12 @@ public final class HSLFSlideShowImpl extends POIDocument { 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 null if the + * @return list with the read pictures or an empty list if the * presentation doesn't contain pictures. */ - public HSLFPictureData[] getPictures() { + public List getPictureData() { if(_pictures == null) { try { readPictures(); @@ -754,7 +760,7 @@ public final class HSLFSlideShowImpl extends POIDocument { } } - return _pictures.toArray(new HSLFPictureData[_pictures.size()]); + return Collections.unmodifiableList(_pictures); } /** diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java index 834f1520b1..a03c253130 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import java.awt.geom.Rectangle2D; import java.io.*; +import java.util.List; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.usermodel.*; @@ -44,8 +45,8 @@ public final class TestOleEmbedding { 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 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()); @@ -137,5 +138,8 @@ public final class TestOleEmbedding { assertArrayEquals(expData, compData); + poiData1.close(); + poiData2.close(); + } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java index 7176c504e7..e27c808f6a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java @@ -26,6 +26,7 @@ import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.security.MessageDigest; +import java.util.List; import org.apache.commons.codec.binary.Base64; import org.apache.poi.POIDataSamples; @@ -34,7 +35,11 @@ import org.apache.poi.hpsf.PropertySet; import org.apache.poi.hpsf.PropertySetFactory; import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; -import org.apache.poi.hslf.usermodel.*; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFSlide; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFTextParagraph; import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.EncryptionInfo; @@ -84,7 +89,7 @@ public class TestDocumentEncryption { NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true); HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); // need to cache data (i.e. read all data) before changing the key size - HSLFPictureData picsExpected[] = hss.getPictures(); + List picsExpected = hss.getPictureData(); hss.getDocumentSummaryInformation(); EncryptionInfo ei = hss.getDocumentEncryptionAtom().getEncryptionInfo(); ((CryptoAPIEncryptionHeader)ei.getHeader()).setKeySize(0x78); @@ -95,12 +100,12 @@ public class TestDocumentEncryption { fs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); hss = new HSLFSlideShowImpl(fs); - HSLFPictureData picsActual[] = hss.getPictures(); + List picsActual = hss.getPictureData(); fs.close(); - assertEquals(picsExpected.length, picsActual.length); - for (int i=0; i pd = hss.getPictureData(); int i = 0; for (HSLFPictureData p : pd) { byte hash[] = md.digest(p.getData()); @@ -177,5 +182,6 @@ public class TestDocumentEncryption { assertTrue(ps.isDocumentSummaryInformation()); assertEquals("On-screen Show (4:3)", ps.getProperties()[1].getValue()); fs.close(); + fs2.close(); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java index a8543924a6..527b92e1c5 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java @@ -77,10 +77,10 @@ public final class TestBugs { 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 pict = ppt.getPictureData(); + assertEquals(2, pict.size()); + assertEquals(PictureType.JPEG, pict.get(0).getType()); + assertEquals(PictureType.JPEG, pict.get(1).getType()); } /** diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java index a660657102..7dc57f772c 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java @@ -34,6 +34,7 @@ import java.io.InputStream; 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; @@ -117,8 +118,8 @@ public final class TestPicture { public void macImages() throws Exception { HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("53446.ppt")); - HSLFPictureData[] pictures = hss.getPictures(); - assertEquals(15, pictures.length); + List pictures = hss.getPictureData(); + assertEquals(15, pictures.size()); int[][] expectedSizes = { null, // WMF diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java index 6f9de093ac..d45f18222c 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java @@ -18,24 +18,32 @@ 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; @@ -43,12 +51,23 @@ public final class TestPictures extends TestCase{ /** * 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); @@ -67,15 +86,22 @@ public final class TestPictures extends TestCase{ assertEquals(data.getIndex(), pict.getPictureIndex()); //check picture data - HSLFPictureData[] pictures = ppt.getPictureData(); + List 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]; @@ -88,12 +114,23 @@ public final class TestPictures extends TestCase{ /** * 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); @@ -112,15 +149,21 @@ public final class TestPictures extends TestCase{ assertEquals(data.getIndex(), pict.getPictureIndex()); //check picture data - HSLFPictureData[] pictures = ppt.getPictureData(); + List 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]; @@ -133,13 +176,23 @@ public final class TestPictures extends TestCase{ /** * 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); @@ -158,21 +211,29 @@ public final class TestPictures extends TestCase{ assertEquals(data.getIndex(), pict.getPictureIndex()); //check picture data - HSLFPictureData[] pictures = ppt.getPictureData(); + List 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(); @@ -197,21 +258,22 @@ public final class TestPictures extends TestCase{ assertEquals(data.getIndex(), pict.getPictureIndex()); //check picture data - HSLFPictureData[] pictures = ppt.getPictureData(); + List 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(); @@ -237,21 +299,22 @@ public final class TestPictures extends TestCase{ assertEquals(data.getIndex(), pict.getPictureIndex()); //check picture data - HSLFPictureData[] pictures = ppt.getPictureData(); + List 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(); @@ -276,21 +339,22 @@ public final class TestPictures extends TestCase{ assertEquals(data.getIndex(), pict.getPictureIndex()); //check picture data - HSLFPictureData[] pictures = ppt.getPictureData(); + List 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; @@ -299,8 +363,8 @@ public final class TestPictures extends TestCase{ HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt")); List slides = ppt.getSlides(); - HSLFPictureData[] pictures = ppt.getPictureData(); - assertEquals(5, pictures.length); + List pictures = ppt.getPictureData(); + assertEquals(5, pictures.size()); pict = (HSLFPictureShape)slides.get(0).getShapes().get(0); //the first slide contains JPEG pdata = pict.getPictureData(); @@ -360,21 +424,22 @@ public final class TestPictures extends TestCase{ * 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 slides = ppt.getSlides(); - HSLFPictureData[] pictures = ppt.getPictureData(); + List pictures = ppt.getPictureData(); assertEquals(12, slides.size()); - assertEquals(2, pictures.length); + assertEquals(2, pictures.size()); HSLFPictureShape pict; HSLFPictureData pdata; @@ -394,23 +459,25 @@ public final class TestPictures extends TestCase{ * 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 slides = ppt.getSlides(); - HSLFPictureData[] pictures = ppt.getPictureData(); + List pictures = ppt.getPictureData(); assertEquals(27, slides.size()); - assertEquals(2, pictures.length); + assertEquals(2, pictures.size()); HSLFPictureShape pict; HSLFPictureData pdata; @@ -436,10 +503,11 @@ public final class TestPictures extends TestCase{ 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); @@ -448,6 +516,7 @@ public final class TestPictures extends TestCase{ assertEquals("test", p.getPictureName()); } + @Test public void testSetPictureName() throws Exception { HSLFSlideShow ppt = new HSLFSlideShow(); -- 2.39.5