]> source.dussan.org Git - poi.git/commitdiff
Regression fixes
authorAndreas Beeker <kiwiwings@apache.org>
Sun, 19 Jun 2016 22:43:24 +0000 (22:43 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sun, 19 Jun 2016 22:43:24 +0000 (22:43 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1749224 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java
src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java

index 73e45d5dba03c902f58327bff41cc08dd4edf0b2..c2df75f3b7df8836501717b7f80c6c32db8bd3a8 100644 (file)
@@ -30,8 +30,14 @@ import java.awt.image.RescaleOp;
 import java.io.ByteArrayInputStream;\r
 import java.io.IOException;\r
 import java.io.InputStream;\r
+import java.util.Iterator;\r
 \r
 import javax.imageio.ImageIO;\r
+import javax.imageio.ImageReadParam;\r
+import javax.imageio.ImageReader;\r
+import javax.imageio.ImageTypeSpecifier;\r
+import javax.imageio.stream.ImageInputStream;\r
+import javax.imageio.stream.MemoryCacheImageInputStream;\r
 \r
 import org.apache.poi.util.POILogFactory;\r
 import org.apache.poi.util.POILogger;\r
@@ -46,28 +52,92 @@ public class BitmapImageRenderer implements ImageRenderer {
 \r
     @Override\r
     public void loadImage(InputStream data, String contentType) throws IOException {\r
-        img = convertBufferedImage(ImageIO.read(data), contentType);\r
+        img = readImage(data, contentType);\r
     }\r
 \r
     @Override\r
     public void loadImage(byte data[], String contentType) throws IOException {\r
-        img = convertBufferedImage(ImageIO.read(new ByteArrayInputStream(data)), contentType);\r
+        img = readImage(new ByteArrayInputStream(data), contentType);\r
     }\r
-\r
+    \r
     /**\r
-     * Add alpha channel to buffered image\r
+     * Read the image data via ImageIO and optionally try to workaround metadata errors.\r
+     * The resulting image is of image image type {@link BufferedImage#TYPE_INT_ARGB}\r
+     *\r
+     * @param data the data stream\r
+     * @param contentType the content type\r
+     * @return the bufferedImage or null, if there was no image reader for this content type\r
+     * @throws IOException thrown if there was an error while processing the image\r
      */\r
-    private static BufferedImage convertBufferedImage(BufferedImage img, String contentType) {\r
+    private static BufferedImage readImage(InputStream data, String contentType) throws IOException {\r
+        IOException lastException = null;\r
+        BufferedImage img = null;\r
+        // currently don't use FileCacheImageInputStream,\r
+        // because of the risk of filling the file handles (see #59166)\r
+        ImageInputStream iis = new MemoryCacheImageInputStream(data);\r
+        try {\r
+            iis = new MemoryCacheImageInputStream(data);\r
+            iis.mark();\r
+            \r
+            Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);\r
+            while (img==null && iter.hasNext()) {\r
+                ImageReader reader = iter.next();\r
+                ImageReadParam param = reader.getDefaultReadParam();\r
+                // 0:default mode, 1:fallback mode\r
+                for (int mode=0; img==null && mode<2; mode++) {\r
+                    iis.reset();\r
+                    iis.mark();\r
+\r
+                    if (mode == 1) {\r
+                        // fallback mode for invalid image band metadata\r
+                        // see http://stackoverflow.com/questions/10416378\r
+                        Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0);\r
+                        while (imageTypes.hasNext()) {\r
+                            ImageTypeSpecifier imageTypeSpecifier = imageTypes.next();\r
+                            int bufferedImageType = imageTypeSpecifier.getBufferedImageType();\r
+                            if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) {\r
+                                param.setDestinationType(imageTypeSpecifier);\r
+                                break;\r
+                            }\r
+                        }\r
+                    }\r
+                    \r
+                    try {\r
+                        reader.setInput(iis, false, true);\r
+                        img = reader.read(0, param);\r
+                    } catch (IOException e) {\r
+                        lastException = e;\r
+                    } catch (RuntimeException e) {\r
+                        lastException = new IOException("ImageIO runtime exception - "+(mode==0 ? "normal" : "fallback"), e);\r
+                    }\r
+                }\r
+                reader.dispose();\r
+            }\r
+        } finally {\r
+            iis.close();\r
+        }\r
+        \r
+        // If you don't have an image at the end of all readers\r
         if (img == null) {\r
+            if (lastException != null) {\r
+                // rethrow exception - be aware that the exception source can be in\r
+                // multiple locations above ...\r
+                throw lastException;\r
+            }\r
             LOG.log(POILogger.WARN, "Content-type: "+contentType+" is not support. Image ignored.");\r
             return null;\r
         }\r
 \r
-        BufferedImage bi = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);\r
-        Graphics g = bi.getGraphics();\r
-        g.drawImage(img, 0, 0, null);\r
-        g.dispose();\r
-        return bi;\r
+        // add alpha channel\r
+        if (img.getType() != BufferedImage.TYPE_INT_ARGB) {\r
+            BufferedImage argbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);\r
+            Graphics g = argbImg.getGraphics();\r
+            g.drawImage(img, 0, 0, null);\r
+            g.dispose();\r
+            return argbImg;\r
+        }\r
+        \r
+        return img;\r
     }\r
 \r
     @Override\r
index 852865d035cec6c0910699bf15afd3e195ed0ab5..ef187de5ab0de65e352107e7645fef73f15ad5df 100644 (file)
@@ -140,15 +140,18 @@ public class CurrentUserAtom
                // See how long it is. If it's under 28 bytes long, we can't
                //  read it
                if(_contents.length < 28) {
-                       if(_contents.length >= 4) {
-                               // PPT95 has 4 byte size, then data
+                   boolean isPP95 = dir.hasEntry("PP40");
+                   // PPT95 has 4 byte size, then data
+                       if (!isPP95 && _contents.length >= 4) {
                                int size = LittleEndian.getInt(_contents);
-                               //System.err.println(size);
-                               if(size + 4 == _contents.length) {
-                                       throw new OldPowerPointFormatException("Based on the Current User stream, you seem to have supplied a PowerPoint95 file, which isn't supported");
-                               }
+                               isPP95 = (size + 4 == _contents.length);
+                       }
+
+                       if (isPP95) {
+                           throw new OldPowerPointFormatException("Based on the Current User stream, you seem to have supplied a PowerPoint95 file, which isn't supported");
+                       } else {
+                           throw new CorruptPowerPointFileException("The Current User stream must be at least 28 bytes long, but was only " + _contents.length);
                        }
-                       throw new CorruptPowerPointFileException("The Current User stream must be at least 28 bytes long, but was only " + _contents.length);
                }
 
                // Set everything up