changes for img to pdf #142
This commit is contained in:
parent
25e5470c5e
commit
e16ed5ca1a
3 changed files with 95 additions and 70 deletions
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in a new issue