changes for img to pdf #142

This commit is contained in:
Anthony Stirling 2023-05-10 22:51:01 +01:00
parent 25e5470c5e
commit e16ed5ca1a
3 changed files with 95 additions and 70 deletions

View file

@ -89,11 +89,14 @@ public class ConvertImgPDFController {
@RequestParam(defaultValue = "false", name = "stretchToFit") @RequestParam(defaultValue = "false", name = "stretchToFit")
@Parameter(description = "Whether to stretch the images to fit the PDF page or maintain the aspect ratio", example = "false") @Parameter(description = "Whether to stretch the images to fit the PDF page or maintain the aspect ratio", example = "false")
boolean stretchToFit, boolean stretchToFit,
@RequestParam("colorType")
@Parameter(description = "The color type of the output image(s)", schema = @Schema(allowableValues = {"rgb", "greyscale", "blackwhite"}))
String colorType,
@RequestParam(defaultValue = "false", name = "autoRotate") @RequestParam(defaultValue = "false", name = "autoRotate")
@Parameter(description = "Whether to automatically rotate the images to better fit the PDF page", example = "true") @Parameter(description = "Whether to automatically rotate the images to better fit the PDF page", example = "true")
boolean autoRotate) throws IOException { boolean autoRotate) throws IOException {
// Convert the file to PDF and get the resulting bytes // Convert the file to PDF and get the resulting bytes
byte[] bytes = PdfUtils.imageToPdf(file, stretchToFit, autoRotate); byte[] bytes = PdfUtils.imageToPdf(file, stretchToFit, autoRotate, colorType);
return PdfUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_coverted.pdf"); return PdfUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_coverted.pdf");
} }

View file

@ -2,6 +2,8 @@ package stirling.software.SPDF.utils;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@ -24,11 +26,13 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.rendering.PDFRenderer;
@ -120,89 +124,99 @@ public class PdfUtils {
throw e; throw e;
} }
} }
public static byte[] imageToPdf(MultipartFile[] files, boolean stretchToFit, boolean autoRotate, String colorType) throws IOException {
public static byte[] imageToPdf(MultipartFile[] files, boolean stretchToFit, boolean autoRotate) throws IOException {
try (PDDocument doc = new PDDocument()) { try (PDDocument doc = new PDDocument()) {
for (MultipartFile file : files) { for (MultipartFile file : files) {
// Create a temporary file for the image String originalFilename = file.getOriginalFilename();
File imageFile = Files.createTempFile("image", ".jpg").toFile(); if (originalFilename != null && (originalFilename.toLowerCase().endsWith(".tiff") || originalFilename.toLowerCase().endsWith(".tif")) ) {
ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = file.getInputStream()) { reader.setInput(ImageIO.createImageInputStream(file.getInputStream()));
byte[] buffer = new byte[1024]; int numPages = reader.getNumImages(true);
int len; for (int i = 0; i < numPages; i++) {
// Read from the input stream and write to the file BufferedImage pageImage = reader.read(i);
while ((len = input.read(buffer)) != -1) { BufferedImage convertedImage = convertColorType(pageImage, colorType);
fos.write(buffer, 0, len); PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
} }
logger.info("Image successfully written to file: {}", imageFile.getAbsolutePath()); } else {
} catch (IOException e) { File imageFile = Files.createTempFile("image", ".png").toFile();
logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e); try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = file.getInputStream()) {
throw e; byte[] buffer = new byte[1024];
} int len;
while ((len = input.read(buffer)) != -1) {
// Create an image object from the image file fos.write(buffer, 0, len);
PDImageXObject image = PDImageXObject.createFromFileByContent(imageFile, doc);
// Determine the orientation of the image
boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4;
if (autoRotate && imageIsLandscape) {
// Rotate the page only if autoRotate is true and the image is landscape
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
}
System.out.println(pageSize + "=" + pageSize);
PDPage page = new PDPage(pageSize);
doc.addPage(page);
// Adjust the page size to match the orientation
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
if (stretchToFit) {
// Stretch the image to fit the whole page
contentStream.drawImage(image, 0, 0, pageWidth, pageHeight);
logger.info("Image successfully added to PDF, stretched to fit page");
} else {
// Ensure the image fits the page but maintain the image's aspect ratio
float imageAspectRatio = (float) image.getWidth() / (float) image.getHeight();
float pageAspectRatio = pageWidth / pageHeight;
// Determine the scale factor to fit the image onto the page
float scaleFactor = 1.0f;
if (imageAspectRatio > pageAspectRatio) {
// Image is wider than the page, scale to fit the width
scaleFactor = pageWidth / image.getWidth();
} else {
// Image is taller than the page, scale to fit the height
scaleFactor = pageHeight / image.getHeight();
} }
BufferedImage image = ImageIO.read(imageFile);
// Calculate the position of the image on the page BufferedImage convertedImage = convertColorType(image, colorType);
float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2; PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2; addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
// Draw the image onto the page
contentStream.drawImage(image, xPos, yPos, image.getWidth() * scaleFactor, image.getHeight() * scaleFactor);
logger.info("Image successfully added to PDF, maintaining aspect ratio");
}
} catch (IOException e) { } catch (IOException e) {
logger.error("Error adding image to PDF", e); logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e);
throw e; throw e;
} finally {
imageFile.delete();
} }
// Delete the temporary file
imageFile.delete();
} }
// Create a ByteArrayOutputStream to save the PDF to }
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
doc.save(byteArrayOutputStream); doc.save(byteArrayOutputStream);
logger.info("PDF successfully saved to byte array"); logger.info("PDF successfully saved to byte array");
return byteArrayOutputStream.toByteArray(); return byteArrayOutputStream.toByteArray();
} }
}
private static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
BufferedImage convertedImage;
switch (colorType) {
case "greyscale":
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
break;
case "blackwhite":
convertedImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
break;
default: // full color
convertedImage = sourceImage;
break;
}
return convertedImage;
}
private static void addImageToDocument(PDDocument doc, PDImageXObject image, boolean stretchToFit, boolean autoRotate) throws IOException {
boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4;
if (autoRotate && imageIsLandscape) {
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
}
PDPage page = new PDPage(pageSize);
doc.addPage(page);
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
if (stretchToFit) {
contentStream.drawImage(image, 0, 0, pageWidth, pageHeight);
} else {
float imageAspectRatio = (float) image.getWidth() / (float) image.getHeight();
float pageAspectRatio = pageWidth / pageHeight;
float scaleFactor = 1.0f;
if (imageAspectRatio > pageAspectRatio) {
scaleFactor = pageWidth / image.getWidth();
} else {
scaleFactor = pageHeight / image.getHeight();
}
float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2;
float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2;
contentStream.drawImage(image, xPos, yPos, image.getWidth() * scaleFactor, image.getHeight() * scaleFactor);
}
} catch (IOException e) {
logger.error("Error adding image to PDF", e);
throw e;
}
} }
public static X509Certificate[] loadCertificateChainFromKeystore(InputStream keystoreInputStream, String keystorePassword) throws Exception { public static X509Certificate[] loadCertificateChainFromKeystore(InputStream keystoreInputStream, String keystorePassword) throws Exception {

View file

@ -29,6 +29,14 @@
<input type="checkbox" class="form-check-input" name="autoRotate" id="autoRotate"> <input type="checkbox" class="form-check-input" name="autoRotate" id="autoRotate">
<label class="ml-3" for="autoRotate" th:text=#{imageToPDF.selectText.2}></label> <label class="ml-3" for="autoRotate" th:text=#{imageToPDF.selectText.2}></label>
</div> </div>
<div class="form-group">
<label th:text="#{pdfToImage.colorType}"></label>
<select class="form-control" name="colorType">
<option value="color" th:text="#{pdfToImage.color}"></option>
<option value="greyscale" th:text="#{pdfToImage.grey}"></option>
<option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option>
</select>
</div>
<br> <br>
<input type="hidden" id="override" name="override" value="multi"> <input type="hidden" id="override" name="override" value="multi">
<div class="form-group"> <div class="form-group">