]> source.dussan.org Git - poi.git/commitdiff
Bugzilla 53446 - Fixed some problems extracting PNGs
authorYegor Kozlov <yegor@apache.org>
Sat, 4 Aug 2012 05:30:19 +0000 (05:30 +0000)
committerYegor Kozlov <yegor@apache.org>
Sat, 4 Aug 2012 05:30:19 +0000 (05:30 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1369263 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/usermodel/HSSFPictureData.java
src/java/org/apache/poi/util/PngUtils.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java
src/scratchpad/src/org/apache/poi/hwpf/usermodel/Picture.java
src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java
src/scratchpad/testcases/org/apache/poi/hwpf/TestHWPFPictures.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFPictureData.java
test-data/document/53446.doc [new file with mode: 0644]
test-data/slideshow/53446.ppt [new file with mode: 0644]
test-data/spreadsheet/53446.xls [new file with mode: 0644]

index 0602dfd241c458071e5d1a837bd867476b95abee..d3a744b48ebd98392c7e076b372ac11528387a0f 100644 (file)
@@ -34,7 +34,8 @@
 
     <changes>
         <release version="3.9-beta1" date="2012-??-??">
-          <action dev="poi-developers" type="fix">53205 - Fix some parsing errors and encoding issues in HDGF </action>
+          <action dev="poi-developers" type="add">53446 - Fixed some problems extracting PNGs </action>
+          <action dev="poi-developers" type="fix">53205 - Fixed some parsing errors and encoding issues in HDGF </action>
           <action dev="poi-developers" type="add">53204 - Improved performanceof PageSettingsBlock in HSSF </action>
           <action dev="poi-developers" type="add">53500 - Getter for repeating rows and columns</action>
           <action dev="poi-developers" type="fix">53369 - Fixed tests failing on JDK 1.7</action>
index 0516cccf6bb5157b9407c4ba01f6cf07be9a2526..69bdae152108d570f9ab3c804d0ab13b08d453e6 100644 (file)
@@ -22,6 +22,7 @@ import org.apache.poi.ddf.EscherBitmapBlip;
 import org.apache.poi.ddf.EscherBlipRecord;
 import org.apache.poi.ddf.EscherMetafileBlip;
 import org.apache.poi.ss.usermodel.PictureData;
+import org.apache.poi.util.PngUtils;
 
 /**
  * Represents binary data stored in the file.  Eg. A GIF, JPEG etc...
@@ -60,7 +61,18 @@ public class HSSFPictureData implements PictureData
      */
     public byte[] getData()
     {
-        return blip.getPicturedata();
+        byte[] pictureData = blip.getPicturedata();
+
+        //PNG created on MAC may have a 16-byte prefix which prevents successful reading.
+        //Just cut it off!.
+        if (PngUtils.matchesPngHeader(pictureData, 16))
+        {
+            byte[] png = new byte[pictureData.length-16];
+            System.arraycopy(pictureData, 16, png, 0, png.length);
+            pictureData = png;
+        }
+
+        return pictureData;
     }
 
     /**
diff --git a/src/java/org/apache/poi/util/PngUtils.java b/src/java/org/apache/poi/util/PngUtils.java
new file mode 100644 (file)
index 0000000..7856758
--- /dev/null
@@ -0,0 +1,57 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.util;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+\r
+public final class PngUtils {\r
+\r
+    /**\r
+     * File header for PNG format.\r
+     */\r
+    private static final byte[] PNG_FILE_HEADER =\r
+        new byte[] { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };\r
+\r
+    private PngUtils() {\r
+        // no instances of this class\r
+    }\r
+\r
+    /**\r
+     * Checks if the offset matches the PNG header.\r
+     *\r
+     * @param data the data to check.\r
+     * @param offset the offset to check at.\r
+     * @return {@code true} if the offset matches.\r
+     */\r
+    public static boolean matchesPngHeader(byte[] data, int offset) {\r
+        if (data == null || data.length - offset < PNG_FILE_HEADER.length) {\r
+            return false;\r
+        }\r
+\r
+        for (int i = 0; i < PNG_FILE_HEADER.length; i++) {\r
+            if (PNG_FILE_HEADER[i] != data[i + offset]) {\r
+                return false;\r
+            }\r
+        }\r
+\r
+        return true;\r
+    }\r
+}\r
index 20016fd6b3bbe59a549dec60a16929694057e23a..12b98f1802175c7b212453d452a79cc2d8ea6d62 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.hslf.blip;
 
+import org.apache.poi.util.PngUtils;
 import org.apache.poi.hslf.model.Picture;
 import org.apache.poi.hslf.exceptions.HSLFException;
 
@@ -35,22 +36,19 @@ public final class PNG extends Bitmap {
     /**
      * @return PNG data
      */
-    public byte[] getData(){
-         byte[] data = super.getData();
-          try {
-              //PNG created on MAC may have a 16-byte prefix which prevents successful reading.
-              //Just cut it off!.
-              BufferedImage bi = ImageIO.read(new ByteArrayInputStream(data));
-              if (bi == null){
-                  byte[] png = new byte[data.length-16];
-                  System.arraycopy(data, 16, png, 0, png.length);
-                  data = png;
-              }
-          } catch (IOException e){
-              throw new HSLFException(e);
-          }
-         return data;
-     }
+    public byte[] getData() {
+        byte[] data = super.getData();
+
+        //PNG created on MAC may have a 16-byte prefix which prevents successful reading.
+        //Just cut it off!.
+        if (PngUtils.matchesPngHeader(data, 16)) {
+            byte[] png = new byte[data.length-16];
+            System.arraycopy(data, 16, png, 0, png.length);
+            data = png;
+        }
+
+        return data;
+    }
 
     /**
      * @return type of  this picture
index ff7af7cf21fa64c7354c2627b57103c9a750155c..670755dbf582ef4cbce8e649fe7a47e0dbf76eb3 100644 (file)
@@ -34,6 +34,7 @@ import org.apache.poi.ddf.EscherProperty;
 import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.hwpf.model.PICF;
 import org.apache.poi.hwpf.model.PICFAndOfficeArtData;
+import org.apache.poi.util.PngUtils;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.StringUtil;
@@ -191,6 +192,15 @@ public final class Picture
         {
             // Raw data is not compressed.
             content = rawContent;
+
+            //PNG created on MAC may have a 16-byte prefix which prevents successful reading.
+            //Just cut it off!.
+            if (PngUtils.matchesPngHeader(content, 16))
+            {
+                byte[] png = new byte[content.length-16];
+                System.arraycopy(content, 16, png, 0, png.length);
+                content = png;
+            }
         }
     }
 
index 871893210ab1b854fdbbc9a1889cd126f007ffde..3444ae5fe81fe39f87adff25c2ad4579325da076 100644 (file)
@@ -20,10 +20,13 @@ package org.apache.poi.hslf.model;
 import java.awt.Graphics2D;
 import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import javax.imageio.ImageIO;
 
 import junit.framework.TestCase;
 
 import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.hslf.HSLFSlideShow;
 import org.apache.poi.hslf.usermodel.PictureData;
 import org.apache.poi.hslf.usermodel.SlideShow;
 import org.apache.poi.POIDataSamples;
@@ -88,4 +91,41 @@ public final class TestPicture extends TestCase {
         Graphics2D graphics = img.createGraphics();
         pict.draw(graphics);
     }
+
+    public void testMacImages() throws Exception {
+        HSLFSlideShow hss = new HSLFSlideShow(_slTests.openResourceAsStream("53446.ppt"));
+
+        PictureData[] pictures = hss.getPictures();
+        assertEquals(15, pictures.length);
+
+        int[][] expectedSizes = {
+                null,           // WMF
+                { 427, 428 },   // PNG
+                { 371, 370 },   // PNG
+                { 288, 183 },   // PNG
+                { 285, 97 },    // PNG
+                { 288, 168 },   // PNG
+                null,           // WMF
+                null,           // WMF
+                { 199, 259 },   // PNG
+                { 432, 244 },   // PNG
+                { 261, 258 },   // PNG
+                null,           // WMF
+                null,           // WMF
+                null,           // WMF
+                null            // EMF
+        };
+
+        for (int i = 0; i < pictures.length; i++) {
+            BufferedImage image = ImageIO.read(new ByteArrayInputStream(pictures[i].getData()));
+
+            if (pictures[i].getType() != Picture.WMF && pictures[i].getType() != Picture.EMF) {
+                assertNotNull(image);
+
+                int[] dimensions = expectedSizes[i];
+                assertEquals(dimensions[0], image.getWidth());
+                assertEquals(dimensions[1], image.getHeight());
+            }
+        }
+    }
 }
index f650f0d8907d2de50bc775aa9f30d852df2abf4c..ae7cc3df246e33578ee163634db4a4c18bc2f5ec 100644 (file)
 
 package org.apache.poi.hwpf;
 
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
 import java.util.List;
 
 import junit.framework.TestCase;
 
+import org.apache.poi.POIDataSamples;
 import org.apache.poi.hwpf.model.PicturesTable;
 import org.apache.poi.hwpf.usermodel.Picture;
 import org.apache.poi.POIDataSamples;
@@ -128,6 +132,30 @@ public final class TestHWPFPictures extends TestCase {
                assertBytesSame(picBytes, pic.getContent());
        }
 
+       public void testMacImages() throws Exception {
+        HWPFDocument docC = HWPFTestDataSamples.openSampleFile("53446.doc");
+               PicturesTable picturesTable = docC.getPicturesTable();
+               List<Picture> pictures = picturesTable.getAllPictures();
+
+               assertEquals(4, pictures.size());
+
+        int[][] expectedSizes = {
+            { 185, 42 },  // PNG
+            { 260, 114 }, // PNG
+            { 185, 42 },  // PNG
+            { 260, 114 }, // PNG
+       };
+
+       for (int i = 0; i < pictures.size(); i++) {
+           BufferedImage image = ImageIO.read(new ByteArrayInputStream(pictures.get(i).getContent()));
+           assertNotNull(image);
+
+           int[] dimensions = expectedSizes[i];
+           assertEquals(dimensions[0], image.getWidth());
+           assertEquals(dimensions[1], image.getHeight());
+       }
+       }
+
        /**
         * Pending the missing files being uploaded to
         *  bug #44937
index 99f4ad80684df71a8ffe2c8fc60e0c764fdc09e2..b9ff69543a49d3bf0d1eea99703dc9d462328b7b 100644 (file)
@@ -71,6 +71,29 @@ public final class TestHSSFPictureData extends TestCase{
             }
         }
     }
+       
+       public void testMacPicture() throws IOException {
+        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("53446.xls");
+
+        @SuppressWarnings("unchecked")
+        List<HSSFPictureData> lst = (List<HSSFPictureData>)(List<?>)wb.getAllPictures();
+        assertEquals(1, lst.size());
+
+        HSSFPictureData pict = lst.get(0);
+        String ext = pict.suggestFileExtension();
+        if (!ext.equals("png")) {
+            fail("Expected a PNG.");
+        }
+
+        //try to read image data using javax.imageio.* (JDK 1.4+)
+        byte[] data = pict.getData();
+        BufferedImage png = ImageIO.read(new ByteArrayInputStream(data));
+        assertNotNull(png);
+        assertEquals(78, png.getWidth());
+        assertEquals(76, png.getHeight());
+        assertEquals(HSSFWorkbook.PICTURE_TYPE_PNG, pict.getFormat());
+        assertEquals("image/png", pict.getMimeType());
+    }
 
     public void testNotNullPictures() throws IOException {
 
diff --git a/test-data/document/53446.doc b/test-data/document/53446.doc
new file mode 100644 (file)
index 0000000..4844cc9
Binary files /dev/null and b/test-data/document/53446.doc differ
diff --git a/test-data/slideshow/53446.ppt b/test-data/slideshow/53446.ppt
new file mode 100644 (file)
index 0000000..55333fc
Binary files /dev/null and b/test-data/slideshow/53446.ppt differ
diff --git a/test-data/spreadsheet/53446.xls b/test-data/spreadsheet/53446.xls
new file mode 100644 (file)
index 0000000..b33bd7a
Binary files /dev/null and b/test-data/spreadsheet/53446.xls differ