Merge pull request #607 from Frooodle/overlay
overlay fix for sequential
This commit is contained in:
commit
7fecae8b0d
1 changed files with 99 additions and 51 deletions
|
@ -3,8 +3,9 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.apache.pdfbox.multipdf.Overlay;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -25,7 +26,7 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||
@Tag(name = "General", description = "General APIs")
|
||||
public class PdfOverlayController {
|
||||
|
||||
@PostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data")
|
||||
@PostMapping(value = "/overlay-pdfs", consumes = "multipart/form-data")
|
||||
@Operation(summary = "Overlay PDF files in various modes", description = "Overlay PDF files onto a base PDF with different modes: Sequential, Interleaved, or Fixed Repeat. Input:PDF Output:PDF Type:MIMO")
|
||||
public ResponseEntity<byte[]> overlayPdfs(@ModelAttribute OverlayPdfsRequest request) throws IOException {
|
||||
MultipartFile baseFile = request.getFileInput();
|
||||
|
@ -33,44 +34,53 @@ public class PdfOverlayController {
|
|||
|
||||
MultipartFile[] overlayFiles = request.getOverlayFiles();
|
||||
File[] overlayPdfFiles = new File[overlayFiles.length];
|
||||
try{
|
||||
for (int i = 0; i < overlayFiles.length; i++) {
|
||||
overlayPdfFiles[i] = GeneralUtils.multipartToFile(overlayFiles[i]);
|
||||
}
|
||||
|
||||
String mode = request.getOverlayMode(); // "SequentialOverlay", "InterleavedOverlay", "FixedRepeatOverlay"
|
||||
int[] counts = request.getCounts(); // Used for FixedRepeatOverlay mode
|
||||
|
||||
try (PDDocument basePdf = PDDocument.load(baseFile.getInputStream());
|
||||
Overlay overlay = new Overlay()) {
|
||||
Map<Integer, String> overlayGuide = prepareOverlayGuide(basePdf.getNumberOfPages(), overlayPdfFiles, mode, counts);
|
||||
|
||||
overlay.setInputPDF(basePdf);
|
||||
if(overlayPos == 0) {
|
||||
overlay.setOverlayPosition(Overlay.Position.FOREGROUND);
|
||||
} else {
|
||||
overlay.setOverlayPosition(Overlay.Position.BACKGROUND);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
overlay.overlay(overlayGuide).save(outputStream);
|
||||
byte[] data = outputStream.toByteArray();
|
||||
String outputFilename = baseFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_overlayed.pdf"; // Remove file extension and append .pdf
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(data, outputFilename, MediaType.APPLICATION_PDF);
|
||||
}
|
||||
List<File> tempFiles = new ArrayList<>(); // List to keep track of temporary files
|
||||
|
||||
try {
|
||||
for (int i = 0; i < overlayFiles.length; i++) {
|
||||
overlayPdfFiles[i] = GeneralUtils.multipartToFile(overlayFiles[i]);
|
||||
}
|
||||
|
||||
String mode = request.getOverlayMode(); // "SequentialOverlay", "InterleavedOverlay", "FixedRepeatOverlay"
|
||||
int[] counts = request.getCounts(); // Used for FixedRepeatOverlay mode
|
||||
|
||||
try (PDDocument basePdf = PDDocument.load(baseFile.getInputStream());
|
||||
Overlay overlay = new Overlay()) {
|
||||
Map<Integer, String> overlayGuide = prepareOverlayGuide(basePdf.getNumberOfPages(), overlayPdfFiles, mode, counts, tempFiles);
|
||||
|
||||
overlay.setInputPDF(basePdf);
|
||||
if (overlayPos == 0) {
|
||||
overlay.setOverlayPosition(Overlay.Position.FOREGROUND);
|
||||
} else {
|
||||
overlay.setOverlayPosition(Overlay.Position.BACKGROUND);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
overlay.overlay(overlayGuide).save(outputStream);
|
||||
byte[] data = outputStream.toByteArray();
|
||||
String outputFilename = baseFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_overlayed.pdf"; // Remove file extension and append .pdf
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(data, outputFilename, MediaType.APPLICATION_PDF);
|
||||
}
|
||||
} finally {
|
||||
for (File overlayPdfFile : overlayPdfFiles) {
|
||||
if (overlayPdfFile != null) overlayPdfFile.delete();
|
||||
if (overlayPdfFile != null) {
|
||||
overlayPdfFile.delete();
|
||||
}
|
||||
}
|
||||
for (File tempFile : tempFiles) { // Delete temporary files
|
||||
if (tempFile != null) {
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Integer, String> prepareOverlayGuide(int basePageCount, File[] overlayFiles, String mode, int[] counts) throws IOException {
|
||||
private Map<Integer, String> prepareOverlayGuide(int basePageCount, File[] overlayFiles, String mode, int[] counts, List<File> tempFiles) throws IOException {
|
||||
Map<Integer, String> overlayGuide = new HashMap<>();
|
||||
switch (mode) {
|
||||
case "SequentialOverlay":
|
||||
sequentialOverlay(overlayGuide, overlayFiles, basePageCount);
|
||||
sequentialOverlay(overlayGuide, overlayFiles, basePageCount, tempFiles);
|
||||
break;
|
||||
case "InterleavedOverlay":
|
||||
interleavedOverlay(overlayGuide, overlayFiles, basePageCount);
|
||||
|
@ -84,42 +94,80 @@ public class PdfOverlayController {
|
|||
return overlayGuide;
|
||||
}
|
||||
|
||||
private void sequentialOverlay(Map<Integer, String> overlayGuide, File[] overlayFiles, int basePageCount) throws IOException {
|
||||
if (overlayFiles.length != 1 || basePageCount != PDDocument.load(overlayFiles[0]).getNumberOfPages()) {
|
||||
throw new IllegalArgumentException("Overlay file count and base page count must match for sequential overlay.");
|
||||
}
|
||||
private void sequentialOverlay(Map<Integer, String> overlayGuide, File[] overlayFiles, int basePageCount, List<File> tempFiles) throws IOException {
|
||||
int overlayFileIndex = 0;
|
||||
int pageCountInCurrentOverlay = 0;
|
||||
|
||||
File overlayFile = overlayFiles[0];
|
||||
try (PDDocument overlayPdf = PDDocument.load(overlayFile)) {
|
||||
for (int i = 1; i <= overlayPdf.getNumberOfPages(); i++) {
|
||||
if (i > basePageCount) break;
|
||||
overlayGuide.put(i, overlayFile.getAbsolutePath());
|
||||
for (int basePageIndex = 1; basePageIndex <= basePageCount; basePageIndex++) {
|
||||
if (pageCountInCurrentOverlay == 0 || pageCountInCurrentOverlay >= getNumberOfPages(overlayFiles[overlayFileIndex])) {
|
||||
pageCountInCurrentOverlay = 0;
|
||||
overlayFileIndex = (overlayFileIndex + 1) % overlayFiles.length;
|
||||
}
|
||||
|
||||
try (PDDocument overlayPdf = PDDocument.load(overlayFiles[overlayFileIndex])) {
|
||||
PDDocument singlePageDocument = new PDDocument();
|
||||
singlePageDocument.addPage(overlayPdf.getPage(pageCountInCurrentOverlay));
|
||||
File tempFile = File.createTempFile("overlay-page-", ".pdf");
|
||||
singlePageDocument.save(tempFile);
|
||||
singlePageDocument.close();
|
||||
|
||||
overlayGuide.put(basePageIndex, tempFile.getAbsolutePath());
|
||||
tempFiles.add(tempFile); // Keep track of the temporary file for cleanup
|
||||
}
|
||||
|
||||
pageCountInCurrentOverlay++;
|
||||
}
|
||||
}
|
||||
|
||||
private int getNumberOfPages(File file) throws IOException {
|
||||
try (PDDocument doc = PDDocument.load(file)) {
|
||||
return doc.getNumberOfPages();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void interleavedOverlay(Map<Integer, String> overlayGuide, File[] overlayFiles, int basePageCount) throws IOException {
|
||||
for (int basePageIndex = 1; basePageIndex <= basePageCount; basePageIndex++) {
|
||||
File overlayFile = overlayFiles[(basePageIndex - 1) % overlayFiles.length];
|
||||
|
||||
// Load the overlay document to check its page count
|
||||
try (PDDocument overlayPdf = PDDocument.load(overlayFile)) {
|
||||
int overlayPageCount = overlayPdf.getNumberOfPages();
|
||||
if ((basePageIndex - 1) % overlayPageCount < overlayPageCount) {
|
||||
overlayGuide.put(basePageIndex, overlayFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void interleavedOverlay(Map<Integer, String> overlayGuide, File[] overlayFiles, int basePageCount) throws IOException {
|
||||
for (int i = 0; i < basePageCount; i++) {
|
||||
File overlayFile = overlayFiles[i % overlayFiles.length];
|
||||
overlayGuide.put(i + 1, overlayFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
private void fixedRepeatOverlay(Map<Integer, String> overlayGuide, File[] overlayFiles, int[] counts, int basePageCount) throws IOException {
|
||||
if (overlayFiles.length != counts.length) {
|
||||
throw new IllegalArgumentException("Counts array length must match the number of overlay files");
|
||||
}
|
||||
int currentPage = 1;
|
||||
for (int i = 0; i < overlayFiles.length; i++) {
|
||||
File overlayFile = overlayFiles[i];
|
||||
File overlayFile = overlayFiles[i];
|
||||
int repeatCount = counts[i];
|
||||
for (int j = 0; j < repeatCount; j++) {
|
||||
if (currentPage > basePageCount) break;
|
||||
overlayGuide.put(currentPage++, overlayFile.getAbsolutePath());
|
||||
|
||||
// Load the overlay document to check its page count
|
||||
try (PDDocument overlayPdf = PDDocument.load(overlayFile)) {
|
||||
int overlayPageCount = overlayPdf.getNumberOfPages();
|
||||
for (int j = 0; j < repeatCount; j++) {
|
||||
for (int page = 0; page < overlayPageCount; page++) {
|
||||
if (currentPage > basePageCount) break;
|
||||
overlayGuide.put(currentPage++, overlayFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Additional classes like OverlayPdfsRequest, WebResponseUtils, etc. are assumed to be defined elsewhere.
|
||||
|
|
Loading…
Reference in a new issue