update #5
7 changed files with 44 additions and 22 deletions
|
@ -1,21 +1,14 @@
|
||||||
package stirling.software.SPDF.controller.api.security;
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.pdfbox.Loader;
|
import org.apache.pdfbox.Loader;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
|
|
||||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||||
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
|
|
||||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
|
||||||
import org.apache.pdfbox.rendering.ImageType;
|
|
||||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
@ -32,6 +25,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import stirling.software.SPDF.model.PDFText;
|
import stirling.software.SPDF.model.PDFText;
|
||||||
import stirling.software.SPDF.model.api.security.RedactPdfRequest;
|
import stirling.software.SPDF.model.api.security.RedactPdfRequest;
|
||||||
import stirling.software.SPDF.pdf.TextFinder;
|
import stirling.software.SPDF.pdf.TextFinder;
|
||||||
|
import stirling.software.SPDF.utils.PdfUtils;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -81,22 +75,9 @@ public class RedactController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convertPDFToImage) {
|
if (convertPDFToImage) {
|
||||||
PDDocument imageDocument = new PDDocument();
|
PDDocument convertedPdf = PdfUtils.convertPdfToPdfImage(document);
|
||||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
|
||||||
pdfRenderer.setSubsamplingAllowed(true);
|
|
||||||
for (int page = 0; page < document.getNumberOfPages(); ++page) {
|
|
||||||
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
|
|
||||||
PDPage newPage = new PDPage(new PDRectangle(bim.getWidth(), bim.getHeight()));
|
|
||||||
imageDocument.addPage(newPage);
|
|
||||||
PDImageXObject pdImage = LosslessFactory.createFromImage(imageDocument, bim);
|
|
||||||
PDPageContentStream contentStream =
|
|
||||||
new PDPageContentStream(
|
|
||||||
imageDocument, newPage, AppendMode.APPEND, true, true);
|
|
||||||
contentStream.drawImage(pdImage, 0, 0);
|
|
||||||
contentStream.close();
|
|
||||||
}
|
|
||||||
document.close();
|
document.close();
|
||||||
document = imageDocument;
|
document = convertedPdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
|
|
@ -36,6 +36,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.security.AddWatermarkRequest;
|
import stirling.software.SPDF.model.api.security.AddWatermarkRequest;
|
||||||
|
import stirling.software.SPDF.utils.PdfUtils;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -60,6 +61,7 @@ public class WatermarkController {
|
||||||
float opacity = request.getOpacity();
|
float opacity = request.getOpacity();
|
||||||
int widthSpacer = request.getWidthSpacer();
|
int widthSpacer = request.getWidthSpacer();
|
||||||
int heightSpacer = request.getHeightSpacer();
|
int heightSpacer = request.getHeightSpacer();
|
||||||
|
boolean convertPdfToImage = request.isConvertPDFToImage();
|
||||||
|
|
||||||
// Load the input PDF
|
// Load the input PDF
|
||||||
PDDocument document = Loader.loadPDF(pdfFile.getBytes());
|
PDDocument document = Loader.loadPDF(pdfFile.getBytes());
|
||||||
|
@ -104,6 +106,12 @@ public class WatermarkController {
|
||||||
contentStream.close();
|
contentStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (convertPdfToImage) {
|
||||||
|
PDDocument convertedPdf = PdfUtils.convertPdfToPdfImage(document);
|
||||||
|
document.close();
|
||||||
|
document = convertedPdf;
|
||||||
|
}
|
||||||
|
|
||||||
return WebResponseUtils.pdfDocToWebResponse(
|
return WebResponseUtils.pdfDocToWebResponse(
|
||||||
document,
|
document,
|
||||||
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
|
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
|
||||||
|
|
|
@ -44,4 +44,7 @@ public class AddWatermarkRequest extends PDFFile {
|
||||||
|
|
||||||
@Schema(description = "The height spacer between watermark elements", example = "50")
|
@Schema(description = "The height spacer between watermark elements", example = "50")
|
||||||
private int heightSpacer;
|
private int heightSpacer;
|
||||||
|
|
||||||
|
@Schema(description = "Convert the redacted PDF to an image", defaultValue = "false")
|
||||||
|
private boolean convertPDFToImage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,6 +341,30 @@ public class PdfUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a given Pdf file to PDF-Image.
|
||||||
|
*
|
||||||
|
* @param document to be converted. Note: the caller is responsible for closing the document
|
||||||
|
* @return converted document to PDF-Image
|
||||||
|
* @throws IOException if conversion fails
|
||||||
|
*/
|
||||||
|
public static PDDocument convertPdfToPdfImage(PDDocument document) throws IOException {
|
||||||
|
PDDocument imageDocument = new PDDocument();
|
||||||
|
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||||
|
pdfRenderer.setSubsamplingAllowed(true);
|
||||||
|
for (int page = 0; page < document.getNumberOfPages(); ++page) {
|
||||||
|
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
|
||||||
|
PDPage newPage = new PDPage(new PDRectangle(bim.getWidth(), bim.getHeight()));
|
||||||
|
imageDocument.addPage(newPage);
|
||||||
|
PDImageXObject pdImage = LosslessFactory.createFromImage(imageDocument, bim);
|
||||||
|
PDPageContentStream contentStream =
|
||||||
|
new PDPageContentStream(imageDocument, newPage, AppendMode.APPEND, true, true);
|
||||||
|
contentStream.drawImage(pdImage, 0, 0);
|
||||||
|
contentStream.close();
|
||||||
|
}
|
||||||
|
return imageDocument;
|
||||||
|
}
|
||||||
|
|
||||||
private static BufferedImage prepareImageForPdfToImage(
|
private static BufferedImage prepareImageForPdfToImage(
|
||||||
int maxWidth, int height, String imageType) {
|
int maxWidth, int height, String imageType) {
|
||||||
BufferedImage combined;
|
BufferedImage combined;
|
||||||
|
|
|
@ -945,6 +945,7 @@ watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||||
watermark.selectText.7=Opacity (0% - 100%):
|
watermark.selectText.7=Opacity (0% - 100%):
|
||||||
watermark.selectText.8=Watermark Type:
|
watermark.selectText.8=Watermark Type:
|
||||||
watermark.selectText.9=Watermark Image:
|
watermark.selectText.9=Watermark Image:
|
||||||
|
watermark.selectText.10=Convert PDF to PDF-Image
|
||||||
watermark.submit=Add Watermark
|
watermark.submit=Add Watermark
|
||||||
watermark.type.1=Text
|
watermark.type.1=Text
|
||||||
watermark.type.2=Image
|
watermark.type.2=Image
|
||||||
|
|
|
@ -945,6 +945,7 @@ watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||||
watermark.selectText.7=Opacity (0% - 100%):
|
watermark.selectText.7=Opacity (0% - 100%):
|
||||||
watermark.selectText.8=Watermark Type:
|
watermark.selectText.8=Watermark Type:
|
||||||
watermark.selectText.9=Watermark Image:
|
watermark.selectText.9=Watermark Image:
|
||||||
|
watermark.selectText.10=Convert PDF to PDF-Image
|
||||||
watermark.submit=Add Watermark
|
watermark.submit=Add Watermark
|
||||||
watermark.type.1=Text
|
watermark.type.1=Text
|
||||||
watermark.type.2=Image
|
watermark.type.2=Image
|
||||||
|
|
|
@ -104,6 +104,10 @@
|
||||||
<label for="heightSpacer" th:text="#{watermark.selectText.6}"></label>
|
<label for="heightSpacer" th:text="#{watermark.selectText.6}"></label>
|
||||||
<input type="text" id="heightSpacer" name="heightSpacer" class="form-control" value="50">
|
<input type="text" id="heightSpacer" name="heightSpacer" class="form-control" value="50">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-3 form-check">
|
||||||
|
<input type="checkbox" id="convertPDFToImage" name="convertPDFToImage">
|
||||||
|
<label for="convertPDFToImage" th:text="#{watermark.selectText.10}"></label>
|
||||||
|
</div>
|
||||||
<div class="mb-3 text-center">
|
<div class="mb-3 text-center">
|
||||||
<input type="submit" id="submitBtn" th:value="#{watermark.submit}" class="btn btn-primary">
|
<input type="submit" id="submitBtn" th:value="#{watermark.submit}" class="btn btn-primary">
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue