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/11/28 20:51:02 UTC

svn commit: r1771812 - in /poi: site/src/documentation/content/xdocs/ trunk/src/java/org/apache/poi/sl/image/ trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/ trunk/src/scratchpad/src/org/apache/poi/hslf/blip/ trunk/src/scratchpad/testcases/org/apac...

Author: kiwiwings
Date: Mon Nov 28 20:51:02 2016
New Revision: 1771812

URL: http://svn.apache.org/viewvc?rev=1771812&view=rev
Log:
#60427 - Creating pictures in PowerPoint slides requires scratchpad-jar for adding WMF images

Added:
    poi/trunk/src/java/org/apache/poi/sl/image/
    poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java   (with props)
    poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderEMF.java   (with props)
    poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderPICT.java   (with props)
    poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderWMF.java   (with props)
Modified:
    poi/site/src/documentation/content/xdocs/status.xml
    poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java

Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1771812&r1=1771811&r2=1771812&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Mon Nov 28 20:51:02 2016
@@ -58,6 +58,7 @@
 
     <release version="3.16-beta2" date="2017-02-??">
       <actions>
+        <action dev="PD" type="fix" fixes-bug="60427" module="XSLF">Creating pictures in PowerPoint slides requires scratchpad-jar for adding WMF images</action>
         <action dev="PD" type="fix" fixes-bug="60331" module="HPSF">Remove deprecated classes - deprecate Mutable* property classes</action>
         <action dev="PD" type="fix" fixes-bug="59200" module="SS Common">Check for actual Excel limits on data validation title/text</action>
         <action dev="PD" type="fix" fixes-bug="60373" module="XSLF">TableCell.getTextHeight() returns NullPointerException</action>

Added: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java?rev=1771812&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java (added)
+++ poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java Mon Nov 28 20:51:02 2016
@@ -0,0 +1,57 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.sl.image;
+
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.Units;
+
+@Internal
+public class ImageHeaderBitmap {
+    private static final POILogger LOG = POILogFactory.getLogger(ImageHeaderBitmap.class);
+    
+    private final Dimension size;
+    
+    public ImageHeaderBitmap(byte data[], int offset) {
+        BufferedImage img = null;
+        try {
+            img = ImageIO.read(new ByteArrayInputStream(data, offset, data.length-offset));
+        } catch (IOException e) {
+            LOG.log(POILogger.WARN, "Can't determine image dimensions", e);
+        }
+        // set dummy size, in case of dummy dimension can't be set
+        size = (img == null)
+            ? new Dimension(200,200)
+            : new Dimension(
+                (int)Units.pixelToPoints(img.getWidth()),
+                (int)Units.pixelToPoints(img.getHeight())
+            );
+    }
+
+    public Dimension getSize() {
+        return size;
+    }
+}

Propchange: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderBitmap.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderEMF.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderEMF.java?rev=1771812&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderEMF.java (added)
+++ poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderEMF.java Mon Nov 28 20:51:02 2016
@@ -0,0 +1,68 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.sl.image;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LocaleUtil;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+@Internal
+public class ImageHeaderEMF {
+    private static POILogger LOG = POILogFactory.getLogger(ImageHeaderEMF.class);
+
+    private final static String EMF_SIGNATURE = " EMF"; // 0x464D4520 (LE)
+    
+    // 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;
+
+    public ImageHeaderEMF(byte data[], int offset) {
+        int type = (int)LittleEndian.getUInt(data, offset); offset += 4;
+        if (type != 1) {
+            LOG.log(POILogger.WARN, "Invalid EMF picture - invalid type");
+            deviceBounds = new Rectangle(0,0,200,200);
+            return;
+        }
+        // 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)) {
+            LOG.log(POILogger.WARN, "Invalid EMF picture - invalid signature");
+        }
+    }
+
+    public Dimension getSize() {
+        return deviceBounds.getSize();
+    }
+    
+    public Rectangle getBounds() {
+        return deviceBounds;
+    }
+}
\ No newline at end of file

Propchange: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderEMF.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderPICT.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderPICT.java?rev=1771812&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderPICT.java (added)
+++ poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderPICT.java Mon Nov 28 20:51:02 2016
@@ -0,0 +1,103 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.sl.image;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.Units;
+
+@Internal
+public class ImageHeaderPICT {
+    /**
+     * 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
+    };
+
+    private final Rectangle bounds;
+    private final double hRes, vRes;
+    
+    public ImageHeaderPICT(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);
+    }
+
+    public Rectangle getBounds() {
+        return bounds;
+    }
+    
+    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;
+    }
+}

Propchange: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderPICT.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderWMF.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderWMF.java?rev=1771812&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderWMF.java (added)
+++ poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderWMF.java Mon Nov 28 20:51:02 2016
@@ -0,0 +1,154 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.sl.image;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.Units;
+
+/**
+ * Aldus Placeable Metafile header - 22 byte structure before WMF data.
+ * <ul>
+ *  <li>int Key;               Magic number (always 9AC6CDD7h)
+ *  <li>short  Handle;         Metafile HANDLE number (always 0)
+ *  <li>short Left;            Left coordinate in metafile units
+ *  <li>short Top;             Top coordinate in metafile units
+ *  <li>short Right;           Right coordinate in metafile units
+ *  <li>short Bottom;          Bottom coordinate in metafile units
+ *  <li>short  Inch;           Number of metafile units per inch
+ *  <li>int Reserved;          Reserved (always 0)
+ *  <li>short  Checksum;       Checksum value for previous 10 shorts
+ * </ul>
+ */
+@Internal
+public class ImageHeaderWMF {
+
+    public static final int APMHEADER_KEY = 0x9AC6CDD7;
+    private static POILogger LOG = POILogFactory.getLogger(ImageHeaderWMF.class);
+
+    @SuppressWarnings("unused")
+    private final int handle;
+    private final int left, top, right, bottom;
+
+    /**
+     * 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; 
+    @SuppressWarnings("unused")
+    private final int reserved;
+    private int checksum;
+    
+    public ImageHeaderWMF(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 ImageHeaderWMF(byte[] data, int pos) {
+        int key = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE; //header key
+        if (key != APMHEADER_KEY) {
+            LOG.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.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;
+
+        checksum = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
+        if (checksum != getChecksum()){
+            LOG.log(POILogger.WARN, "WMF checksum does not match the header data");
+        }
+    }
+
+    /**
+     * Returns a checksum value for the previous 10 shorts in the header.
+     * The checksum is calculated by XORing each short value to an initial value of 0:
+     */
+    public int getChecksum(){
+        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 {
+        byte[] header = new byte[22];
+        int pos = 0;
+        LittleEndian.putInt(header, pos, APMHEADER_KEY); pos += LittleEndian.INT_SIZE; //header key
+        LittleEndian.putUShort(header, pos, 0); pos += LittleEndian.SHORT_SIZE; //hmf
+        LittleEndian.putUShort(header, pos, left); pos += LittleEndian.SHORT_SIZE; //left
+        LittleEndian.putUShort(header, pos, top); pos += LittleEndian.SHORT_SIZE; //top
+        LittleEndian.putUShort(header, pos, right); pos += LittleEndian.SHORT_SIZE; //right
+        LittleEndian.putUShort(header, pos, bottom); pos += LittleEndian.SHORT_SIZE; //bottom
+        LittleEndian.putUShort(header, pos, inch); pos += LittleEndian.SHORT_SIZE; //inch
+        LittleEndian.putInt(header, pos, 0); pos += LittleEndian.INT_SIZE;  //reserved
+
+        checksum = getChecksum();
+        LittleEndian.putUShort(header, pos, checksum);
+
+        out.write(header);
+    }
+
+    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 Rectangle getBounds() {
+        return new Rectangle(left, top, right-left, bottom-top);
+    }
+    
+    public int getLength(){
+        return 22;
+    }
+}

Propchange: poi/trunk/src/java/org/apache/poi/sl/image/ImageHeaderWMF.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java?rev=1771812&r1=1771811&r2=1771812&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java Mon Nov 28 20:51:02 2016
@@ -20,28 +20,23 @@
 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.image.ImageHeaderBitmap;
+import org.apache.poi.sl.image.ImageHeaderEMF;
+import org.apache.poi.sl.image.ImageHeaderPICT;
+import org.apache.poi.sl.image.ImageHeaderWMF;
 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;
 import org.apache.poi.util.Units;
 
 /**
@@ -49,8 +44,6 @@ import org.apache.poi.util.Units;
  */
 @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)
@@ -171,30 +164,18 @@ public final class XSLFPictureData exten
             
             switch (pt) {
             case EMF:
-                origSize = new EMF.NativeHeader(data, 0).getSize();
+                origSize = new ImageHeaderEMF(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();
+                origSize = new ImageHeaderWMF(data, 0).getSize();
                 break;
             case PICT:
-                origSize = new PICT.NativeHeader(data, 0).getSize();
+                origSize = new ImageHeaderPICT(data, 0).getSize();
                 break;
             default:
-                BufferedImage img = null;
-                try {
-                    img = ImageIO.read(new ByteArrayInputStream(data));
-                } catch (IOException e) {
-                    logger.log(POILogger.WARN, "Can't determine image dimensions", e);
-                }
-                // set dummy size, in case of dummy dimension can't be set
-                origSize = (img == null)
-                    ? new Dimension(200,200)
-                    : new Dimension(
-                        (int)Units.pixelToPoints(img.getWidth()),
-                        (int)Units.pixelToPoints(img.getHeight())
-                    );
+                origSize = new ImageHeaderBitmap(data, 0).getSize();
                 break;
             }
         }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java?rev=1771812&r1=1771811&r2=1771812&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java Mon Nov 28 20:51:02 2016
@@ -18,7 +18,6 @@
 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,8 +25,7 @@ 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.sl.image.ImageHeaderEMF;
 import org.apache.poi.util.Units;
 
 /**
@@ -35,38 +33,6 @@ 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 {
@@ -96,11 +62,11 @@ 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);
+        ImageHeaderEMF nHeader = new ImageHeaderEMF(data, 0);
         
         Header header = new Header();
         header.wmfsize = data.length;
-        header.bounds = nHeader.deviceBounds;
+        header.bounds = nHeader.getBounds();
         Dimension nDim = nHeader.getSize();
         header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
         header.zipsize = compressed.length;

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java?rev=1771812&r1=1771811&r2=1771812&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java Mon Nov 28 20:51:02 2016
@@ -18,13 +18,13 @@
 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;
 import java.util.zip.InflaterInputStream;
 
 import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.sl.image.ImageHeaderPICT;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.Units;
@@ -35,79 +35,6 @@ import org.apache.poi.util.Units;
 public final class PICT extends Metafile {
     private static final POILogger LOG = POILogFactory.getLogger(PICT.class);
     
-    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(){
@@ -163,14 +90,14 @@ public final class PICT extends Metafile
     @Override
     public void setData(byte[] data) throws IOException {
         // skip the first 512 bytes - they are MAC specific crap
-        final int nOffset = NativeHeader.PICT_HEADER_OFFSET;
-        NativeHeader nHeader = new NativeHeader(data, nOffset);
+        final int nOffset = ImageHeaderPICT.PICT_HEADER_OFFSET;
+        ImageHeaderPICT nHeader = new ImageHeaderPICT(data, nOffset);
         
         Header header = new Header();
         header.wmfsize = data.length - nOffset;
         byte[] compressed = compress(data, nOffset, header.wmfsize);
         header.zipsize = compressed.length;
-        header.bounds = nHeader.bounds;
+        header.bounds = nHeader.getBounds();
         Dimension nDim = nHeader.getSize();
         header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
 

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java?rev=1771812&r1=1771811&r2=1771812&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java Mon Nov 28 20:51:02 2016
@@ -18,18 +18,14 @@
 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;
 import java.io.InputStream;
-import java.io.OutputStream;
 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.sl.image.ImageHeaderWMF;
 import org.apache.poi.util.Units;
 
 /**
@@ -49,7 +45,7 @@ public final class WMF extends Metafile
             long len = is.skip(header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
             assert(len == header.getSize() + CHECKSUM_SIZE*uidInstanceCount);
 
-            NativeHeader aldus = new NativeHeader(header.bounds);
+            ImageHeaderWMF aldus = new ImageHeaderWMF(header.bounds);
             aldus.write(out);
 
             InflaterInputStream inflater = new InflaterInputStream( is );
@@ -68,14 +64,14 @@ public final class WMF extends Metafile
     @Override
     public void setData(byte[] data) throws IOException {
         int pos = 0;
-        NativeHeader nHeader = new NativeHeader(data, pos);
+        ImageHeaderWMF nHeader = new ImageHeaderWMF(data, pos);
         pos += nHeader.getLength();
 
         byte[] compressed = compress(data, pos, data.length-pos);
 
         Header header = new Header();
         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);
+        header.bounds = nHeader.getBounds();
         Dimension nDim = nHeader.getSize();
         header.size = new Dimension(Units.toEMU(nDim.getWidth()), Units.toEMU(nDim.getHeight()));
         header.zipsize = compressed.length;
@@ -118,122 +114,4 @@ public final class WMF extends Metafile
                 throw new IllegalArgumentException(signature+" is not a valid instance/signature value for WMF");
         }
     }
-
-    /**
-     * Aldus Placeable Metafile header - 22 byte structure before WMF data.
-     * <ul>
-     *  <li>int Key;               Magic number (always 9AC6CDD7h)
-     *  <li>short  Handle;         Metafile HANDLE number (always 0)
-     *  <li>short Left;            Left coordinate in metafile units
-     *  <li>short Top;             Top coordinate in metafile units
-     *  <li>short Right;           Right coordinate in metafile units
-     *  <li>short Bottom;          Bottom coordinate in metafile units
-     *  <li>short  Inch;           Number of metafile units per inch
-     *  <li>int Reserved;          Reserved (always 0)
-     *  <li>short  Checksum;       Checksum value for previous 10 shorts
-     * </ul>
-     */
-    @SuppressWarnings("unused")
-    public static class NativeHeader {
-        public static final int APMHEADER_KEY = 0x9AC6CDD7;
-        private static POILogger logger = POILogFactory.getLogger(NativeHeader.class);
-
-        private final int handle;
-        private final int left, top, right, bottom;
-
-        /**
-         * 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) {
-                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.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;
-
-            checksum = LittleEndian.getShort(data, pos); pos += LittleEndian.SHORT_SIZE;
-            if (checksum != getChecksum()){
-                logger.log(POILogger.WARN, "WMF checksum does not match the header data");
-            }
-        }
-
-        /**
-         * Returns a checksum value for the previous 10 shorts in the header.
-         * The checksum is calculated by XORing each short value to an initial value of 0:
-         */
-        public int getChecksum(){
-            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 {
-            byte[] header = new byte[22];
-            int pos = 0;
-            LittleEndian.putInt(header, pos, APMHEADER_KEY); pos += LittleEndian.INT_SIZE; //header key
-            LittleEndian.putUShort(header, pos, 0); pos += LittleEndian.SHORT_SIZE; //hmf
-            LittleEndian.putUShort(header, pos, left); pos += LittleEndian.SHORT_SIZE; //left
-            LittleEndian.putUShort(header, pos, top); pos += LittleEndian.SHORT_SIZE; //top
-            LittleEndian.putUShort(header, pos, right); pos += LittleEndian.SHORT_SIZE; //right
-            LittleEndian.putUShort(header, pos, bottom); pos += LittleEndian.SHORT_SIZE; //bottom
-            LittleEndian.putUShort(header, pos, inch); pos += LittleEndian.SHORT_SIZE; //inch
-            LittleEndian.putInt(header, pos, 0); pos += LittleEndian.INT_SIZE;  //reserved
-
-            checksum = getChecksum();
-            LittleEndian.putUShort(header, pos, checksum);
-
-            out.write(header);
-        }
-
-        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;
-        }
-    }
 }

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java?rev=1771812&r1=1771811&r2=1771812&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java Mon Nov 28 20:51:02 2016
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertTru
 import java.awt.Dimension;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.net.URL;
 import java.util.List;
 
@@ -34,6 +35,9 @@ 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.image.ImageHeaderEMF;
+import org.apache.poi.sl.image.ImageHeaderPICT;
+import org.apache.poi.sl.image.ImageHeaderWMF;
 import org.apache.poi.sl.usermodel.PictureData.PictureType;
 import org.apache.poi.util.Units;
 import org.junit.Ignore;
@@ -51,13 +55,13 @@ public final class TestPictures {
      * Test read/write Macintosh PICT
      */
     @Test
-    public void testPICT() throws Exception {
+    public void testPICT() throws IOException {
         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);
+        ImageHeaderPICT nHeader = new ImageHeaderPICT(src_bytes, 512);
         final int expWidth = 197, expHeight = 137;
         Dimension nDim = nHeader.getSize();
         assertEquals(expWidth, nDim.getWidth(), 0);
@@ -114,13 +118,13 @@ public final class TestPictures {
      * Test read/write WMF
      */
     @Test
-    public void testWMF() throws Exception {
+    public void testWMF() throws IOException {
         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);
+        ImageHeaderWMF nHeader = new ImageHeaderWMF(src_bytes, 0);
         final int expWidth = 136, expHeight = 146;
         Dimension nDim = nHeader.getSize();
         assertEquals(expWidth, nDim.getWidth(), 0);
@@ -176,13 +180,13 @@ public final class TestPictures {
      * Test read/write EMF
      */
     @Test
-    public void testEMF() throws Exception {
+    public void testEMF() throws IOException {
         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);
+        ImageHeaderEMF nHeader = new ImageHeaderEMF(src_bytes, 0);
         final int expWidth = 190, expHeight = 115;
         Dimension nDim = nHeader.getSize();
         assertEquals(expWidth, nDim.getWidth(), 0);
@@ -233,7 +237,7 @@ public final class TestPictures {
      * Test read/write PNG
      */
     @Test
-    public void testPNG() throws Exception {
+    public void testPNG() throws IOException {
         HSLFSlideShow ppt = new HSLFSlideShow();
 
         HSLFSlide slide = ppt.createSlide();
@@ -273,7 +277,7 @@ public final class TestPictures {
      * Test read/write JPEG
      */
     @Test
-    public void testJPEG() throws Exception {
+    public void testJPEG() throws IOException {
         HSLFSlideShow ppt = new HSLFSlideShow();
 
         HSLFSlide slide = ppt.createSlide();
@@ -314,7 +318,7 @@ public final class TestPictures {
      * Test read/write DIB
      */
     @Test
-    public void testDIB() throws Exception {
+    public void testDIB() throws IOException {
         HSLFSlideShow ppt = new HSLFSlideShow();
 
         HSLFSlide slide = ppt.createSlide();
@@ -354,7 +358,7 @@ public final class TestPictures {
      * Read pictures in different formats from a reference slide show
      */
     @Test
-    public void testReadPictures() throws Exception {
+    public void testReadPictures() throws IOException {
 
         byte[] src_bytes, ppt_bytes, b1, b2;
         HSLFPictureShape pict;
@@ -417,6 +421,7 @@ public final class TestPictures {
         ppt_bytes = slTests.readFile("wrench.emf");
         assertArrayEquals(src_bytes, ppt_bytes);
 
+        ppt.close();
     }
 
 	/**
@@ -424,7 +429,7 @@ public final class TestPictures {
 	 *  crazy pictures of type 0, we do our best.
 	 */
     @Test
-	public void testZeroPictureType() throws Exception {
+	public void testZeroPictureType() throws IOException {
 		HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"));
 
 		// Should still have 2 real pictures
@@ -452,6 +457,8 @@ public final class TestPictures {
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof WMF);
         assertEquals(PictureType.WMF, pdata.getType());
+        
+        ppt.close();
 	}
 
     /**
@@ -460,7 +467,7 @@ public final class TestPictures {
      */
     @Test
     @Ignore
-	public void testZeroPictureLength() throws Exception {
+	public void testZeroPictureLength() throws IOException {
         // 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());
@@ -504,19 +511,21 @@ public final class TestPictures {
         assertEquals(streamSize, offset);
         assertEquals(3, ppt.getPictureData().size());
 
+        ppt.close();
     }
 
     @Test
-    public void testGetPictureName() throws Exception {
+    public void testGetPictureName() throws IOException {
         HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt"));
         HSLFSlide slide = ppt.getSlides().get(0);
 
         HSLFPictureShape p = (HSLFPictureShape)slide.getShapes().get(0); //the first slide contains JPEG
         assertEquals("test", p.getPictureName());
+        ppt.close();
     }
 
     @Test
-    public void testSetPictureName() throws Exception {
+    public void testSetPictureName() throws IOException {
         HSLFSlideShow ppt = new HSLFSlideShow();
 
         HSLFSlide slide = ppt.createSlide();




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