fake scan to scanner effect (#3954)

# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Anthony Stirling
2025-07-16 14:33:04 +01:00
committed by GitHub
parent 638d9ec43c
commit cc7f163085
48 changed files with 1396 additions and 1397 deletions

View File

@@ -33,7 +33,7 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.FakeScanRequest;
import stirling.software.SPDF.model.api.misc.ScannerEffectRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.util.WebResponseUtils;
@@ -42,7 +42,7 @@ import stirling.software.common.util.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous PDF APIs")
@RequiredArgsConstructor
@Slf4j
public class FakeScanController {
public class ScannerEffectController {
private final CustomPDFDocumentFactory pdfDocumentFactory;
private static final Random RANDOM = new Random();
@@ -52,12 +52,12 @@ public class FakeScanController {
private static final int MAX_IMAGE_HEIGHT = 8192;
private static final long MAX_IMAGE_PIXELS = 16_777_216; // 4096x4096
@PostMapping(value = "/fake-scan", consumes = "multipart/form-data")
@PostMapping(value = "/scanner-effect", consumes = "multipart/form-data")
@Operation(
summary = "Convert PDF to look like a scanned document",
summary = "Apply scanner effect to PDF",
description =
"Applies various effects to make a PDF look like it was scanned, including rotation, noise, and edge softening. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> fakeScan(@Valid @ModelAttribute FakeScanRequest request)
"Applies various effects to simulate a scanned document, including rotation, noise, and edge softening. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> scannerEffect(@Valid @ModelAttribute ScannerEffectRequest request)
throws IOException {
MultipartFile file = request.getFileInput();
@@ -80,7 +80,7 @@ public class FakeScanController {
float noise = request.getNoise();
boolean yellowish = request.isYellowish();
int resolution = request.getResolution();
FakeScanRequest.Colorspace colorspace = request.getColorspace();
ScannerEffectRequest.Colorspace colorspace = request.getColorspace();
try (PDDocument document = pdfDocumentFactory.load(file)) {
PDDocument outputDocument = new PDDocument();
@@ -130,7 +130,7 @@ public class FakeScanController {
// 1. Convert to grayscale or keep color
BufferedImage processed;
if (colorspace == FakeScanRequest.Colorspace.grayscale) {
if (colorspace == ScannerEffectRequest.Colorspace.grayscale) {
processed =
new BufferedImage(
image.getWidth(),
@@ -316,7 +316,7 @@ public class FakeScanController {
String outputFilename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_scanned.pdf";
+ "_scanner_effect.pdf";
return WebResponseUtils.bytesToWebResponse(
outputStream.toByteArray(), outputFilename, MediaType.APPLICATION_PDF);

View File

@@ -70,11 +70,11 @@ public class OtherWebController {
return "misc/add-page-numbers";
}
@GetMapping("/fake-scan")
@GetMapping("/scanner-effect")
@Hidden
public String fakeScanForm(Model model) {
model.addAttribute("currentPage", "fake-scan");
return "misc/fake-scan";
public String scannerEffectForm(Model model) {
model.addAttribute("currentPage", "scanner-effect");
return "misc/scanner-effect";
}
@GetMapping("/extract-images")

View File

@@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode
public class FakeScanRequest {
public class ScannerEffectRequest {
public enum Quality {
low,
medium,