From 06705460473fe1d911d29f264b9ac505d5111fbf Mon Sep 17 00:00:00 2001 From: Christian Maierhofer Date: Mon, 13 Jun 2016 13:17:30 +0200 Subject: Modified sig-block positioning to image-based --- .../at/gv/egiz/pdfas/lib/api/PdfAsFactory.java | 8 + pdf-as-pdfbox-2/build.gradle | 3 +- .../egiz/pdfas/lib/impl/pdfbox2/PDFBOXObject.java | 14 +- .../lib/impl/pdfbox2/positioning/Positioning.java | 18 +- .../pdfbox2/positioning/PositioningPageDrawer.java | 68 ++++++++ .../pdfbox2/positioning/PositioningRenderer.java | 22 +++ .../wag/egov/egiz/pdfbox2/pdf/PDFUtilities.java | 181 +++++++++++++++------ 7 files changed, 258 insertions(+), 56 deletions(-) create mode 100644 pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningPageDrawer.java create mode 100644 pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningRenderer.java diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java index d47b05fa..cd0a4699 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java @@ -26,6 +26,8 @@ package at.gv.egiz.pdfas.lib.api; import iaik.security.ec.provider.ECCelerate; import iaik.security.provider.IAIK; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -175,6 +177,7 @@ public class PdfAsFactory implements IConfigurationConstants { synchronized (init_mutex) { if (!initialized) { initialized = true; + registerGraphicsEnvironment(); registerSecurityProvider(configuration); teeInformation("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); teeInformation("+ PDF-AS: " + getVersion()); @@ -188,6 +191,11 @@ public class PdfAsFactory implements IConfigurationConstants { } } } + + private static void registerGraphicsEnvironment(){ + BufferedImage bim = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = bim.createGraphics(); + } /** * Create a new instance of PDF-AS diff --git a/pdf-as-pdfbox-2/build.gradle b/pdf-as-pdfbox-2/build.gradle index 2a6248fa..4fe4b427 100644 --- a/pdf-as-pdfbox-2/build.gradle +++ b/pdf-as-pdfbox-2/build.gradle @@ -23,7 +23,8 @@ dependencies { compile project (':pdf-as-lib') compile group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion compile 'org.slf4j:jcl-over-slf4j:1.7.18' - compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.1' + compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.2' + compile group: 'org.apache.pdfbox', name: 'pdfbox-tools', version: '2.0.2' compile group: 'commons-io', name: 'commons-io', version: '2.4' compile group: 'ognl', name: 'ognl', version: '3.0.6' testCompile group: 'junit', name: 'junit', version: '4.+' diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/PDFBOXObject.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/PDFBOXObject.java index 0eee4cd3..e380e483 100644 --- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/PDFBOXObject.java +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/PDFBOXObject.java @@ -9,6 +9,7 @@ import javax.activation.DataSource; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.font.PDFont; +import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2.PDFAsFontCache; import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; import at.gv.egiz.pdfas.lib.impl.status.PDFObject; @@ -18,6 +19,16 @@ public class PDFBOXObject extends PDFObject { private Map fontCache = new HashMap(); + private PDFAsFontCache sigBlockFontCache = new PDFAsFontCache(); + + public PDFAsFontCache getSigBlockFontCache() { + return sigBlockFontCache; + } + + public void setSigBlockFontCache(PDFAsFontCache sigBlockFontCache) { + this.sigBlockFontCache = sigBlockFontCache; + } + public PDFBOXObject(OperationStatus operationStatus) { super(operationStatus); } @@ -64,7 +75,4 @@ public class PDFBOXObject extends PDFObject { return String.valueOf(getDocument().getDocument().getVersion()); } - public Map getFontCache() { - return fontCache; - } } diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java index 429fe518..0966ba11 100644 --- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java @@ -25,6 +25,7 @@ package at.gv.egiz.pdfas.lib.impl.pdfbox2.positioning; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; +import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; @@ -32,6 +33,7 @@ import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PDFIOException; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; import at.gv.egiz.pdfas.lib.impl.pdfbox2.utils.PdfBoxUtils; import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; @@ -263,11 +265,19 @@ public class Positioning { // Now we have to getfreespace in page and reguard footerline float footer_line = pos.getFooterLine(); - float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, - page - 1, page_height - footer_line, /* page_rotation, */ - legacy32, legacy40); +// float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, +// page - 1, page_height - footer_line, /* page_rotation, */ +// legacy32, legacy40); - if (pre_page_length == Float.NEGATIVE_INFINITY) { + float pre_page_length = Float.NEGATIVE_INFINITY; + try { + pre_page_length = PDFUtilities.getMaxYPosition(pdfDataSource, page-1, pdf_table, SIGNATURE_MARGIN_VERTICAL, footer_line); + //pre_page_length = PDFUtilities.getFreeTablePosition(pdfDataSource, page-1, pdf_table,SIGNATURE_MARGIN_VERTICAL); + } catch (IOException e) { + logger.warn("Could not determine page length, using -INFINITY"); + } + + if (pre_page_length == Float.NEGATIVE_INFINITY){ // we do have an empty page or nothing in area above footerline pre_page_length = page_height; // no text --> SIGNATURE_BORDER diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningPageDrawer.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningPageDrawer.java new file mode 100644 index 00000000..72c333b7 --- /dev/null +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningPageDrawer.java @@ -0,0 +1,68 @@ +package at.gv.egiz.pdfas.lib.impl.pdfbox2.positioning; + +import java.awt.Color; +import java.awt.Paint; +import java.io.IOException; + +import org.apache.pdfbox.pdmodel.graphics.color.PDColor; +import org.apache.pdfbox.rendering.PageDrawer; +import org.apache.pdfbox.rendering.PageDrawerParameters; + +public class PositioningPageDrawer extends PageDrawer{ + + public PositioningPageDrawer(PageDrawerParameters parameters) + throws IOException { + super(parameters); + // TODO Auto-generated constructor stub + } + + private static final Color POSCOLOR = new Color(234, 14, 184, 211); + + @Override + protected Paint getPaint(PDColor color){ + return POSCOLOR; + } + +// @Override +// protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode,Vector displacement) throws IOException{ +// // bbox in EM -> user units +// Shape bbox = new Rectangle2D.Float(0, 0, font.getWidth(code) / 1000, 1); +// AffineTransform at = textRenderingMatrix.createAffineTransform(); +// bbox = at.createTransformedShape(bbox); +// +// // save +// Graphics2D graphics = getGraphics(); +// +// // draw +// graphics.setClip(graphics.getDeviceConfiguration().getBounds()); +// graphics.setColor(POSCOLOR); +// graphics.setStroke(new BasicStroke(.5f)); +// graphics.draw(bbox); +// +// // restore +// } +// +// @Override +// public void fillPath(int windingRule) throws IOException +// { +// // bbox in user units +// Shape bbox = getLinePath().getBounds2D(); +// +// // draw path (note that getLinePath() is now reset) +// //super.fillPath(windingRule); +// +// // save +// Graphics2D graphics = getGraphics(); +// +// +// // draw +// graphics.setClip(graphics.getDeviceConfiguration().getBounds()); +// graphics.setColor(POSCOLOR); +// graphics.setStroke(new BasicStroke(.5f)); +// graphics.draw(bbox); +// +// } + + + +} diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningRenderer.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningRenderer.java new file mode 100644 index 00000000..64e8fd17 --- /dev/null +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/PositioningRenderer.java @@ -0,0 +1,22 @@ +package at.gv.egiz.pdfas.lib.impl.pdfbox2.positioning; + +import java.io.IOException; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.apache.pdfbox.rendering.PageDrawer; +import org.apache.pdfbox.rendering.PageDrawerParameters; + +public class PositioningRenderer extends PDFRenderer{ + + public PositioningRenderer(PDDocument document) { + super(document); + // TODO Auto-generated constructor stub + } + + @Override + protected PageDrawer createPageDrawer(PageDrawerParameters params) throws IOException{ + return new PositioningPageDrawer(params); + } + +} diff --git a/pdf-as-pdfbox-2/src/main/java/at/knowcenter/wag/egov/egiz/pdfbox2/pdf/PDFUtilities.java b/pdf-as-pdfbox-2/src/main/java/at/knowcenter/wag/egov/egiz/pdfbox2/pdf/PDFUtilities.java index c1578120..79e75b99 100644 --- a/pdf-as-pdfbox-2/src/main/java/at/knowcenter/wag/egov/egiz/pdfbox2/pdf/PDFUtilities.java +++ b/pdf-as-pdfbox-2/src/main/java/at/knowcenter/wag/egov/egiz/pdfbox2/pdf/PDFUtilities.java @@ -48,65 +48,150 @@ */ package at.knowcenter.wag.egov.egiz.pdfbox2.pdf; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; import java.io.IOException; -import java.util.Iterator; -import java.util.List; +import java.util.HashMap; -import org.apache.pdfbox.cos.COSStream; import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDPageTree; -import org.apache.pdfbox.pdmodel.PDResources; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.rendering.PDFRenderer; +import org.apache.pdfbox.tools.imageio.ImageIOUtil; -import at.gv.egiz.pdfas.common.exceptions.PDFIOException; +import at.gv.egiz.pdfas.lib.impl.pdfbox2.positioning.PositioningRenderer; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; -/** - * Contains useful helpers for accessing PDF documents. - * - * @author wprinz - * @author mruhmer - */ public abstract class PDFUtilities { - public static float calculatePageLength(PDDocument document, int page, - float effectivePageHeight, /* int pagerotation, */boolean legacy32, boolean legacy40) - throws PDFIOException { - // int last_page_id = document.getNumberOfPages(); - PDPageTree allPages = document.getDocumentCatalog().getPages(); - PDPage pdpage = allPages.get(page); - // pdpage.setRotation(pagerotation); - return calculatePageLength(pdpage, effectivePageHeight, legacy32, legacy40); - } - public static float calculatePageLength(PDPage page, - float effectivePageHeight, boolean legacy32, boolean legacy40) throws PDFIOException { - try { - PDFPage my_page = new PDFPage(effectivePageHeight, legacy32, legacy40); - //PDResources resources = page.getResources(); - if (page.getContents() != null) { - //COSStream stream = page.getContents(); - // List articles = page.getThreadBeads(); - // my_page.processMyPage(page); - //my_page.processStream(page, resources, stream); //TODO: pdfbox2 -> right? - my_page.processPage(page); - } - if (!legacy32) { - if (page.getAnnotations() != null) { - Iterator annotationsIt = page - .getAnnotations().iterator(); + public static Color MAGIC_COLOR = new Color(152,254,52);// green-ish background + + public static float getMaxYPosition( + PDDocument pdfDataSource, int page, IPDFVisualObject pdfTable, float signatureMarginVertical, float footer_line) throws IOException { + long t0 = System.currentTimeMillis(); + PositioningRenderer renderer = new PositioningRenderer(pdfDataSource); + //BufferedImage bim = renderer.renderImage(page); + long t1 = System.currentTimeMillis(); + int width = (int) pdfDataSource.getPage(page).getCropBox().getWidth(); + int height = (int) pdfDataSource.getPage(page).getCropBox().getHeight(); + BufferedImage bim = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + long t2 = System.currentTimeMillis(); + Graphics2D graphics = bim.createGraphics(); + long t3 = System.currentTimeMillis(); +// graphics.setPaint(MAGIC_COLOR); +// graphics.fillRect(0, 0, width, height); + graphics.setBackground(MAGIC_COLOR); + + renderer.renderPageToGraphics(page, graphics); + long t4 = System.currentTimeMillis(); + Color bgColor = MAGIC_COLOR; + + if(true){ //only used if background color should be determined automatically + bgColor = determineBackgroundColor(bim); + } + long t5 = System.currentTimeMillis(); + int yCoord = bim.getHeight() - 1 - (int)footer_line; - while (annotationsIt.hasNext()) { - PDAnnotation annotation = annotationsIt.next(); - if (!annotation.isInvisible()) { - my_page.processAnnotation(annotation); - } - } + for(int row = yCoord; row >= 0; row--){ + for(int col = 0; col < bim.getWidth(); col++){ + int val = bim.getRGB(col, row); + if(val != bgColor.getRGB()){ + yCoord = row; + row=-1; + break; } } - return my_page.getMaxPageLength(); - } catch (IOException e) { - throw new PDFIOException("error.pdf.stamp.11", e); } + long t6 = System.currentTimeMillis(); + + System.out.println("new Renderer: "+ (t1-t0)); + System.out.println("new BI: "+ (t2-t1)); + System.out.println("Create Graphics: "+ (t3-t2)); + System.out.println("Render to Graphics: "+ (t4-t3)); + System.out.println("Determined bg color: "+ (t5-t4)); + System.out.println("Calc y: "+ (t6-t5)); + +// for(int i=0; i < bim.getWidth(); i++){ +// bim.setRGB(i, yCoord, 255); +// } +// + ImageIOUtil.writeImage(bim, "/home/cmaierhofer/temp/bufferer.png", 72); + + return yCoord; } + +// public static float getFreeTablePosition( +// PDDocument pdfDataSource, int page, IPDFVisualObject pdfTable, float signatureMarginVertical) throws IOException { +// +// float table_height = pdfTable.getHeight(); +// +// PDFRenderer renderer = new PDFRenderer(pdfDataSource); +// +// BufferedImage bim = renderer.renderImage(page); +// +// Color bgColor = determineBackgroundColor(bim); +// float posY = bim.getHeight(); +// +// for(int row=0; row= table_height+signatureMarginVertical){ +// posY = row; +// row=bim.getHeight(); +// break; +// } +// } +// } +// } +// +// if(posY == -1) +// return Float.NEGATIVE_INFINITY; +// return posY; +// } + + public static Color determineBackgroundColor(BufferedImage bim){ + + int inset = 5;//px + + int pixelUpLeft = bim.getRGB(inset,inset); + int pixelUpRight = bim.getRGB(bim.getWidth()-inset,inset); + int pixelDownLeft = bim.getRGB(inset, bim.getHeight()-inset); + int pixelDownRight = bim.getRGB(bim.getWidth()-inset, bim.getHeight()-inset); + + HashMap stats = new HashMap(); + stats.put(pixelUpLeft, 0); + stats.put(pixelUpRight, 0); + stats.put(pixelDownLeft, 0); + stats.put(pixelDownRight, 0); + + stats.put(pixelUpLeft, stats.get(pixelUpLeft)+1); + stats.put(pixelUpRight, stats.get(pixelUpRight)+1); + stats.put(pixelDownLeft, stats.get(pixelDownLeft)+1); + stats.put(pixelDownRight, stats.get(pixelDownRight)+1); + int bgValue = -1; + int cnt =0; + for(int key:stats.keySet()){ + if(stats.get(key) > cnt){ + cnt = stats.get(key); + bgValue = key; + } + } + + return new Color(bgValue); + } + } -- cgit v1.2.3