Bug 54542 - Add support for cropped images in XSLFPictureShape.drawContent()
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1634410 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f818d1fdb7
commit
2ff41d7acd
@ -19,16 +19,19 @@
|
|||||||
|
|
||||||
package org.apache.poi.xslf.usermodel;
|
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.Graphics2D;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.Shape;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
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
|
* For now this class renders only images supported by the javax.imageio.ImageIO
|
||||||
* framework. Subclasses can override this class to support other formats, for
|
* 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
|
* @return true if the picture data was successfully rendered
|
||||||
*/
|
*/
|
||||||
public boolean drawImage(Graphics2D graphics, XSLFPictureData data,
|
public boolean drawImage(Graphics2D graphics, XSLFPictureData data,
|
||||||
Rectangle2D anchor) {
|
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 {
|
try {
|
||||||
BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream());
|
BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream());
|
||||||
double sx = anchor.getWidth()/img.getWidth();
|
int iw = img.getWidth();
|
||||||
double sy = anchor.getHeight()/img.getHeight();
|
int ih = img.getHeight();
|
||||||
double tx = anchor.getX();
|
|
||||||
double ty = anchor.getY();
|
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) ;
|
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;
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
package org.apache.poi.xslf.usermodel;
|
package org.apache.poi.xslf.usermodel;
|
||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Insets;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
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.CTOfficeArtExtension;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
|
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.CTShapeProperties;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
|
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;
|
||||||
@ -177,6 +179,12 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||||||
return id;
|
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
|
@Override
|
||||||
public void drawContent(Graphics2D graphics) {
|
public void drawContent(Graphics2D graphics) {
|
||||||
|
|
||||||
@ -188,8 +196,10 @@ public class XSLFPictureShape extends XSLFSimpleShape {
|
|||||||
|
|
||||||
RenderableShape rShape = new RenderableShape(this);
|
RenderableShape rShape = new RenderableShape(this);
|
||||||
Rectangle2D anchor = rShape.getAnchor(graphics);
|
Rectangle2D anchor = rShape.getAnchor(graphics);
|
||||||
|
|
||||||
|
Insets insets = getBlipClip();
|
||||||
|
|
||||||
renderer.drawImage(graphics, data, anchor);
|
renderer.drawImage(graphics, data, anchor, insets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,10 +16,24 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.xslf;
|
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.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.POITestCase;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import org.apache.poi.POIXMLDocumentPart;
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
import org.apache.poi.openxml4j.opc.PackagePart;
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
import org.apache.poi.xslf.usermodel.DrawingParagraph;
|
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.XSLFShape;
|
||||||
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
||||||
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
|
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")
|
@SuppressWarnings("deprecation")
|
||||||
public void test51187() throws Exception {
|
public void bug51187() throws Exception {
|
||||||
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("51187.pptx");
|
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("51187.pptx");
|
||||||
|
|
||||||
assertEquals(1, ss.getSlides().length);
|
assertEquals(1, ss.getSlides().length);
|
||||||
@ -70,7 +87,8 @@ public class TestXSLFBugs extends POITestCase {
|
|||||||
/**
|
/**
|
||||||
* Slide relations with anchors in them
|
* Slide relations with anchors in them
|
||||||
*/
|
*/
|
||||||
public void testTIKA705() {
|
@Test
|
||||||
|
public void tika705() {
|
||||||
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx");
|
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx");
|
||||||
|
|
||||||
// Should have one slide
|
// Should have one slide
|
||||||
@ -117,7 +135,9 @@ public class TestXSLFBugs extends POITestCase {
|
|||||||
* slide, eg presentation.xml rID1 -> slide1.xml, but slide1.xml
|
* slide, eg presentation.xml rID1 -> slide1.xml, but slide1.xml
|
||||||
* rID2 -> slide3.xml
|
* rID2 -> slide3.xml
|
||||||
*/
|
*/
|
||||||
public void DISABLEDtest54916() throws Exception {
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void bug54916() throws Exception {
|
||||||
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("OverlappingRelations.pptx");
|
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("OverlappingRelations.pptx");
|
||||||
XSLFSlide slide;
|
XSLFSlide slide;
|
||||||
|
|
||||||
@ -144,7 +164,8 @@ public class TestXSLFBugs extends POITestCase {
|
|||||||
* there is no data available and XSLFPictureShape.getPictureData()
|
* there is no data available and XSLFPictureShape.getPictureData()
|
||||||
* gives a NPE, see bug #56812
|
* gives a NPE, see bug #56812
|
||||||
*/
|
*/
|
||||||
public void test56812() throws Exception {
|
@Test
|
||||||
|
public void bug56812() throws Exception {
|
||||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("56812.pptx");
|
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("56812.pptx");
|
||||||
|
|
||||||
int internalPictures = 0;
|
int internalPictures = 0;
|
||||||
@ -173,6 +194,34 @@ public class TestXSLFBugs extends POITestCase {
|
|||||||
assertEquals(2, internalPictures);
|
assertEquals(2, internalPictures);
|
||||||
assertEquals(1, externalPictures);
|
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) {
|
protected String getSlideText(XSLFSlide slide) {
|
||||||
StringBuffer text = new StringBuffer();
|
StringBuffer text = new StringBuffer();
|
||||||
|
BIN
test-data/slideshow/54542_cropped_bitmap.pptx
Normal file
BIN
test-data/slideshow/54542_cropped_bitmap.pptx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user