You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/06/19 22:43:25 UTC

svn commit: r1749224 - in /poi/trunk/src: java/org/apache/poi/sl/draw/BitmapImageRenderer.java scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java

Author: kiwiwings
Date: Sun Jun 19 22:43:24 2016
New Revision: 1749224

URL: http://svn.apache.org/viewvc?rev=1749224&view=rev
Log:
Regression fixes

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

Modified: poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java?rev=1749224&r1=1749223&r2=1749224&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java Sun Jun 19 22:43:24 2016
@@ -30,8 +30,14 @@ import java.awt.image.RescaleOp;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Iterator;
 
 import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
 
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -46,28 +52,92 @@ public class BitmapImageRenderer impleme
 
     @Override
     public void loadImage(InputStream data, String contentType) throws IOException {
-        img = convertBufferedImage(ImageIO.read(data), contentType);
+        img = readImage(data, contentType);
     }
 
     @Override
     public void loadImage(byte data[], String contentType) throws IOException {
-        img = convertBufferedImage(ImageIO.read(new ByteArrayInputStream(data)), contentType);
+        img = readImage(new ByteArrayInputStream(data), contentType);
     }
-
+    
     /**
-     * Add alpha channel to buffered image
+     * Read the image data via ImageIO and optionally try to workaround metadata errors.
+     * The resulting image is of image image type {@link BufferedImage#TYPE_INT_ARGB}
+     *
+     * @param data the data stream
+     * @param contentType the content type
+     * @return the bufferedImage or null, if there was no image reader for this content type
+     * @throws IOException thrown if there was an error while processing the image
      */
-    private static BufferedImage convertBufferedImage(BufferedImage img, String contentType) {
+    private static BufferedImage readImage(InputStream data, String contentType) throws IOException {
+        IOException lastException = null;
+        BufferedImage img = null;
+        // currently don't use FileCacheImageInputStream,
+        // because of the risk of filling the file handles (see #59166)
+        ImageInputStream iis = new MemoryCacheImageInputStream(data);
+        try {
+            iis = new MemoryCacheImageInputStream(data);
+            iis.mark();
+            
+            Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
+            while (img==null && iter.hasNext()) {
+                ImageReader reader = iter.next();
+                ImageReadParam param = reader.getDefaultReadParam();
+                // 0:default mode, 1:fallback mode
+                for (int mode=0; img==null && mode<2; mode++) {
+                    iis.reset();
+                    iis.mark();
+
+                    if (mode == 1) {
+                        // fallback mode for invalid image band metadata
+                        // see http://stackoverflow.com/questions/10416378
+                        Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0);
+                        while (imageTypes.hasNext()) {
+                            ImageTypeSpecifier imageTypeSpecifier = imageTypes.next();
+                            int bufferedImageType = imageTypeSpecifier.getBufferedImageType();
+                            if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) {
+                                param.setDestinationType(imageTypeSpecifier);
+                                break;
+                            }
+                        }
+                    }
+                    
+                    try {
+                        reader.setInput(iis, false, true);
+                        img = reader.read(0, param);
+                    } catch (IOException e) {
+                        lastException = e;
+                    } catch (RuntimeException e) {
+                        lastException = new IOException("ImageIO runtime exception - "+(mode==0 ? "normal" : "fallback"), e);
+                    }
+                }
+                reader.dispose();
+            }
+        } finally {
+            iis.close();
+        }
+        
+        // If you don't have an image at the end of all readers
         if (img == null) {
+            if (lastException != null) {
+                // rethrow exception - be aware that the exception source can be in
+                // multiple locations above ...
+                throw lastException;
+            }
             LOG.log(POILogger.WARN, "Content-type: "+contentType+" is not support. Image ignored.");
             return null;
         }
 
-        BufferedImage bi = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
-        Graphics g = bi.getGraphics();
-        g.drawImage(img, 0, 0, null);
-        g.dispose();
-        return bi;
+        // add alpha channel
+        if (img.getType() != BufferedImage.TYPE_INT_ARGB) {
+            BufferedImage argbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
+            Graphics g = argbImg.getGraphics();
+            g.drawImage(img, 0, 0, null);
+            g.dispose();
+            return argbImg;
+        }
+        
+        return img;
     }
 
     @Override

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java?rev=1749224&r1=1749223&r2=1749224&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java Sun Jun 19 22:43:24 2016
@@ -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



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org