/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.github.jipsg.pdfbox;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
* Helper class to work with Apache PDFBox.
*/
public class PdfToImageConverter {
private final int DPI_72 = 72;
/**
* Generates preview images of the given PDF document.
*
* @param source the opaque source of the PDF
* @param imageFormat the requested image format, e.g. "jpeg"
* @param startPage the first extracted page
* @param endPage the las extracted page
* @param resolution the resolution of the extracted images
* @param color the color model, e.g. "rgb"
* @return list of images
* @throws Exception the operation failed
*/
public List<BufferedImage> toImages(Object source, String imageFormat, int startPage, int endPage, int resolution, String color) throws Exception {
PDDocument pdDocument = new PDDocumentFactory().create(source);
try {
return toImages(pdDocument, imageFormat, startPage, endPage, resolution, color);
} finally {
if (pdDocument != null) {
pdDocument.close();
}
}
}
/**
* Split a PDF document into images.
*
* @param pdDocument the source document
* @param imageFormat the requested image format, e.g. "jpeg"
* @param startPage the first extracted page
* @param endPage the las extracted page
* @param resolution the resolution of the extracted images
* @param color the color model, e.g. "rgb", "gray"
* @return a list of images
* @throws Exception the conversion failed
*/
@SuppressWarnings("unchecked")
public List<BufferedImage> toImages(PDDocument pdDocument, String imageFormat, int startPage, int endPage, int resolution, String color) throws Exception {
/**
Validate.notNull(pdDocument, "pdDocument is null");
Validate.notEmpty(imageFormat, "imageFormat is null");
Validate.isTrue(startPage > 0, "invalid start page : " + startPage);
Validate.isTrue(endPage >= startPage, "invalid end page : " + endPage);
Validate.isTrue(resolution >= 0, "invalid resolution : " + resolution);
*/
List<BufferedImage> result = new ArrayList<BufferedImage>();
int imageType = getImageType(color);
List<PDPage> pages = pdDocument.getDocumentCatalog().getAllPages();
int pagesSize = pages.size();
for (int i = startPage - 1; i < endPage && i < pagesSize; i++) {
PDPage page = pages.get(i);
PDRectangle cropBox = page.findCropBox();
int currResolution = calculateResolution(resolution, cropBox.getWidth(), cropBox.getHeight());
BufferedImage image = page.convertToImage(imageType, currResolution);
result.add(image);
}
return result;
}
private int getImageType(String color) {
int result;
String currColor = (color != null && color.length() > 0 ? color : "rgb");
if ("bilevel".equalsIgnoreCase(currColor)) {
result = BufferedImage.TYPE_BYTE_BINARY;
} else if ("indexed".equalsIgnoreCase(currColor)) {
result = BufferedImage.TYPE_BYTE_INDEXED;
} else if ("gray".equalsIgnoreCase(currColor)) {
result = BufferedImage.TYPE_BYTE_GRAY;
} else if ("rgb".equalsIgnoreCase(currColor)) {
result = BufferedImage.TYPE_INT_RGB;
} else if ("rgba".equalsIgnoreCase(currColor)) {
result = BufferedImage.TYPE_INT_ARGB;
} else {
throw new IllegalArgumentException("Error: the number of bits per pixel must be 1, 8 or 24.");
}
return result;
}
/**
* Calculate the resolution being used assuming that the DPI is used
* for an A4 page.
*/
protected int calculateResolution(int dpi, float cropBoxWidth, float cropBoxHeight) {
int result;
float maxPoints = Math.max(cropBoxWidth, cropBoxHeight);
float pointForRequestedResolution = 29.7f * dpi / 2.54f;
result = Math.round((pointForRequestedResolution * DPI_72 / maxPoints));
return result;
}
}