mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	pdfjs worker changes and crop fix
This commit is contained in:
		
							parent
							
								
									e83a027023
								
							
						
					
					
						commit
						749461334d
					
				@ -90,7 +90,7 @@ public class CropController {
 | 
			
		||||
	@PostMapping(value = "/crop", consumes = "multipart/form-data")
 | 
			
		||||
	@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")
 | 
			
		||||
	public ResponseEntity<byte[]> cropPdf(
 | 
			
		||||
	        @Parameter(description = "The input PDF file", required = true) @RequestParam("file") MultipartFile file,
 | 
			
		||||
	        @Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
 | 
			
		||||
	        @Parameter(description = "The x-coordinate of the top-left corner of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("x") float x,
 | 
			
		||||
	        @Parameter(description = "The y-coordinate of the top-left corner of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("y") float y,
 | 
			
		||||
	        @Parameter(description = "The width of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("width") float width,
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,66 @@
 | 
			
		||||
package stirling.software.SPDF.controller.api.converters;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestPart;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Parameter;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
import stirling.software.SPDF.utils.ProcessExecutor;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@Tag(name = "Convert", description = "Convert APIs")
 | 
			
		||||
public class ConvertHtmlToPDF {
 | 
			
		||||
 | 
			
		||||
	@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-pdfa")
 | 
			
		||||
	@Operation(
 | 
			
		||||
	    summary = "Convert a PDF to a PDF/A",
 | 
			
		||||
	    description = "This endpoint converts a PDF file to a PDF/A file. PDF/A is a format designed for long-term archiving of digital documents. Input:PDF Output:PDF Type:SISO"
 | 
			
		||||
	)
 | 
			
		||||
	public ResponseEntity<byte[]> pdfToPdfA(
 | 
			
		||||
	    @RequestPart(required = true, value = "fileInput")
 | 
			
		||||
	    @Parameter(description = "The input PDF file to be converted to a PDF/A file", required = true)
 | 
			
		||||
	        MultipartFile inputFile) throws IOException, InterruptedException {
 | 
			
		||||
 | 
			
		||||
        // Save the uploaded file to a temporary location
 | 
			
		||||
        Path tempInputFile = Files.createTempFile("input_", ".pdf");
 | 
			
		||||
        inputFile.transferTo(tempInputFile.toFile());
 | 
			
		||||
 | 
			
		||||
        // Prepare the output file path
 | 
			
		||||
        Path tempOutputFile = Files.createTempFile("output_", ".pdf");
 | 
			
		||||
 | 
			
		||||
        // Prepare the OCRmyPDF command
 | 
			
		||||
        List<String> command = new ArrayList<>();
 | 
			
		||||
        command.add("ocrmypdf");
 | 
			
		||||
        command.add("--skip-text");
 | 
			
		||||
        command.add("--tesseract-timeout=0");
 | 
			
		||||
        command.add("--output-type");
 | 
			
		||||
        command.add("pdfa");
 | 
			
		||||
        command.add(tempInputFile.toString());
 | 
			
		||||
        command.add(tempOutputFile.toString());
 | 
			
		||||
 | 
			
		||||
        int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
 | 
			
		||||
 | 
			
		||||
        // Read the optimized PDF file
 | 
			
		||||
        byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
 | 
			
		||||
 | 
			
		||||
        // Clean up the temporary files
 | 
			
		||||
        Files.delete(tempInputFile);
 | 
			
		||||
        Files.delete(tempOutputFile);
 | 
			
		||||
 | 
			
		||||
        // Return the optimized PDF as a response
 | 
			
		||||
        String outputFilename = inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_PDFA.pdf";
 | 
			
		||||
        return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -126,7 +126,7 @@ home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
 | 
			
		||||
home.PDFToPresentation.title=PDF to Presentation
 | 
			
		||||
home.PDFToPresentation.desc=Convert PDF to Presentation formats (PPT, PPTX and ODP)
 | 
			
		||||
 | 
			
		||||
home.PDFToText.title=PDF to Text/RTF
 | 
			
		||||
home.PDFToText.title=PDF to RTF (Text)
 | 
			
		||||
home.PDFToText.desc=Convert PDF to Text or RTF format
 | 
			
		||||
 | 
			
		||||
home.PDFToHTML.title=PDF to HTML
 | 
			
		||||
@ -582,8 +582,8 @@ PDFToPresentation.submit=Convert
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#PDFToText
 | 
			
		||||
PDFToText.title=PDF to Text/RTF
 | 
			
		||||
PDFToText.header=PDF to Text/RTF
 | 
			
		||||
PDFToText.title=PDF to RTF (Text)
 | 
			
		||||
PDFToText.header=PDF to RTF (Text)
 | 
			
		||||
PDFToText.selectText.1=Output file format
 | 
			
		||||
PDFToText.credit=This service uses LibreOffice for file conversion.
 | 
			
		||||
PDFToText.submit=Convert
 | 
			
		||||
 | 
			
		||||
@ -594,7 +594,7 @@ PDFToPresentation.submit=변환
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#PDFToText
 | 
			
		||||
PDFToText.title=PDF to Text/RTF
 | 
			
		||||
PDFToText.title=PDF to RTF (Text)
 | 
			
		||||
PDFToText.header=PDF를 텍스트/RTF로 변환
 | 
			
		||||
PDFToText.selectText.1=출력 파일 형식
 | 
			
		||||
PDFToText.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.
 | 
			
		||||
 | 
			
		||||
@ -135,7 +135,7 @@ home.PDFToWord.desc=将PDF转换为Word格式(DOC、DOCX和ODT)。
 | 
			
		||||
home.PDFToPresentation.title=PDF To Presentation
 | 
			
		||||
home.PDFToPresentation.desc=将PDF转换成演示文稿格式(PPT、PPTX和ODP)。
 | 
			
		||||
 | 
			
		||||
home.PDFToText.title=PDF To Text/RTF
 | 
			
		||||
home.PDFToText.title=PDF to RTF (Text)
 | 
			
		||||
home.PDFToText.desc=将PDF转换为文本或RTF格式
 | 
			
		||||
 | 
			
		||||
home.PDFToHTML.title=PDF To HTML
 | 
			
		||||
@ -594,7 +594,7 @@ PDFToPresentation.submit=转换
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#PDFToText
 | 
			
		||||
PDFToText.title=PDF To Text/RTF
 | 
			
		||||
PDFToText.title=PDF to RTF (Text)
 | 
			
		||||
PDFToText.header=将PDF转换成文本/RTF
 | 
			
		||||
PDFToText.selectText.1=输出文件格式
 | 
			
		||||
PDFToText.credit=该服务使用LibreOffice进行文件转换。
 | 
			
		||||
 | 
			
		||||
@ -70,3 +70,13 @@ html[lang-direction="rtl"] label.form-check-label {
 | 
			
		||||
    box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
 | 
			
		||||
    width: 100%;
 | 
			
		||||
}
 | 
			
		||||
.fixed-shadow-canvas {
 | 
			
		||||
    box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
 | 
			
		||||
    width: 100%;
 | 
			
		||||
}
 | 
			
		||||
.shadow-canvas {
 | 
			
		||||
    box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
 | 
			
		||||
}
 | 
			
		||||
.hidden {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
@ -120,6 +120,7 @@ class PdfContainer {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async toRenderer(objectUrl) {
 | 
			
		||||
		pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
        const pdf = await pdfjsLib.getDocument(objectUrl).promise;
 | 
			
		||||
        return {
 | 
			
		||||
            document: pdf,
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,6 @@
 | 
			
		||||
                                <label th:text="#{PDFToText.selectText.1}"></label> 
 | 
			
		||||
                                <select class="form-control" name="outputFormat">
 | 
			
		||||
                                    <option value="rtf">RTF</option>
 | 
			
		||||
                                    <option value="txt:Text">TXT</option>
 | 
			
		||||
                                </select>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <br>
 | 
			
		||||
 | 
			
		||||
@ -22,13 +22,13 @@
 | 
			
		||||
              <button type="submit" class="btn btn-primary" th:text="#{crop.submit}"></button>
 | 
			
		||||
            </form>
 | 
			
		||||
            <div style="position: relative; display: inline-block;">
 | 
			
		||||
			    <canvas id="pdf-canvas" style="position: absolute; top: 0; left: 0; z-index: 1;"></canvas>
 | 
			
		||||
			    <canvas id="crop-pdf-canvas" style="position: absolute; top: 0; left: 0; z-index: 1;"></canvas>
 | 
			
		||||
			    <canvas id="overlayCanvas" style="position: absolute; top: 0; left: 0; z-index: 2;"></canvas>
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
            <script>
 | 
			
		||||
            
 | 
			
		||||
            let pdfCanvas  = document.getElementById('pdf-canvas');
 | 
			
		||||
            let pdfCanvas  = document.getElementById('crop-pdf-canvas');
 | 
			
		||||
            let overlayCanvas = document.getElementById('overlayCanvas');
 | 
			
		||||
 | 
			
		||||
            let context = pdfCanvas.getContext('2d');
 | 
			
		||||
@ -61,6 +61,7 @@
 | 
			
		||||
                let reader = new FileReader();
 | 
			
		||||
                reader.onload = function(ev) {
 | 
			
		||||
                  let typedArray = new Uint8Array(reader.result);
 | 
			
		||||
                  pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
                  pdfjsLib.getDocument(typedArray).promise.then(function(pdf) {
 | 
			
		||||
                    pdfDoc = pdf;
 | 
			
		||||
                    totalPages = pdf.numPages;
 | 
			
		||||
@ -126,6 +127,7 @@
 | 
			
		||||
                    
 | 
			
		||||
                    let renderContext = { canvasContext: context, viewport: viewport };
 | 
			
		||||
                    page.render(renderContext);
 | 
			
		||||
                    pdfCanvas.classList.add("shadow-canvas");
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
           
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,7 @@
 | 
			
		||||
                                if (file) {
 | 
			
		||||
                                	originalFileName = file.name.replace(/\.[^/.]+$/, "");
 | 
			
		||||
                                    const pdfData = await file.arrayBuffer();
 | 
			
		||||
                                    pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
                                    const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise;
 | 
			
		||||
                                    await DraggableUtils.renderPage(pdfDoc, 0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,37 +14,50 @@
 | 
			
		||||
			<br> <br>
 | 
			
		||||
			<div class="container">
 | 
			
		||||
				<div class="row justify-content-center">
 | 
			
		||||
					<div class="col-md-6">
 | 
			
		||||
						<h2 th:text="#{adjustContrast.header}"></h2>
 | 
			
		||||
						<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
 | 
			
		||||
					<div class="col-md-12">
 | 
			
		||||
                        <div class="row justify-content-center">
 | 
			
		||||
                            <div class="col-md-3">
 | 
			
		||||
                                <div id="sliders-container" style="display:none;">
 | 
			
		||||
                                    <h4>
 | 
			
		||||
                                        <span th:text="#{adjustContrast.contrast}"></span> <span id="contrast-val">100</span>%
 | 
			
		||||
                                    </h4>
 | 
			
		||||
						<input type="range" min="0" max="200" value="100"
 | 
			
		||||
							id="contrast-slider" />
 | 
			
		||||
                                    <input type="range" min="0" max="200" value="100" id="contrast-slider" />
 | 
			
		||||
 | 
			
		||||
                                    <h4>
 | 
			
		||||
                                        <span th:text="#{adjustContrast.brightness}"></span> <span id="brightness-val">100</span>%
 | 
			
		||||
                                    </h4>
 | 
			
		||||
						<input type="range" min="0" max="200" value="100"
 | 
			
		||||
							id="brightness-slider" />
 | 
			
		||||
                                    <input type="range" min="0" max="200" value="100" id="brightness-slider" />
 | 
			
		||||
 | 
			
		||||
                                    <h4>
 | 
			
		||||
                                        <span th:text="#{adjustContrast.saturation}"></span> <span id="saturation-val">100</span>%
 | 
			
		||||
                                    </h4>
 | 
			
		||||
						<input type="range" min="0" max="200" value="100"
 | 
			
		||||
							id="saturation-slider" />
 | 
			
		||||
							
 | 
			
		||||
							</br>
 | 
			
		||||
						<canvas id="pdf-canvas"></canvas>
 | 
			
		||||
 | 
			
		||||
						
 | 
			
		||||
 | 
			
		||||
                                    <input type="range" min="0" max="200" value="100" id="saturation-slider" />
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div class="col-md-7">
 | 
			
		||||
                                <h2 th:text="#{adjustContrast.header}"></h2>
 | 
			
		||||
                                <div class="col-md-8">
 | 
			
		||||
                                    <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <br>
 | 
			
		||||
                                <canvas id="contrast-pdf-canvas"></canvas>
 | 
			
		||||
                                <button id="download-button" class="btn btn-primary" th:text="#{adjustContrast.download}"></button>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <style>
 | 
			
		||||
                            #flex-container {
 | 
			
		||||
					            display: flex;
 | 
			
		||||
					            align-items: center;
 | 
			
		||||
					        }
 | 
			
		||||
					        #sliders-container {
 | 
			
		||||
					            padding: 0 20px;  /* Add some padding to separate sliders from canvas */
 | 
			
		||||
					        }
 | 
			
		||||
                        </style>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
						<script src="pdfjs/pdf.js"></script>
 | 
			
		||||
						<script>
 | 
			
		||||
						  var canvas = document.getElementById('pdf-canvas');
 | 
			
		||||
						  var canvas = document.getElementById('contrast-pdf-canvas');
 | 
			
		||||
						  var context = canvas.getContext('2d');
 | 
			
		||||
						  var originalImageData = null;
 | 
			
		||||
						  var allPages = [];
 | 
			
		||||
@ -55,6 +68,7 @@
 | 
			
		||||
						    var fileReader = new FileReader();
 | 
			
		||||
						    fileReader.onload = async function() {
 | 
			
		||||
						      var data = new Uint8Array(this.result);
 | 
			
		||||
						      pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
						      pdf = await pdfjsLib.getDocument({data: data}).promise;
 | 
			
		||||
						
 | 
			
		||||
						      // Get the number of pages in the PDF
 | 
			
		||||
@ -65,6 +79,8 @@
 | 
			
		||||
						      pdfDoc = await PDFLib.PDFDocument.create();
 | 
			
		||||
						      // Render the first page in the viewer
 | 
			
		||||
						      await renderPageAndAdjustImageProperties(1);
 | 
			
		||||
						      document.getElementById("sliders-container").style.display = "block";
 | 
			
		||||
						      
 | 
			
		||||
						    };
 | 
			
		||||
						    fileReader.readAsArrayBuffer(file);
 | 
			
		||||
						  }
 | 
			
		||||
@ -90,6 +106,7 @@
 | 
			
		||||
						            adjustImageProperties();
 | 
			
		||||
						            resolve();
 | 
			
		||||
						          });
 | 
			
		||||
						          canvas.classList.add("fixed-shadow-canvas");
 | 
			
		||||
						      });
 | 
			
		||||
						  }
 | 
			
		||||
						  
 | 
			
		||||
 | 
			
		||||
@ -145,7 +145,7 @@
 | 
			
		||||
	  
 | 
			
		||||
    const file = this.files[0];
 | 
			
		||||
    var url = URL.createObjectURL(file)
 | 
			
		||||
 | 
			
		||||
	pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
    const pdf = await pdfjsLib.getDocument(url).promise;
 | 
			
		||||
    const pdfMetadata = await pdf.getMetadata();
 | 
			
		||||
    lastPDFFile = pdfMetadata?.info
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,7 @@
 | 
			
		||||
                                console.error("Please select two PDF files to compare");
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
                            
 | 
			
		||||
                            pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
                            const [pdf1, pdf2] = await Promise.all([
 | 
			
		||||
                                pdfjsLib.getDocument(URL.createObjectURL(file1)).promise,
 | 
			
		||||
                                pdfjsLib.getDocument(URL.createObjectURL(file2)).promise
 | 
			
		||||
 | 
			
		||||
@ -59,7 +59,7 @@
 | 
			
		||||
			document.querySelector("#editSection").style.display = "";
 | 
			
		||||
 | 
			
		||||
			var url = URL.createObjectURL(fileInput.files[0])
 | 
			
		||||
 | 
			
		||||
			pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
			const pdf = await pdfjsLib.getDocument(url).promise;
 | 
			
		||||
			const page = await pdf.getPage(1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,7 @@ select#font-select, select#font-select option {
 | 
			
		||||
                                if (file) {
 | 
			
		||||
                                	originalFileName = file.name.replace(/\.[^/.]+$/, "");
 | 
			
		||||
                                    const pdfData = await file.arrayBuffer();
 | 
			
		||||
                                    pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
 | 
			
		||||
                                    const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise;
 | 
			
		||||
                                    await DraggableUtils.renderPage(pdfDoc, 0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user