1
0
mirror of https://github.com/Stirling-Tools/Stirling-PDF.git synced 2024-09-28 23:51:56 +02:00

pdfjs worker changes and crop fix

This commit is contained in:
Anthony Stirling 2023-07-22 13:17:24 +01:00
parent e83a027023
commit 749461334d
15 changed files with 1093 additions and 996 deletions

View File

@ -90,7 +90,7 @@ public class CropController {
@PostMapping(value = "/crop", consumes = "multipart/form-data") @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") @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( 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 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 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, @Parameter(description = "The width of the crop area", required = true, schema = @Schema(type = "number")) @RequestParam("width") float width,

View File

@ -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);
}
}

View File

@ -126,7 +126,7 @@ home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
home.PDFToPresentation.title=PDF to Presentation home.PDFToPresentation.title=PDF to Presentation
home.PDFToPresentation.desc=Convert PDF to Presentation formats (PPT, PPTX and ODP) 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.PDFToText.desc=Convert PDF to Text or RTF format
home.PDFToHTML.title=PDF to HTML home.PDFToHTML.title=PDF to HTML
@ -582,8 +582,8 @@ PDFToPresentation.submit=Convert
#PDFToText #PDFToText
PDFToText.title=PDF to Text/RTF PDFToText.title=PDF to RTF (Text)
PDFToText.header=PDF to Text/RTF PDFToText.header=PDF to RTF (Text)
PDFToText.selectText.1=Output file format PDFToText.selectText.1=Output file format
PDFToText.credit=This service uses LibreOffice for file conversion. PDFToText.credit=This service uses LibreOffice for file conversion.
PDFToText.submit=Convert PDFToText.submit=Convert

View File

@ -594,7 +594,7 @@ PDFToPresentation.submit=변환
#PDFToText #PDFToText
PDFToText.title=PDF to Text/RTF PDFToText.title=PDF to RTF (Text)
PDFToText.header=PDF를 텍스트/RTF로 변환 PDFToText.header=PDF를 텍스트/RTF로 변환
PDFToText.selectText.1=출력 파일 형식 PDFToText.selectText.1=출력 파일 형식
PDFToText.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다. PDFToText.credit=이 서비스는 파일 변환을 위해 LibreOffice를 사용합니다.

View File

@ -135,7 +135,7 @@ home.PDFToWord.desc=将PDF转换为Word格式DOC、DOCX和ODT
home.PDFToPresentation.title=PDF To Presentation home.PDFToPresentation.title=PDF To Presentation
home.PDFToPresentation.desc=将PDF转换成演示文稿格式PPT、PPTX和ODP 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.PDFToText.desc=将PDF转换为文本或RTF格式
home.PDFToHTML.title=PDF To HTML home.PDFToHTML.title=PDF To HTML
@ -594,7 +594,7 @@ PDFToPresentation.submit=转换
#PDFToText #PDFToText
PDFToText.title=PDF To Text/RTF PDFToText.title=PDF to RTF (Text)
PDFToText.header=将PDF转换成文本/RTF PDFToText.header=将PDF转换成文本/RTF
PDFToText.selectText.1=输出文件格式 PDFToText.selectText.1=输出文件格式
PDFToText.credit=该服务使用LibreOffice进行文件转换。 PDFToText.credit=该服务使用LibreOffice进行文件转换。

View File

@ -70,3 +70,13 @@ html[lang-direction="rtl"] label.form-check-label {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384); box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%; 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;
}

View File

@ -120,6 +120,7 @@ class PdfContainer {
} }
async toRenderer(objectUrl) { async toRenderer(objectUrl) {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdf = await pdfjsLib.getDocument(objectUrl).promise; const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return { return {
document: pdf, document: pdf,

View File

@ -19,7 +19,6 @@
<label th:text="#{PDFToText.selectText.1}"></label> <label th:text="#{PDFToText.selectText.1}"></label>
<select class="form-control" name="outputFormat"> <select class="form-control" name="outputFormat">
<option value="rtf">RTF</option> <option value="rtf">RTF</option>
<option value="txt:Text">TXT</option>
</select> </select>
</div> </div>
<br> <br>

View File

@ -22,13 +22,13 @@
<button type="submit" class="btn btn-primary" th:text="#{crop.submit}"></button> <button type="submit" class="btn btn-primary" th:text="#{crop.submit}"></button>
</form> </form>
<div style="position: relative; display: inline-block;"> <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> <canvas id="overlayCanvas" style="position: absolute; top: 0; left: 0; z-index: 2;"></canvas>
</div> </div>
<script> <script>
let pdfCanvas = document.getElementById('pdf-canvas'); let pdfCanvas = document.getElementById('crop-pdf-canvas');
let overlayCanvas = document.getElementById('overlayCanvas'); let overlayCanvas = document.getElementById('overlayCanvas');
let context = pdfCanvas.getContext('2d'); let context = pdfCanvas.getContext('2d');
@ -61,6 +61,7 @@
let reader = new FileReader(); let reader = new FileReader();
reader.onload = function(ev) { reader.onload = function(ev) {
let typedArray = new Uint8Array(reader.result); let typedArray = new Uint8Array(reader.result);
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
pdfjsLib.getDocument(typedArray).promise.then(function(pdf) { pdfjsLib.getDocument(typedArray).promise.then(function(pdf) {
pdfDoc = pdf; pdfDoc = pdf;
totalPages = pdf.numPages; totalPages = pdf.numPages;
@ -126,6 +127,7 @@
let renderContext = { canvasContext: context, viewport: viewport }; let renderContext = { canvasContext: context, viewport: viewport };
page.render(renderContext); page.render(renderContext);
pdfCanvas.classList.add("shadow-canvas");
}); });
} }

View File

@ -25,6 +25,7 @@
if (file) { if (file) {
originalFileName = file.name.replace(/\.[^/.]+$/, ""); originalFileName = file.name.replace(/\.[^/.]+$/, "");
const pdfData = await file.arrayBuffer(); const pdfData = await file.arrayBuffer();
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise; const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise;
await DraggableUtils.renderPage(pdfDoc, 0); await DraggableUtils.renderPage(pdfDoc, 0);

View File

@ -14,37 +14,50 @@
<br> <br> <br> <br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-12">
<h2 th:text="#{adjustContrast.header}"></h2> <div class="row justify-content-center">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div> <div class="col-md-3">
<div id="sliders-container" style="display:none;">
<h4> <h4>
<span th:text="#{adjustContrast.contrast}"></span> <span id="contrast-val">100</span>% <span th:text="#{adjustContrast.contrast}"></span> <span id="contrast-val">100</span>%
</h4> </h4>
<input type="range" min="0" max="200" value="100" <input type="range" min="0" max="200" value="100" id="contrast-slider" />
id="contrast-slider" />
<h4> <h4>
<span th:text="#{adjustContrast.brightness}"></span> <span id="brightness-val">100</span>% <span th:text="#{adjustContrast.brightness}"></span> <span id="brightness-val">100</span>%
</h4> </h4>
<input type="range" min="0" max="200" value="100" <input type="range" min="0" max="200" value="100" id="brightness-slider" />
id="brightness-slider" />
<h4> <h4>
<span th:text="#{adjustContrast.saturation}"></span> <span id="saturation-val">100</span>% <span th:text="#{adjustContrast.saturation}"></span> <span id="saturation-val">100</span>%
</h4> </h4>
<input type="range" min="0" max="200" value="100" <input type="range" min="0" max="200" value="100" id="saturation-slider" />
id="saturation-slider" /> </div>
</div>
</br> <div class="col-md-7">
<canvas id="pdf-canvas"></canvas> <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> <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 src="pdfjs/pdf.js"></script>
<script> <script>
var canvas = document.getElementById('pdf-canvas'); var canvas = document.getElementById('contrast-pdf-canvas');
var context = canvas.getContext('2d'); var context = canvas.getContext('2d');
var originalImageData = null; var originalImageData = null;
var allPages = []; var allPages = [];
@ -55,6 +68,7 @@
var fileReader = new FileReader(); var fileReader = new FileReader();
fileReader.onload = async function() { fileReader.onload = async function() {
var data = new Uint8Array(this.result); var data = new Uint8Array(this.result);
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
pdf = await pdfjsLib.getDocument({data: data}).promise; pdf = await pdfjsLib.getDocument({data: data}).promise;
// Get the number of pages in the PDF // Get the number of pages in the PDF
@ -65,6 +79,8 @@
pdfDoc = await PDFLib.PDFDocument.create(); pdfDoc = await PDFLib.PDFDocument.create();
// Render the first page in the viewer // Render the first page in the viewer
await renderPageAndAdjustImageProperties(1); await renderPageAndAdjustImageProperties(1);
document.getElementById("sliders-container").style.display = "block";
}; };
fileReader.readAsArrayBuffer(file); fileReader.readAsArrayBuffer(file);
} }
@ -90,6 +106,7 @@
adjustImageProperties(); adjustImageProperties();
resolve(); resolve();
}); });
canvas.classList.add("fixed-shadow-canvas");
}); });
} }

View File

@ -145,7 +145,7 @@
const file = this.files[0]; const file = this.files[0];
var url = URL.createObjectURL(file) var url = URL.createObjectURL(file)
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdf = await pdfjsLib.getDocument(url).promise; const pdf = await pdfjsLib.getDocument(url).promise;
const pdfMetadata = await pdf.getMetadata(); const pdfMetadata = await pdf.getMetadata();
lastPDFFile = pdfMetadata?.info lastPDFFile = pdfMetadata?.info

View File

@ -61,7 +61,7 @@
console.error("Please select two PDF files to compare"); console.error("Please select two PDF files to compare");
return; return;
} }
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const [pdf1, pdf2] = await Promise.all([ const [pdf1, pdf2] = await Promise.all([
pdfjsLib.getDocument(URL.createObjectURL(file1)).promise, pdfjsLib.getDocument(URL.createObjectURL(file1)).promise,
pdfjsLib.getDocument(URL.createObjectURL(file2)).promise pdfjsLib.getDocument(URL.createObjectURL(file2)).promise

View File

@ -59,7 +59,7 @@
document.querySelector("#editSection").style.display = ""; document.querySelector("#editSection").style.display = "";
var url = URL.createObjectURL(fileInput.files[0]) var url = URL.createObjectURL(fileInput.files[0])
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdf = await pdfjsLib.getDocument(url).promise; const pdf = await pdfjsLib.getDocument(url).promise;
const page = await pdf.getPage(1); const page = await pdf.getPage(1);

View File

@ -47,6 +47,7 @@ select#font-select, select#font-select option {
if (file) { if (file) {
originalFileName = file.name.replace(/\.[^/.]+$/, ""); originalFileName = file.name.replace(/\.[^/.]+$/, "");
const pdfData = await file.arrayBuffer(); const pdfData = await file.arrayBuffer();
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise; const pdfDoc = await pdfjsLib.getDocument({ data: pdfData }).promise;
await DraggableUtils.renderPage(pdfDoc, 0); await DraggableUtils.renderPage(pdfDoc, 0);