diff --git a/app/core/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java b/app/core/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java index 6697beb79..7d1b68b25 100644 --- a/app/core/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java +++ b/app/core/src/main/java/stirling/software/SPDF/Factories/ReplaceAndInvertColorFactory.java @@ -5,6 +5,7 @@ import org.springframework.web.multipart.MultipartFile; import lombok.RequiredArgsConstructor; +import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.common.model.api.misc.HighContrastColorCombination; import stirling.software.common.model.api.misc.ReplaceAndInvert; import stirling.software.common.util.TempFileManager; @@ -18,6 +19,7 @@ import stirling.software.common.util.misc.ReplaceAndInvertColorStrategy; public class ReplaceAndInvertColorFactory { private final TempFileManager tempFileManager; + private final EndpointConfiguration endpointConfiguration; public ReplaceAndInvertColorStrategy replaceAndInvert( MultipartFile file, @@ -26,6 +28,13 @@ public class ReplaceAndInvertColorFactory { String backGroundColor, String textColor) { + // Check Ghostscript availability for CMYK conversion + if (replaceAndInvertOption == ReplaceAndInvert.COLOR_SPACE_CONVERSION + && !endpointConfiguration.isGroupEnabled("Ghostscript")) { + throw new IllegalStateException( + "CMYK color space conversion requires Ghostscript, which is not available on this system"); + } + return switch (replaceAndInvertOption) { case CUSTOM_COLOR, HIGH_CONTRAST_COLOR -> new CustomColorReplaceStrategy( diff --git a/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java b/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java index edb2e96cf..2b4fa32d9 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/EndpointConfiguration.java @@ -403,8 +403,6 @@ public class EndpointConfiguration { /* Ghostscript */ addEndpointToGroup("Ghostscript", "repair"); addEndpointToGroup("Ghostscript", "compress-pdf"); - addEndpointToGroup("Ghostscript", "crop"); - addEndpointToGroup("Ghostscript", "replace-invert-pdf"); /* tesseract */ addEndpointToGroup("tesseract", "ocr-pdf"); diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java index 17c3b28ea..63642df4a 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/CropController.java @@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import stirling.software.SPDF.config.EndpointConfiguration; import stirling.software.SPDF.config.swagger.StandardPdfResponse; import stirling.software.SPDF.model.api.general.CropPdfForm; import stirling.software.common.annotations.AutoJobPostMapping; @@ -37,6 +38,11 @@ import stirling.software.common.util.WebResponseUtils; public class CropController { private final CustomPDFDocumentFactory pdfDocumentFactory; + private final EndpointConfiguration endpointConfiguration; + + private boolean isGhostscriptEnabled() { + return endpointConfiguration.isGroupEnabled("Ghostscript"); + } @AutoJobPostMapping(value = "/crop", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @StandardPdfResponse @@ -46,9 +52,13 @@ public class CropController { "This operation takes an input PDF file and crops it according to the given" + " coordinates. Input:PDF Output:PDF Type:SISO") public ResponseEntity cropPdf(@ModelAttribute CropPdfForm request) throws IOException { - if (request.isRemoveDataOutsideCrop()) { + if (request.isRemoveDataOutsideCrop() && isGhostscriptEnabled()) { return cropWithGhostscript(request); } else { + if (request.isRemoveDataOutsideCrop()) { + log.warn( + "Ghostscript not available - 'removeDataOutsideCrop' option requires Ghostscript. Falling back to visual crop only."); + } return cropWithPDFBox(request); } }