diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java index ca13615b5c..b67c9fe419 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java @@ -19,16 +19,19 @@ package org.apache.poi.xslf.usermodel; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.util.Beta; - -import javax.imageio.ImageIO; import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; +import javax.imageio.ImageIO; + +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.util.Beta; + /** * For now this class renders only images supported by the javax.imageio.ImageIO * framework. Subclasses can override this class to support other formats, for @@ -72,17 +75,52 @@ public class XSLFImageRenderer { * * @return true if the picture data was successfully rendered */ - public boolean drawImage(Graphics2D graphics, XSLFPictureData data, - Rectangle2D anchor) { + public boolean drawImage(Graphics2D graphics, XSLFPictureData data, + Rectangle2D anchor) { + return drawImage(graphics, data, anchor, null); + } + + /** + * Render picture data into the supplied graphics + * + * @return true if the picture data was successfully rendered + */ + public boolean drawImage(Graphics2D graphics, XSLFPictureData data, + Rectangle2D anchor, Insets clip) { + boolean isClipped = true; + if (clip == null) { + isClipped = false; + clip = new Insets(0,0,0,0); + } + try { BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream()); - double sx = anchor.getWidth()/img.getWidth(); - double sy = anchor.getHeight()/img.getHeight(); - double tx = anchor.getX(); - double ty = anchor.getY(); + int iw = img.getWidth(); + int ih = img.getHeight(); + + double aw = anchor.getWidth(); + double ah = anchor.getHeight(); + double ax = anchor.getX(); + double ay = anchor.getY(); + + double cw = (100000-clip.left-clip.right) / 100000.0; + double ch = (100000-clip.top-clip.bottom) / 100000.0; + double sx = aw/(iw*cw); + double sy = ah/(ih*ch); + double tx = anchor.getX()-(iw*sx*clip.left/100000.0); + double ty = anchor.getY()-(ih*sy*clip.top/100000.0); AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; - graphics.drawRenderedImage(img, at); + if (isClipped) { + Shape clipOld = graphics.getClip(); + AffineTransform atClip = new AffineTransform(aw, 0, 0, ah, ax, ay); + Shape clipNew = atClip.createTransformedShape(new Rectangle2D.Double(0, 0, 1, 1)); + graphics.setClip(clipNew); + graphics.drawRenderedImage(img, at); + graphics.setClip(clipOld); + } else { + graphics.drawRenderedImage(img, at); + } return true; } catch (Exception e) { 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 43d151c66d..a7e7e5e815 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -20,6 +20,7 @@ package org.apache.poi.xslf.usermodel; import java.awt.Graphics2D; +import java.awt.Insets; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; @@ -40,6 +41,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension; import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList; import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect; import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; @@ -177,6 +179,12 @@ public class XSLFPictureShape extends XSLFSimpleShape { return id; } + public Insets getBlipClip(){ + CTPicture ct = (CTPicture)getXmlObject(); + CTRelativeRect r = ct.getBlipFill().getSrcRect(); + return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR()); + } + @Override public void drawContent(Graphics2D graphics) { @@ -188,8 +196,10 @@ public class XSLFPictureShape extends XSLFSimpleShape { RenderableShape rShape = new RenderableShape(this); Rectangle2D anchor = rShape.getAnchor(graphics); + + Insets insets = getBlipClip(); - renderer.drawImage(graphics, data, anchor); + renderer.drawImage(graphics, data, anchor, insets); } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java index 0e787ba569..bee3651432 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java @@ -16,10 +16,24 @@ ==================================================================== */ package org.apache.poi.xslf; +import static junit.framework.TestCase.assertEquals; +import static org.apache.poi.POITestCase.assertContains; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.File; import java.net.URI; import java.util.List; -import org.apache.poi.POITestCase; +import javax.imageio.ImageIO; + import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.xslf.usermodel.DrawingParagraph; @@ -31,11 +45,14 @@ import org.apache.poi.xslf.usermodel.XSLFRelation; import org.apache.poi.xslf.usermodel.XSLFShape; import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.poi.xslf.usermodel.XSLFSlideLayout; +import org.junit.Ignore; +import org.junit.Test; -public class TestXSLFBugs extends POITestCase { +public class TestXSLFBugs { + @Test @SuppressWarnings("deprecation") - public void test51187() throws Exception { + public void bug51187() throws Exception { XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("51187.pptx"); assertEquals(1, ss.getSlides().length); @@ -70,7 +87,8 @@ public class TestXSLFBugs extends POITestCase { /** * Slide relations with anchors in them */ - public void testTIKA705() { + @Test + public void tika705() { XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx"); // Should have one slide @@ -117,7 +135,9 @@ public class TestXSLFBugs extends POITestCase { * slide, eg presentation.xml rID1 -> slide1.xml, but slide1.xml * rID2 -> slide3.xml */ - public void DISABLEDtest54916() throws Exception { + @Test + @Ignore + public void bug54916() throws Exception { XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("OverlappingRelations.pptx"); XSLFSlide slide; @@ -144,7 +164,8 @@ public class TestXSLFBugs extends POITestCase { * there is no data available and XSLFPictureShape.getPictureData() * gives a NPE, see bug #56812 */ - public void test56812() throws Exception { + @Test + public void bug56812() throws Exception { XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("56812.pptx"); int internalPictures = 0; @@ -173,6 +194,34 @@ public class TestXSLFBugs extends POITestCase { assertEquals(2, internalPictures); assertEquals(1, externalPictures); } + + @Test + @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix") + public void bug54542() throws Exception { + XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("54542_cropped_bitmap.pptx"); + + Dimension pgsize = ss.getPageSize(); + + XSLFSlide slide = ss.getSlides()[0]; + + // render it + double zoom = 1; + AffineTransform at = new AffineTransform(); + at.setToScale(zoom, zoom); + + BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR); + Graphics2D graphics = imgActual.createGraphics(); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + graphics.setTransform(at); + graphics.setPaint(Color.white); + graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height)); + slide.draw(graphics); + + ImageIO.write(imgActual, "PNG", new File("bug54542.png")); + } protected String getSlideText(XSLFSlide slide) { StringBuffer text = new StringBuffer(); diff --git a/test-data/slideshow/54542_cropped_bitmap.pptx b/test-data/slideshow/54542_cropped_bitmap.pptx new file mode 100644 index 0000000000..eb3e2339a3 Binary files /dev/null and b/test-data/slideshow/54542_cropped_bitmap.pptx differ