Za input przyjmowałem tiff'a.
Tworzenie pdfów:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NoArgsConstructor;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
import org.springframework.beans.factory.annotation.Autowired;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@org.springframework.stereotype.Component
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FilesToPdfConverter {
static final String ABSOLUTE_FILE_LOCATION = "absoluteLocation";
@Autowired FilePathOperations filePathOperations;
void closeDocument(PDDocument pdDocument) {
try {
pdDocument.close();
} catch (IOException e) {
throw new CouldNotClosePDDocumentProperly("Could not close document: " + pdDocument.getDocumentInformation());
}
}
//Remember to close pdf document after performing other operations on it!
PDDocument createDocumentFromPage(PDPage pdPage, Path newDocumentFileLocation) {
PDDocument pdDocument = new PDDocument();
pdDocument.addPage(pdPage);
finalizeCreating(newDocumentFileLocation, pdDocument);
return pdDocument;
}
private void finalizeCreating(Path newDocumentFileLocation, PDDocument pdDocument) {
setAdditionalInformations(newDocumentFileLocation, pdDocument);
saveDocument(newDocumentFileLocation, pdDocument);
}
private void saveDocument(Path pdfPath, PDDocument doc) {
try {
doc.save(pdfPath.toFile());
} catch (Exception e) {
throw new CouldNotCreatePdfFromFileDirectory("Could not save document", e);
}
}
private void setAdditionalInformations(Path pdfPath, PDDocument doc) {
PDDocumentInformation pdDocumentInformation = new PDDocumentInformation();
pdDocumentInformation.setCustomMetadataValue(ABSOLUTE_FILE_LOCATION, String.valueOf(pdfPath));
doc.setDocumentInformation(pdDocumentInformation);
}
//Remember to close pdf document after performing other operations on it!
PDDocument createDocumentFromPages(List<PDPage> pdPages, Path newDocumentFileLocation) {
PDDocument pdDocument = new PDDocument();
pdPages.forEach(pdDocument::addPage);
finalizeCreating(newDocumentFileLocation, pdDocument);
return pdDocument;
}
//changed version of: http://www.paulzepernick.com/java/java-apache-pdfbox-convert-multipage-tiff-to-pdf/
PDDocument generatePdfFromFileList(Set<File> fileList, String outputPdfFileName) {
List<BufferedImage> allBufferedImages = getAllBufferedImages(fileList);
return createDocument(fileList, outputPdfFileName, allBufferedImages);
}
//Remember to close pdf document after performing other operations on it!
private PDDocument createDocument(Set<File> fileList, String outputPdfFileName, List<BufferedImage> allBufferedImages) {
PDDocument doc = new PDDocument();
for (BufferedImage bi : allBufferedImages) {
addPageWithImage(doc, bi);
}
Path documentPath = getDocumentStorePath(fileList, outputPdfFileName);
finalizeCreating(documentPath, doc);
return doc;
}
private Path getDocumentStorePath(Set<File> fileList, String outputPdfFileName) {
return filePathOperations.getConvertedOutputFilePathFromAttachmentOrConvertedPath(fileList.iterator().next().toPath(), outputPdfFileName);
}
private void addPageWithImage(PDDocument doc, BufferedImage bi) {
PDPage page = new PDPage();
doc.addPage(page);
PDPageContentStream contentStream = tryGettingPDPageContentStream(doc, page);
try {
PDXObjectImage image = new PDJpeg(doc, bi, 1F);
drawImage(page, contentStream, image);
} catch (Exception e) {
throw new CouldNotCreatePdfFromFileDirectory("Could not create image or draw object." + e);
} finally {
tryCloseContentStream(contentStream);
}
}
private void drawImage(PDPage page, PDPageContentStream contentStream, PDXObjectImage image) throws IOException {
Dimension mediaBoxDimension = page.getMediaBox().createDimension();
Dimension scaledDim = getScaledDimension(new Dimension(image.getWidth(), image.getHeight()), mediaBoxDimension);
if (imageIsSmall(scaledDim, mediaBoxDimension))
contentStream.drawXObject(image, 1, getSmallImageHeight(scaledDim, mediaBoxDimension), scaledDim.width, scaledDim.height);
else
contentStream.drawXObject(image, 1, 1, scaledDim.width, scaledDim.height);
}
private boolean imageIsSmall(Dimension dimension, Dimension mediaBoxDimension) {
return dimension.getHeight() <= mediaBoxDimension.getHeight() || dimension.getWidth() <= mediaBoxDimension.getWidth();
}
private float getSmallImageHeight(Dimension dimension, Dimension mediaBoxDimension) {
return (float) (mediaBoxDimension.getHeight() - dimension.getHeight());
}
//taken from a stack overflow post http://stackoverflow.com/questions/23223716/scaled-image-blurry-in-pdfbox
private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
int original_width = imgSize.width;
int original_height = imgSize.height;
int bound_width = boundary.width;
int bound_height = boundary.height;
int new_width = original_width;
int new_height = original_height;
if (original_width > bound_width) {
new_width = bound_width;
new_height = (new_width * original_height) / original_width;
}
if (new_height > bound_height) {
new_height = bound_height;
new_width = (new_height * original_width) / original_height;
}
return new Dimension(new_width, new_height);
}
private void tryCloseContentStream(PDPageContentStream contentStream) {
try {
contentStream.close();
} catch (IOException e) {
throw new CouldNotCreatePdfFromFileDirectory("Could not close content Stream.", e);
}
}
private PDPageContentStream tryGettingPDPageContentStream(PDDocument doc, PDPage page) {
try {
return new PDPageContentStream(doc, page);
} catch (IOException e) {
throw new CouldNotCreatePdfFromFileDirectory("Could not create PD Page Content Stream.", e);
}
}
private List<BufferedImage> getAllBufferedImages(Set<File> fileList) {
List<BufferedImage> allBufferedImages = new ArrayList<>();
for (final File f : fileList) {
allBufferedImages.add(getImageFromFileLocation(f));
}
return allBufferedImages;
}
private BufferedImage getImageFromFileLocation(File f) {
try {
return ImageIO.read(f);
} catch (Exception e) {
throw new CouldNotCreatePdfFromFileDirectory("Could not get images from file location with path: " + f
.getAbsolutePath(), e);
}
}
}