mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	Merge pull request #607 from Frooodle/overlay
overlay fix for sequential
This commit is contained in:
		
						commit
						7fecae8b0d
					
				@ -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 New Issue
	
	Block a user