From a2a27e2216268ea2b7432f0759245e2ba250b23f Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Sat, 25 Mar 2023 22:16:26 +0000 Subject: [PATCH] Image stuff (#77) Features --------- Image to PDF supports multiple images, stretching and auto rotation File inputs now only search for wanted file type Settings now has a zip range so it can zip if you have more than x downloads (default 4) extras --------- DevTools support for easier development Fix for temporary files for thread safety --- build.gradle | 3 +- .../SPDF/controller/CompressController.java | 42 +------ .../SPDF/controller/OCRController.java | 14 +-- .../SPDF/controller/SplitPDFController.java | 6 +- .../converters/ConvertImgPDFController.java | 11 +- .../converters/ConvertOfficeController.java | 5 - .../software/SPDF/utils/PdfUtils.java | 113 +++++++++++++----- .../software/SPDF/utils/ProcessExecutor.java | 6 +- src/main/resources/application.properties | 7 +- src/main/resources/messages_ar_AR.properties | 7 +- src/main/resources/messages_de_DE.properties | 7 +- src/main/resources/messages_en_GB.properties | 15 ++- src/main/resources/messages_en_US.properties | 13 +- src/main/resources/messages_fr_FR.properties | 7 +- src/main/resources/templates/add-image.html | 4 +- .../resources/templates/compress-pdf.html | 2 +- .../templates/convert/img-to-pdf.html | 51 +++++++- .../templates/convert/pdf-to-img.html | 2 +- .../resources/templates/extract-images.html | 2 +- .../resources/templates/fragments/common.html | 15 ++- .../resources/templates/fragments/navbar.html | 38 +++--- src/main/resources/templates/home.html | 2 + src/main/resources/templates/merge-pdfs.html | 2 +- src/main/resources/templates/ocr-pdf.html | 2 +- .../resources/templates/pdf-organizer.html | 2 +- .../resources/templates/remove-pages.html | 2 +- src/main/resources/templates/rotate-pdf.html | 2 +- .../templates/security/add-password.html | 2 +- .../templates/security/add-watermark.html | 2 +- .../templates/security/change-metadata.html | 2 +- .../security/change-permissions.html | 2 +- .../templates/security/remove-password.html | 2 +- .../templates/security/remove-watermark.html | 2 +- src/main/resources/templates/split-pdfs.html | 2 +- 34 files changed, 243 insertions(+), 153 deletions(-) diff --git a/build.gradle b/build.gradle index 507a5a44..73cf5577 100644 --- a/build.gradle +++ b/build.gradle @@ -21,8 +21,9 @@ dependencies { //general PDF implementation 'org.apache.pdfbox:pdfbox:2.0.27' + implementation 'com.itextpdf:itextpdf:5.5.13.3' - + developmentOnly("org.springframework.boot:spring-boot-devtools") } diff --git a/src/main/java/stirling/software/SPDF/controller/CompressController.java b/src/main/java/stirling/software/SPDF/controller/CompressController.java index 6e72b09c..d8028a75 100644 --- a/src/main/java/stirling/software/SPDF/controller/CompressController.java +++ b/src/main/java/stirling/software/SPDF/controller/CompressController.java @@ -1,23 +1,15 @@ package stirling.software.SPDF.controller; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; -import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; -import javax.imageio.ImageIO; - -import org.apache.pdfbox.cos.COSName; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDResources; -import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -26,30 +18,8 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; -import com.itextpdf.text.DocumentException; -import com.itextpdf.text.pdf.PdfReader; -import com.itextpdf.text.pdf.PdfStamper; - -import stirling.software.SPDF.utils.PdfUtils; import stirling.software.SPDF.utils.ProcessExecutor; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.multipart.MultipartFile; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - @Controller public class CompressController { diff --git a/src/main/java/stirling/software/SPDF/controller/OCRController.java b/src/main/java/stirling/software/SPDF/controller/OCRController.java index 5425b2c4..93e0f6eb 100644 --- a/src/main/java/stirling/software/SPDF/controller/OCRController.java +++ b/src/main/java/stirling/software/SPDF/controller/OCRController.java @@ -1,10 +1,8 @@ package stirling.software.SPDF.controller; -import java.io.BufferedReader; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -13,11 +11,12 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -28,13 +27,6 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import stirling.software.SPDF.utils.ProcessExecutor; - -import java.io.FileOutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; //import com.spire.pdf.*; @Controller public class OCRController { diff --git a/src/main/java/stirling/software/SPDF/controller/SplitPDFController.java b/src/main/java/stirling/software/SPDF/controller/SplitPDFController.java index e159effc..0eb0429e 100644 --- a/src/main/java/stirling/software/SPDF/controller/SplitPDFController.java +++ b/src/main/java/stirling/software/SPDF/controller/SplitPDFController.java @@ -1,7 +1,6 @@ package stirling.software.SPDF.controller; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -10,7 +9,6 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -108,7 +106,7 @@ public class SplitPDFController { document.close(); // create the zip file - Path zipFile = Paths.get("split_documents.zip"); + Path zipFile = Files.createTempFile("split_documents", ".zip"); URI uri = URI.create("jar:file:" + zipFile.toUri().getPath()); Map env = new HashMap<>(); env.put("create", "true"); @@ -132,7 +130,7 @@ public class SplitPDFController { logger.info("Successfully created zip file with split documents: {}", zipFile.toString()); byte[] data = Files.readAllBytes(zipFile); ByteArrayResource resource = new ByteArrayResource(data); - new File("split_documents.zip").delete(); + Files.delete(zipFile); // return the Resource in the response return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_split.zip").contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(resource.contentLength()).body(resource); diff --git a/src/main/java/stirling/software/SPDF/controller/converters/ConvertImgPDFController.java b/src/main/java/stirling/software/SPDF/controller/converters/ConvertImgPDFController.java index dd8415d0..8d0d43b2 100644 --- a/src/main/java/stirling/software/SPDF/controller/converters/ConvertImgPDFController.java +++ b/src/main/java/stirling/software/SPDF/controller/converters/ConvertImgPDFController.java @@ -38,12 +38,13 @@ public class ConvertImgPDFController { } @PostMapping("/img-to-pdf") - public ResponseEntity convertToPdf(@RequestParam("fileInput") MultipartFile file) throws IOException { + public ResponseEntity convertToPdf(@RequestParam("fileInput") MultipartFile[] file, + @RequestParam(defaultValue = "false", name = "stretchToFit") boolean stretchToFit, + @RequestParam(defaultValue = "true", name = "autoRotate") boolean autoRotate) throws IOException { // Convert the file to PDF and get the resulting bytes - byte[] bytes = PdfUtils.convertToPdf(file.getInputStream()); - logger.info("File {} successfully converted to pdf", file.getOriginalFilename()); - - return PdfUtils.bytesToWebResponse(bytes, file.getOriginalFilename().replaceFirst("[.][^.]+$", "")+ "_coverted.pdf"); + System.out.println(stretchToFit); + byte[] bytes = PdfUtils.imageToPdf(file, stretchToFit, autoRotate); + return PdfUtils.bytesToWebResponse(bytes, file[0].getOriginalFilename().replaceFirst("[.][^.]+$", "")+ "_coverted.pdf"); } @PostMapping("/pdf-to-img") diff --git a/src/main/java/stirling/software/SPDF/controller/converters/ConvertOfficeController.java b/src/main/java/stirling/software/SPDF/controller/converters/ConvertOfficeController.java index 00996dc0..708f3df2 100644 --- a/src/main/java/stirling/software/SPDF/controller/converters/ConvertOfficeController.java +++ b/src/main/java/stirling/software/SPDF/controller/converters/ConvertOfficeController.java @@ -1,9 +1,6 @@ package stirling.software.SPDF.controller.converters; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -17,9 +14,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.ModelAndView; -import stirling.software.SPDF.LibreOfficeListener; import stirling.software.SPDF.utils.PdfUtils; import stirling.software.SPDF.utils.ProcessExecutor; @Controller diff --git a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java index 18825a50..030f9e2b 100644 --- a/src/main/java/stirling/software/SPDF/utils/PdfUtils.java +++ b/src/main/java/stirling/software/SPDF/utils/PdfUtils.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -28,6 +29,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; @@ -37,49 +39,100 @@ public class PdfUtils { private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class); - public static byte[] convertToPdf(InputStream imageStream) throws IOException { - - // Create a File object for the image - File imageFile = new File("image.jpg"); - - try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = imageStream) { - byte[] buffer = new byte[1024]; - int len; - // Read from the input stream and write to the file - while ((len = input.read(buffer)) != -1) { - fos.write(buffer, 0, len); - } - logger.info("Image successfully written to file: {}", imageFile.getAbsolutePath()); - } catch (IOException e) { - logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e); - throw e; - } - + public static byte[] imageToPdf(MultipartFile[] files, boolean stretchToFit, boolean autoRotate) throws IOException { try (PDDocument doc = new PDDocument()) { - // Create a new PDF page - PDPage page = new PDPage(); - doc.addPage(page); + for (MultipartFile file : files) { + // Create a temporary file for the image + File imageFile = Files.createTempFile("image", ".jpg").toFile(); - // Create an image object from the image file - PDImageXObject image = PDImageXObject.createFromFileByContent(imageFile, doc); + try (FileOutputStream fos = new FileOutputStream(imageFile); InputStream input = file.getInputStream()) { + byte[] buffer = new byte[1024]; + int len; + // Read from the input stream and write to the file + while ((len = input.read(buffer)) != -1) { + fos.write(buffer, 0, len); + } + logger.info("Image successfully written to file: {}", imageFile.getAbsolutePath()); + } catch (IOException e) { + logger.error("Error writing image to file: {}", imageFile.getAbsolutePath(), e); + throw e; + } - try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) { - // Draw the image onto the page - contentStream.drawImage(image, 0, 0); - logger.info("Image successfully added to PDF"); - } catch (IOException e) { - logger.error("Error adding image to PDF", e); - throw e; + // Create a new PDF page + PDPage page = new PDPage(); + doc.addPage(page); + + // Create an image object from the image file + PDImageXObject image = PDImageXObject.createFromFileByContent(imageFile, doc); + + float pageWidth = page.getMediaBox().getWidth(); + float pageHeight = page.getMediaBox().getHeight(); + + if (autoRotate && ((image.getWidth() > image.getHeight() && pageHeight > pageWidth) || (image.getWidth() < image.getHeight() && pageWidth > pageHeight))) { + // Rotate the page 90 degrees if the image better fits the page in landscape orientation + page.setRotation(90); + pageWidth = page.getMediaBox().getHeight(); + pageHeight = page.getMediaBox().getWidth(); + } + + try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) { + if (stretchToFit) { + if (page.getRotation() == 0 || page.getRotation() == 180) { + // Stretch the image to fit the whole page + contentStream.drawImage(image, 0, 0, pageWidth, pageHeight); + } else { + // Adjust the width and height of the page when rotated + contentStream.drawImage(image, 0, 0, pageHeight, pageWidth); + } + 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(); + } + + // Calculate the position of the image on the page + float xPos = (pageWidth - (image.getWidth() * scaleFactor)) / 2; + float yPos = (pageHeight - (image.getHeight() * scaleFactor)) / 2; + + // Draw the image onto the page + if (page.getRotation() == 0 || page.getRotation() == 180) { + contentStream.drawImage(image, xPos, yPos, image.getWidth() * scaleFactor, image.getHeight() * scaleFactor); + } else { + // Adjust the width and height of the page when rotated + contentStream.drawImage(image, yPos, xPos, image.getHeight() * scaleFactor, image.getWidth() * scaleFactor); + } + logger.info("Image successfully added to PDF, maintaining aspect ratio"); + } + } catch (IOException e) { + logger.error("Error adding image to PDF", 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 byte[] convertFromPdf(byte[] inputStream, String imageType, ImageType colorType, boolean singleImage, int DPI) throws IOException, Exception { try (PDDocument document = PDDocument.load(new ByteArrayInputStream(inputStream))) { diff --git a/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java b/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java index e244d4a2..73d597dc 100644 --- a/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java +++ b/src/main/java/stirling/software/SPDF/utils/ProcessExecutor.java @@ -1,13 +1,11 @@ package stirling.software.SPDF.utils; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.Arrays; -import java.util.List; -import java.io.BufferedReader; import java.util.ArrayList; +import java.util.List; public class ProcessExecutor { public static int runCommandWithOutputHandling(List command) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(command); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 88844ae4..266a0f35 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,4 +16,9 @@ server.error.include-stacktrace=always server.error.include-exception=true server.error.include-message=always -server.servlet.session.tracking-modes=cookie \ No newline at end of file +server.servlet.session.tracking-modes=cookie + +spring.devtools.restart.enabled=true +spring.devtools.livereload.enabled=true + +spring.thymeleaf.encoding=UTF-8 \ No newline at end of file diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties index 4a163e44..f5a38183 100644 --- a/src/main/resources/messages_ar_AR.properties +++ b/src/main/resources/messages_ar_AR.properties @@ -95,7 +95,7 @@ settings.downloadOption.title=\u062A\u062D\u062F\u064A\u062F \u062E\u064A\u0627\ settings.downloadOption.1=\u0641\u062A\u062D \u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0646\u0627\u0641\u0630\u0629 settings.downloadOption.2=\u0641\u062A\u062D \u0641\u064A \u0646\u0627\u0641\u0630\u0629 \u062C\u062F\u064A\u062F\u0629 settings.downloadOption.3=\u062A\u0646\u0632\u064A\u0644 \u0627\u0644\u0645\u0644\u0641 -settings.zip=\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u0646\u0632\u064A\u0644 \u0627\u0644\u0645\u062A\u0639\u062F\u062F \u0627\u0644\u0645\u0636\u063A\u0648\u0637\u0629 +settings.zipThreshold=\u0645\u0644\u0641\u0627\u062A \u0645\u0636\u063A\u0648\u0637\u0629 \u0639\u0646\u062F \u062A\u062C\u0627\u0648\u0632 \u0639\u062F\u062F \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0645 \u062A\u0646\u0632\u064A\u0644\u0647\u0627 #OCR OCR.title = OCR @@ -184,6 +184,11 @@ split.submit=Split imageToPDF.title=صورة إلى PDF imageToPDF.header=صورة إلى PDF imageToPDF.submit=تحول +imageToPDF.selectText.1=\u062A\u0645\u062F\u062F \u0644\u0644\u0645\u0644\u0627\u0621\u0645\u0629 +imageToPDF.selectText.2=\u062F\u0648\u0631\u0627\u0646 PDF \u062A\u0644\u0642\u0627\u0626\u064A\u064B\u0627 +imageToPDF.selectText.3=\u0627\u0644\u0645\u0646\u0637\u0642 \u0627\u0644\u0645\u062A\u0639\u062F\u062F \u0644\u0644\u0645\u0644\u0641\u0627\u062A (\u0645\u0641\u0639\u0651\u0644 \u0641\u0642\u0637 \u0625\u0630\u0627 \u0643\u0646\u062A \u062A\u0639\u0645\u0644 \u0645\u0639 \u0635\u0648\u0631 \u0645\u062A\u0639\u062F\u062F\u0629) +imageToPDF.selectText.4=\u062F\u0645\u062C \u0641\u064A \u0645\u0644\u0641 PDF \u0648\u0627\u062D\u062F +imageToPDF.selectText.5=\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 \u0645\u0644\u0641\u0627\u062A PDF \u0645\u0646\u0641\u0635\u0644\u0629 #pdfToImage pdfToImage.title=تحويل PDF إلى صورة diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index abf5f3f1..f653822e 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -90,7 +90,7 @@ settings.downloadOption.title=Download-Option w settings.downloadOption.1=Im selben Fenster öffnen settings.downloadOption.2=In neuem Fenster öffnen settings.downloadOption.3=Datei herunterladen -settings.zip=Dateien mit mehrfachem Download zippen +settings.zipThreshold=Dateien komprimieren, wenn die Anzahl der heruntergeladenen Dateien überschritten wird #OCR ocr.title=OCR @@ -183,6 +183,11 @@ split.submit=Aufteilen imageToPDF.title=Bild zu PDF imageToPDF.header=Bild zu PDF imageToPDF.submit=Umwandeln +imageToPDF.selectText.1=Auf Seite strecken +imageToPDF.selectText.2=PDF automatisch drehen +imageToPDF.selectText.3=Mehrere Dateien verarbeiten (nur aktiv, wenn Sie mit mehreren Bildern arbeiten) +imageToPDF.selectText.4=In ein einziges PDF zusammenführen +imageToPDF.selectText.5=In separate PDFs konvertieren #pdfToImage pdfToImage.title=PDF zu Bild diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 3fd3477d..8a171bab 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -4,10 +4,10 @@ # the direction that the language is written (ltr = left to right, rtl = right to left) language.direction=ltr -pdfPrompt=Choose PDF -multiPdfPrompt=Choose PDFs (2+) +pdfPrompt=Select PDF(s) +multiPdfPrompt=Select PDFs (2+) multiPdfDropPrompt=Select (or drag & drop) all PDFs you require -imgPrompt=Choose Image +imgPrompt=Select Image(s) genericSubmit=Submit processTimeWarning=Warning: This process can take up to a minute depending on file-size pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) : @@ -91,7 +91,7 @@ settings.downloadOption.title=Choose download option (For single file non zip do settings.downloadOption.1=Open in same window settings.downloadOption.2=Open in new window settings.downloadOption.3=Download file -settings.zip=Zip multi-download files +settings.zipThreshold=Zip files when the number of downloaded files exceeds #OCR ocr.title=OCR @@ -181,7 +181,12 @@ split.submit=Split imageToPDF.title=Image to PDF imageToPDF.header=Image to PDF imageToPDF.submit=Convert - +imageToPDF.selectText.1=Stretch to fit +imageToPDF.selectText.2=Auto rotate PDF +imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images) +imageToPDF.selectText.4=Merge into single PDF +imageToPDF.selectText.5=Convert to separate PDFs + #pdfToImage pdfToImage.title=PDF to Image pdfToImage.header=PDF to Image diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index 740b83b7..2532ca8e 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -4,10 +4,10 @@ # the direction that the language is written (ltr = left to right, rtl = right to left) language.direction=ltr -pdfPrompt=Choose PDF -multiPdfPrompt=Choose PDFs (2+) +pdfPrompt=Select PDF(s) +multiPdfPrompt=Select PDFs (2+) multiPdfDropPrompt=Select (or drag & drop) all PDFs you require -imgPrompt=Choose Image +imgPrompt=Select Image(s) genericSubmit=Submit processTimeWarning=Warning: This process can take up to a minute depending on file-size pageOrderPrompt=Page Order (Enter a comma-separated list of page numbers) : @@ -91,7 +91,7 @@ settings.downloadOption.title=Choose download option (For single file non zip do settings.downloadOption.1=Open in same window settings.downloadOption.2=Open in new window settings.downloadOption.3=Download file -settings.zip=Zip multi-download files +settings.zipThreshold=Zip files when the number of downloaded files exceeds #OCR ocr.title=OCR @@ -180,6 +180,11 @@ split.submit=Split imageToPDF.title=Image to PDF imageToPDF.header=Image to PDF imageToPDF.submit=Convert +imageToPDF.selectText.1=Stretch to fit +imageToPDF.selectText.2=Auto rotate PDF +imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images) +imageToPDF.selectText.4=Merge into single PDF +imageToPDF.selectText.5=Convert to separate PDFs #pdfToImage pdfToImage.title=PDF to Image diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties index 6068bf10..1b3e7652 100644 --- a/src/main/resources/messages_fr_FR.properties +++ b/src/main/resources/messages_fr_FR.properties @@ -96,7 +96,7 @@ settings.downloadOption.title=Choisissez l\u2019option de t settings.downloadOption.1=Ouvrir dans la même fenêtre settings.downloadOption.2=Ouvrir dans une nouvelle fenêtre settings.downloadOption.3=Fichier téléchargé -settings.zip=Fichiers multi-téléchargements Zip +settings.zipThreshold=Zip les fichiers lorsque le nombre de fichiers téléchargés dépasse #OCR @@ -189,6 +189,11 @@ split.submit=Diviser imageToPDF.title=Image au format PDF imageToPDF.header=Image au format PDF imageToPDF.submit=Convertir +imageToPDF.selectText.1=Étirer pour s'adapter +imageToPDF.selectText.2=Rotation automatique du PDF +imageToPDF.selectText.3=Logique de fichiers multiples (activé uniquement si vous travaillez avec plusieurs images) +imageToPDF.selectText.4= Fusionner en un seul PDF +imageToPDF.selectText.5= Convertir en PDFs distincts #pdfToImage pdfToImage.title=PDF vers image diff --git a/src/main/resources/templates/add-image.html b/src/main/resources/templates/add-image.html index 96662487..f6b67e5f 100644 --- a/src/main/resources/templates/add-image.html +++ b/src/main/resources/templates/add-image.html @@ -15,9 +15,9 @@

-
+
- +
diff --git a/src/main/resources/templates/compress-pdf.html b/src/main/resources/templates/compress-pdf.html index ad1b4eb9..64e1c6e8 100644 --- a/src/main/resources/templates/compress-pdf.html +++ b/src/main/resources/templates/compress-pdf.html @@ -15,7 +15,7 @@

-
+
- + + + +
+ +
+ +
+
+ + +
+
+ +
+ + +
+

- + +
diff --git a/src/main/resources/templates/convert/pdf-to-img.html b/src/main/resources/templates/convert/pdf-to-img.html index bfc70fc0..2b5cf199 100644 --- a/src/main/resources/templates/convert/pdf-to-img.html +++ b/src/main/resources/templates/convert/pdf-to-img.html @@ -16,7 +16,7 @@

-
+
diff --git a/src/main/resources/templates/fragments/common.html b/src/main/resources/templates/fragments/common.html index ad46b8c1..80b7c712 100644 --- a/src/main/resources/templates/fragments/common.html +++ b/src/main/resources/templates/fragments/common.html @@ -2,6 +2,7 @@ + @@ -63,10 +64,10 @@ function toggleDarkMode() { - +
- +
@@ -90,7 +91,9 @@ function toggleDarkMode() { event.preventDefault(); // Prevent the default form handling behavior /* Check if ${multiple} is false */ var multiple = [[${multiple}]] || false; - if (!multiple && files.length > 1) { + var override = $('#override').val() || ''; + console.log("override=" + override) + if (override === 'multi' || (!multiple && files.length > 1) && override !== 'single' ) { console.log("multi parallel download") submitMultiPdfForm(event,url); } else { @@ -208,8 +211,9 @@ function toggleDarkMode() { progressBar.attr('aria-valuenow', 0); progressBar.attr('aria-valuemax', files.length); - // Check the flag in localStorage - const zipFiles = localStorage.getItem('zipParallelFiles') === 'true'; + // Check the flag in localStorage, default to 4 + const zipThreshold = parseInt(localStorage.getItem('zipThreshold'), 10) || 4; + const zipFiles = files.length > zipThreshold; // Initialize JSZip instance if needed let jszip = null; @@ -355,6 +359,7 @@ function toggleDarkMode() { fileNames.forEach(fileName => { selectedFilesContainer.append("
" + fileName + "
"); }); + console.log("fileNames.length=" + fileNames.length) if (fileNames.length === 1) { $(inputElement).siblings(".custom-file-label").addClass("selected").html(fileNames[0]); } else if (fileNames.length > 1) { diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html index 1df0cc43..c6f95372 100644 --- a/src/main/resources/templates/fragments/navbar.html +++ b/src/main/resources/templates/fragments/navbar.html @@ -206,25 +206,24 @@ function compareVersions(version1, version2) {