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();
reader.setInput(ImageIO.createImageInputStream(file.getInputStream()));
int numPages = reader.getNumImages(true);
for (int i = 0; i < numPages; i++) {
BufferedImage pageImage = reader.read(i);
BufferedImage convertedImage = convertColorType(pageImage, colorType);
PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
}
} else {
File imageFile = Files.createTempFile("image", ".png").toFile();
try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = file.getInputStream()) { try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = file.getInputStream()) {
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int len; int len;
// Read from the input stream and write to the file
while ((len = input.read(buffer)) != -1) { while ((len = input.read(buffer)) != -1) {
fos.write(buffer, 0, len); fos.write(buffer, 0, len);
} }
logger.info("Image successfully written to file: {}", imageFile.getAbsolutePath()); BufferedImage image = ImageIO.read(imageFile);
BufferedImage convertedImage = convertColorType(image, colorType);
PDImageXObject pdImage = LosslessFactory.createFromImage(doc, convertedImage);
addImageToDocument(doc, pdImage, stretchToFit, autoRotate);
} catch (IOException e) { } catch (IOException e) {
logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e); logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e);
throw e; throw e;
} finally {
imageFile.delete();
}
}
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
doc.save(byteArrayOutputStream);
logger.info("PDF successfully saved to byte array");
return byteArrayOutputStream.toByteArray();
}
} }
// Create an image object from the image file private static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
PDImageXObject image = PDImageXObject.createFromFileByContent(imageFile, doc); 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;
}
// Determine the orientation of the image private static void addImageToDocument(PDDocument doc, PDImageXObject image, boolean stretchToFit, boolean autoRotate) throws IOException {
boolean imageIsLandscape = image.getWidth() > image.getHeight(); boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4; PDRectangle pageSize = PDRectangle.A4;
if (autoRotate && imageIsLandscape) { if (autoRotate && imageIsLandscape) {
// Rotate the page only if autoRotate is true and the image is landscape
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth()); pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
} }
System.out.println(pageSize + "=" + pageSize);
PDPage page = new PDPage(pageSize); PDPage page = new PDPage(pageSize);
doc.addPage(page); doc.addPage(page);
// Adjust the page size to match the orientation
float pageWidth = page.getMediaBox().getWidth(); float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight(); float pageHeight = page.getMediaBox().getHeight();
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) { try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
if (stretchToFit) { if (stretchToFit) {
// Stretch the image to fit the whole page
contentStream.drawImage(image, 0, 0, pageWidth, pageHeight); contentStream.drawImage(image, 0, 0, pageWidth, pageHeight);
logger.info("Image successfully added to PDF, stretched to fit page");
} else { } else {
// Ensure the image fits the page but maintain the image's aspect ratio
float imageAspectRatio = (float) image.getWidth() / (float) image.getHeight(); float imageAspectRatio = (float) image.getWidth() / (float) image.getHeight();
float pageAspectRatio = pageWidth / pageHeight; float pageAspectRatio = pageWidth / pageHeight;
// Determine the scale factor to fit the image onto the page
float scaleFactor = 1.0f; float scaleFactor = 1.0f;
if (imageAspectRatio > pageAspectRatio) { if (imageAspectRatio > pageAspectRatio) {
// Image is wider than the page, scale to fit the width
scaleFactor = pageWidth / image.getWidth(); scaleFactor = pageWidth / image.getWidth();
} else { } else {
// Image is taller than the page, scale to fit the height
scaleFactor = pageHeight / image.getHeight(); scaleFactor = pageHeight / image.getHeight();
} }
// Calculate the position of the image on the page
float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2; float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2;
float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2; float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2;
// Draw the image onto the page
contentStream.drawImage(image, xPos, yPos, image.getWidth() * scaleFactor, image.getHeight() * scaleFactor); 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 adding image to PDF", e);
throw e; throw e;
} }
// Delete the temporary file
imageFile.delete();
}
// Create a ByteArrayOutputStream to save the PDF to
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
doc.save(byteArrayOutputStream);
logger.info("PDF successfully saved to byte array");
return byteArrayOutputStream.toByteArray();
}
} }
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">