com.formkiq.core.service.conversion.PdfToPngFormatConverter.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.service.conversion.PdfToPngFormatConverter.java

Source

/*
 * 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;
    }
}