diff options
Diffstat (limited to 'src/ooxml')
5 files changed, 154 insertions, 66 deletions
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java index 2cf4bda982..a327630ba8 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java @@ -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; } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java index e6fc0fd4ef..b2d407d231 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java @@ -19,24 +19,41 @@ 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 diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index 0dc14844ea..df352b57d0 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -19,12 +19,10 @@ package org.apache.poi.xslf.usermodel;
+import java.awt.Dimension;
import java.awt.Insets;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
+import java.awt.Rectangle;
import java.net.URI;
-
-import javax.imageio.ImageIO;
import javax.xml.namespace.QName;
import org.apache.poi.POIXMLException;
@@ -87,20 +85,23 @@ public class XSLFPictureShape extends XSLFSimpleShape /**
* 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 sets the default size to 200x200 pixels.
*/
public void resize() {
- try {
- BufferedImage img = ImageIO.read(getPictureData().getInputStream());
- setAnchor(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
+ Dimension dim = getPictureData().getImageDimension();
+ if (dim.width > 0 && dim.height > 0)
+ {
+ setAnchor(new Rectangle(0, 0, dim.width, dim.height));
}
- catch (Exception e) {
- //default size is 200x200
- setAnchor(new java.awt.Rectangle(50, 50, 200, 200));
+ else
+ {
+ // unsupported/unknown formats
+ setAnchor(new Rectangle(50, 50, 200, 200));
}
}
-
+
/**
* Is this an internal picture (image data included within
* the PowerPoint file), or an external linked picture
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java index cd78f6565e..0f1d14f4cb 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java @@ -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()); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java index 12dde34afe..b5acb85291 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFPictureShape.java @@ -36,44 +36,46 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; public class TestXSLFPictureShape {
@Test
- public void testCreate() {
- XMLSlideShow ppt = new XMLSlideShow();
- assertEquals(0, ppt.getAllPictures().size());
+ public void testCreate() throws Exception {
+ XMLSlideShow ppt1 = new XMLSlideShow();
+ assertEquals(0, ppt1.getPictureData().size());
byte[] data1 = new byte[100];
for(int i = 0;i < 100;i++) { data1[i] = (byte)i; }
- XSLFPictureData pdata1 = ppt.addPicture(data1, PictureType.JPEG);
+ XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG);
assertEquals(0, pdata1.getIndex());
- assertEquals(1, ppt.getAllPictures().size());
+ assertEquals(1, ppt1.getPictureData().size());
- XSLFSlide slide = ppt.createSlide();
+ XSLFSlide slide = ppt1.createSlide();
XSLFPictureShape shape1 = slide.createPicture(pdata1);
assertNotNull(shape1.getPictureData());
assertArrayEquals(data1, shape1.getPictureData().getData());
byte[] data2 = new byte[200];
for(int i = 0;i < 200;i++) { data2[i] = (byte)i; }
- XSLFPictureData pdata2 = ppt.addPicture(data2, PictureType.PNG);
+ XSLFPictureData pdata2 = ppt1.addPicture(data2, PictureType.PNG);
XSLFPictureShape shape2 = slide.createPicture(pdata2);
assertNotNull(shape2.getPictureData());
assertEquals(1, pdata2.getIndex());
- assertEquals(2, ppt.getAllPictures().size());
+ assertEquals(2, ppt1.getPictureData().size());
assertArrayEquals(data2, shape2.getPictureData().getData());
- ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);
- List<XSLFPictureData> pics = ppt.getAllPictures();
+ XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);
+ ppt1.close();
+ List<XSLFPictureData> pics = ppt2.getPictureData();
assertEquals(2, pics.size());
assertArrayEquals(data1, pics.get(0).getData());
assertArrayEquals(data2, pics.get(1).getData());
- List<XSLFShape> shapes = ppt.getSlides().get(0).getShapes();
+ List<XSLFShape> shapes = ppt2.getSlides().get(0).getShapes();
assertArrayEquals(data1, ((XSLFPictureShape) shapes.get(0)).getPictureData().getData());
assertArrayEquals(data2, ((XSLFPictureShape) shapes.get(1)).getPictureData().getData());
+ ppt2.close();
}
@Test
- public void testCreateMultiplePictures() {
- XMLSlideShow ppt = new XMLSlideShow();
- XSLFSlide slide1 = ppt.createSlide();
+ public void testCreateMultiplePictures() throws Exception {
+ XMLSlideShow ppt1 = new XMLSlideShow();
+ XSLFSlide slide1 = ppt1.createSlide();
XSLFGroupShape group1 = slide1.createGroup();
@@ -81,7 +83,7 @@ public class TestXSLFPictureShape { // first add 20 images to the slide
for (int i = 0; i < 20; i++, pictureIndex++) {
byte[] data = new byte[]{(byte)pictureIndex};
- XSLFPictureData elementData = ppt.addPicture(data, PictureType.PNG);
+ XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG);
assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19
XSLFPictureShape picture = slide1.createPicture(elementData);
// POI saves images as image1.png, image2.png, etc.
@@ -93,7 +95,7 @@ public class TestXSLFPictureShape { // and then add next 20 images to a group
for (int i = 0; i < 20; i++, pictureIndex++) {
byte[] data = new byte[]{(byte)pictureIndex};
- XSLFPictureData elementData = ppt.addPicture(data, PictureType.PNG);
+ XSLFPictureData elementData = ppt1.addPicture(data, PictureType.PNG);
XSLFPictureShape picture = group1.createPicture(elementData);
// POI saves images as image1.png, image2.png, etc.
assertEquals(pictureIndex, elementData.getIndex()); // added images have indexes 0,1,2....19
@@ -104,10 +106,11 @@ public class TestXSLFPictureShape { // serialize, read back and check that all images are there
- ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);
+ XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);
+ ppt1.close();
// pictures keyed by file name
Map<String, XSLFPictureData> pics = new HashMap<String, XSLFPictureData>();
- for(XSLFPictureData p : ppt.getAllPictures()){
+ for(XSLFPictureData p : ppt2.getPictureData()){
pics.put(p.getFileName(), p);
}
assertEquals(40, pics.size());
@@ -119,10 +122,11 @@ public class TestXSLFPictureShape { assertEquals(fileName, data.getFileName());
assertArrayEquals(data1, data.getData());
}
+ ppt2.close();
}
@Test
- public void testImageCaching() {
+ public void testImageCaching() throws Exception {
XMLSlideShow ppt = new XMLSlideShow();
byte[] img1 = new byte[]{1,2,3};
byte[] img2 = new byte[]{3,4,5};
@@ -139,10 +143,11 @@ public class TestXSLFPictureShape { XSLFSlide slide2 = ppt.createSlide();
assertNotNull(slide2);
+ ppt.close();
}
@Test
- public void testMerge() {
+ public void testMerge() throws Exception {
XMLSlideShow ppt1 = new XMLSlideShow();
byte[] data1 = new byte[100];
XSLFPictureData pdata1 = ppt1.addPicture(data1, PictureType.JPEG);
@@ -151,7 +156,7 @@ public class TestXSLFPictureShape { XSLFPictureShape shape1 = slide1.createPicture(pdata1);
CTPicture ctPic1 = (CTPicture)shape1.getXmlObject();
ctPic1.getNvPicPr().getNvPr().addNewCustDataLst().addNewTags().setId("rId99");
-
+
XMLSlideShow ppt2 = new XMLSlideShow();
XSLFSlide slide2 = ppt2.createSlide().importContent(slide1);
@@ -162,5 +167,7 @@ public class TestXSLFPictureShape { CTPicture ctPic2 = (CTPicture)shape2.getXmlObject();
assertFalse(ctPic2.getNvPicPr().getNvPr().isSetCustDataLst());
+ ppt1.close();
+ ppt2.close();
}
}
\ No newline at end of file |