command =
+ List.of(
+ "gs",
+ "-sDEVICE=pdfwrite",
+ "-dUseCropBox",
+ "-o",
+ tempOutputFile.toString(),
+ tempInputFile.toString());
+
+ processExecutor.runCommandWithOutputHandling(command);
+
+ byte[] pdfContent = Files.readAllBytes(tempOutputFile);
+
+ return WebResponseUtils.bytesToWebResponse(
+ pdfContent,
+ request.getFileInput().getOriginalFilename().replaceFirst("[.][^.]+$", "")
+ + "_cropped.pdf");
+
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new IOException("Ghostscript processing was interrupted", e);
+ } finally {
+ try {
+ Files.deleteIfExists(tempInputFile);
+ Files.deleteIfExists(tempOutputFile);
+ } catch (IOException e) {
+ log.debug("Failed to delete temporary files", e);
+ }
+ }
+ }
}
diff --git a/app/core/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java b/app/core/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java
index 913f94a10..480169468 100644
--- a/app/core/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java
+++ b/app/core/src/main/java/stirling/software/SPDF/model/api/general/CropPdfForm.java
@@ -26,4 +26,9 @@ public class CropPdfForm extends PDFFile {
@Schema(description = "The height of the crop area", type = "number")
private float height;
+
+ @Schema(
+ description = "Whether to remove text outside the crop area (keeps images)",
+ type = "boolean")
+ private boolean removeDataOutsideCrop = true;
}
diff --git a/app/core/src/main/resources/templates/crop.html b/app/core/src/main/resources/templates/crop.html
index 0617bf9b6..e91c481c3 100644
--- a/app/core/src/main/resources/templates/crop.html
+++ b/app/core/src/main/resources/templates/crop.html
@@ -22,6 +22,7 @@
+
diff --git a/testing/webpage_urls.txt b/testing/webpage_urls.txt
index c6c713dd0..6e7874eca 100644
--- a/testing/webpage_urls.txt
+++ b/testing/webpage_urls.txt
@@ -8,7 +8,6 @@
/pdf-organizer
/multi-page-layout
/scale-pages
-/crop
/extract-page
/pdf-to-single-page
/img-to-pdf