Java tutorial
/* * Copyright (C) 2017 FormKiQ Inc. * * Licensed 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 com.formkiq.core.service.conversion; import static com.formkiq.core.form.dto.WorkflowOutputDocumentType.PDF; import static com.formkiq.core.form.dto.WorkflowOutputDocumentType.PNG; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget; import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField; import org.apache.pdfbox.rendering.PDFRenderer; import com.formkiq.core.form.dto.WorkflowOutputDocumentType; import com.formkiq.core.service.generator.pdfbox.PDRectangleUtil; /** * Converts DOCX to HTML. * */ public class PdfToPngFormatConverter implements FormatConverter { /** the Image Scale. The higher the number the better the quality. * But the bigger the file size and longer it takes. */ private static final int SCALE = 1; @Override public ConversionResult convert(final Object data, final WorkflowOutputDocumentType inputType, final WorkflowOutputDocumentType outputType) throws IOException { PDDocument doc = (PDDocument) data; PDFRenderer pdfRenderer = new PDFRenderer(doc); BufferedImage[] images = new BufferedImage[doc.getNumberOfPages()]; for (int page = 0; page < doc.getNumberOfPages(); ++page) { BufferedImage bim = pdfRenderer.renderImage(page, SCALE); images[page] = bim; } ConversionResult result = merge(images); List<ConversionField> fields = findSigningButtons(doc, result); result.setFields(fields); return result; } /** * Find {@link PDSignatureField} on the Image. * @param doc {@link PDDocument} * @param result {@link ConversionResult} * @return {@link List} of {@link ConversionField} * @throws IOException IOException */ private List<ConversionField> findSigningButtons(final PDDocument doc, final ConversionResult result) throws IOException { List<ConversionField> fields = new ArrayList<>(); List<PDSignatureField> sigs = doc.getSignatureFields(); for (PDSignatureField s : sigs) { PDRectangle rect = PDRectangleUtil.calculateWidget(s.getWidgets()); PDAnnotationWidget widget = s.getWidgets().get(0); PDPage page = widget.getPage(); int pageNumber = doc.getPages().indexOf(page); float imagePageSize = result.getDataheight() / doc.getNumberOfPages(); float x = rect.getLowerLeftX(); float y = (imagePageSize - rect.getUpperRightY()) + (imagePageSize * pageNumber); ConversionField f = new ConversionField(); f.setDocumentfieldname(s.getFullyQualifiedName()); f.setX(x); f.setY(y); f.setHeight(rect.getHeight()); fields.add(f); } return fields; } /** * Merge Buffered Images together. * @param buffImages {@link BufferedImage} * @return {@link ConversionResult} * @throws IOException IOException */ private ConversionResult merge(final BufferedImage[] buffImages) throws IOException { ConversionResult result = new ConversionResult(); int cols = 1; int rows = buffImages.length; int type = buffImages[0].getType(); int width = buffImages[0].getWidth(); int height = buffImages[0].getHeight(); BufferedImage bi = new BufferedImage(width * cols, height * rows, type); int num = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { bi.createGraphics().drawImage(buffImages[num], width * j, height * i, null); num++; } } ByteArrayOutputStream os = new ByteArrayOutputStream(); try { ImageIO.write(bi, "png", os); } finally { os.close(); } result.setDatawidth(width * cols); result.setDataheight(height * rows); result.setData(os.toByteArray()); return result; } @Override public boolean isSupported(final Object data, final WorkflowOutputDocumentType inputType, final WorkflowOutputDocumentType outputType) { return PDF.equals(inputType) && PNG.equals(outputType) && data instanceof PDDocument; } }