]> source.dussan.org Git - poi.git/commitdiff
- #58207 - Provide user access to the original image dimensions (XSLF)
authorAndreas Beeker <kiwiwings@apache.org>
Sun, 20 Sep 2015 02:25:35 +0000 (02:25 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sun, 20 Sep 2015 02:25:35 +0000 (02:25 +0000)
- 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

26 files changed:
src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java
src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java
src/integrationtest/org/apache/poi/stress/SlideShowHandler.java
src/java/org/apache/poi/sl/usermodel/PictureData.java
src/java/org/apache/poi/sl/usermodel/SlideShow.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java
src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java
src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java
src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java
src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java
src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java

index df29334d9df201d4d6b238eba296bb2dfed74c0c..7a7d4599472d78178a1111956a45d86695aa85dd 100644 (file)
@@ -58,7 +58,7 @@ public final class DataExtraction {
         }\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
index 838bbf7269744977786e0f4ebb88cddf7dfdb32c..822bf13735288da9dd8419f65df1b1eb628a746b 100644 (file)
@@ -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) {
index c1c13024184b8450607bf11b569a5d59077c91ec..34830f1e01a9be19682eea58d15374ddb3826109 100644 (file)
@@ -17,6 +17,7 @@
 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
@@ -31,6 +32,7 @@ import java.util.Map;
 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
@@ -45,6 +47,7 @@ public abstract class SlideShowHandler extends POIFSFileHandler {
         renderSlides(ss);\r
 \r
         readContent(ss);\r
+        readPictures(ss);\r
 \r
         // write out the file\r
         ByteArrayOutputStream out = writeToArray(ss);\r
@@ -98,6 +101,14 @@ public abstract class SlideShowHandler extends POIFSFileHandler {
         }\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
index e50149f7d567878a517572de4ff234b966059f9b..62780773eac37b96e5ef8902de9738b355af435b 100644 (file)
@@ -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
index 03e63f240d929be1b7e3c77d57e4100bf0edbfc0..53449e76d5c4de290ee01c05f4c3079fd4406f39 100644 (file)
@@ -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<? extends PictureData> getPictureData();
 
+        
     /**
      * Adds a picture to the workbook.
      *
index 2cf4bda982b9122c0b05cbe341f9a027e0b9ddf6..a327630ba8439b3e118146f0bc6c3d47350b998f 100644 (file)
@@ -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<XSLFShape,XSLFTextParagraph> {
     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<XSLFShape,XSLFTextParagraph> {
         );
     }
 
-    /**
-     * 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());
@@ -472,8 +477,11 @@ implements SlideShow<XSLFShape,XSLFTextParagraph> {
      */
     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;
             }
         }
index e6fc0fd4ef74ecef29cf86266aceb4f5cd6760fb..b2d407d23142339134feb50cc8e59bad5bcdf266 100644 (file)
 
 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
index 0dc14844ea67e7efdef3d6f42c456f7f49d86f97..df352b57d00a55c756b80995021dc0319f179efa 100644 (file)
 \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
@@ -87,20 +85,23 @@ public class XSLFPictureShape extends XSLFSimpleShape
 \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
index cd78f6565e4e56c164ef9fcfb68d30e3051fa445..0f1d14f4cbfead145da3b1ab8d5f5a58af74a042 100644 (file)
@@ -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());
index 12dde34afe9818b19459f17b1d1918eda49d7b5d..b5acb85291d67629e62533d3c0d9424aac729084 100644 (file)
@@ -36,44 +36,46 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
 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
@@ -81,7 +83,7 @@ public class TestXSLFPictureShape {
         // 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
@@ -93,7 +95,7 @@ public class TestXSLFPictureShape {
         // 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
@@ -104,10 +106,11 @@ public class TestXSLFPictureShape {
 \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
@@ -119,10 +122,11 @@ public class TestXSLFPictureShape {
             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
@@ -139,10 +143,11 @@ public class TestXSLFPictureShape {
         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
@@ -151,7 +156,7 @@ public class TestXSLFPictureShape {
         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
@@ -162,5 +167,7 @@ public class TestXSLFPictureShape {
         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
index 416315a2f598fcdc1ed486d4ef148649d6a079e6..c25d7de84f559ad8bba98d84671cba713bc213ad 100644 (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.
@@ -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);
+        }
+    }
 }
index 3c814893d9abf96798d63212ec1c654c256e0a71..0de8cd744a6cb507af4658e6ae9912474eaf8f56 100644 (file)
@@ -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);
 
index b9f66ff29b937e2d1dcb366a5f6534e636b97637..74a793f5abab7d32f0152ceebad2cc5166765fb9 100644 (file)
 
 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()))
+        );
+    }
 }
index a21e0fe6b011221eaba2119825882c00bace9453..a5670a126d02fc84b835597a5ce99f4bde3b54d9 100644 (file)
@@ -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);
 
index 14d1b2652fbbc342e2f71dae2f1ebb6fe421c408..bd459c1d45e96521c3e16127eb9527b2cc3e4c42 100644 (file)
@@ -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 {
      *  <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;
@@ -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;
         }
     }
index 97b822a9912d25f950495602e7ee734059fe6880..4062aeb8ee314dcccdb43ae90aa630641c830bdf 100644 (file)
 
 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<HSLFPictureData> pdata = ppt.getPictureData();
+        for (int i = 0; i < pdata.size(); i++) {
+            HSLFPictureData pict = pdata.get(i);
 
             // picture data
             byte[] data = pict.getData();
index 7940892e7dc893e307e2fb682834590cba3ea792..5c4f1461aff59595e69d118530c2065632aa443f 100644 (file)
@@ -264,7 +264,7 @@ public final class HSLFFill {
         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();
@@ -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;
                 }
             }
         }
index a2c27e51c196408c85a72a273b806e05107b4f8a..0100658fe40cee45396ba63d1c3739698ef8e059 100644 (file)
@@ -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);
     }
 
     /**
index 639545c87ba9daefc8309117a9e11036460ba0b8..58ce1a1f2229c62f82c73fd5e2a0b28069e6d6ed 100644 (file)
 
 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<HS
     /**
      * 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());
index fd31be4365eab3ca4ede80a0f75fc72de32dbd7f..697f10521abc25cf1c317cdfb4d37591a0bb25da 100644 (file)
@@ -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<HSLFShape,HSLFTextParagrap
                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();
        }
 
        /**
index 4b8b5dc2c877a54198800d88aac1aeb41477f5d4..80781ee14e4d40757e3e0e0113784ea218bb5c6c 100644 (file)
@@ -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<HSLFPictureData>();
 
@@ -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 <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();
@@ -754,7 +760,7 @@ public final class HSLFSlideShowImpl extends POIDocument {
              }
           }
           
-               return _pictures.toArray(new HSLFPictureData[_pictures.size()]);
+               return Collections.unmodifiableList(_pictures);
        }
 
     /**
index 834f1520b13ff82797ef2b2aaedef47c2e40b248..a03c253130163d978a64af05912b9b41b966e8e5 100644 (file)
@@ -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<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());
 
@@ -137,5 +138,8 @@ public final class TestOleEmbedding {
        
        assertArrayEquals(expData, compData);
        
+       poiData1.close();
+       poiData2.close();
+       
     }
 }
index 7176c504e786de62ff9c3c7b1015dfde577ad450..e27c808f6a2a3ce2eb235ca8d04cbafb545afbf7 100644 (file)
@@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
 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
@@ -34,7 +35,11 @@ import org.apache.poi.hpsf.PropertySet;
 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
@@ -84,7 +89,7 @@ public class TestDocumentEncryption {
         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
@@ -95,12 +100,12 @@ public class TestDocumentEncryption {
         \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
@@ -158,7 +163,7 @@ public class TestDocumentEncryption {
         };\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
@@ -177,5 +182,6 @@ public class TestDocumentEncryption {
         assertTrue(ps.isDocumentSummaryInformation());\r
         assertEquals("On-screen Show (4:3)", ps.getProperties()[1].getValue());\r
         fs.close();\r
+        fs2.close();\r
     }\r
 }\r
index a8543924a607e44cbf4c6665a6598ffde32d4470..527b92e1c5e2f9024819cf616ecd58eabf202f75 100644 (file)
@@ -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<HSLFPictureData> pict = ppt.getPictureData();
+        assertEquals(2, pict.size());
+        assertEquals(PictureType.JPEG, pict.get(0).getType());
+        assertEquals(PictureType.JPEG, pict.get(1).getType());
     }
 
     /**
index a6606571021239795ecf342a2e59f5a85ffd3259..7dc57f772ce6e056391d90f7a477f595c322b881 100644 (file)
@@ -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<HSLFPictureData> pictures = hss.getPictureData();
+        assertEquals(15, pictures.size());
 
         int[][] expectedSizes = {
                 null,           // WMF
index 6f9de093ac09a4e195bf5bdfb401605afcac2db2..d45f18222cd71a8acc86b013761c68017597dc46 100644 (file)
 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<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];
@@ -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<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];
@@ -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<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();
 
@@ -197,21 +258,22 @@ public final class TestPictures extends TestCase{
         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();
 
@@ -237,21 +299,22 @@ public final class TestPictures extends TestCase{
         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();
 
@@ -276,21 +339,22 @@ public final class TestPictures extends TestCase{
         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;
@@ -299,8 +363,8 @@ public final class TestPictures extends TestCase{
 
         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();
@@ -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<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;
@@ -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<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;
@@ -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();