Skip to content

Commit

Permalink
Merge pull request #452 from slovensko-digital/pdf-box-image-render
Browse files Browse the repository at this point in the history
Try pdf box to render pdf as images
  • Loading branch information
celuchmarek authored Jun 13, 2024
2 parents 8ff9d1a + 4289c27 commit 48d032d
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 241 deletions.
56 changes: 6 additions & 50 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<dss.version>6.0</dss.version>
<gson.version>2.10.1</gson.version>
<apache.httpcomponents.version>4.5.14</apache.httpcomponents.version>
<pdfjs.version>2.10.377</pdfjs.version>
<pdfbox.version>2.0.30</pdfbox.version>
<saxon.version>12.4</saxon.version>
<xerces.version>2.12.1</xerces.version>
<slf4j.version>2.0.13</slf4j.version>
Expand Down Expand Up @@ -97,6 +97,11 @@
<artifactId>httpclient</artifactId>
<version>${apache.httpcomponents.version}</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${pdfbox.version}</version>
</dependency>
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
Expand Down Expand Up @@ -297,55 +302,6 @@
</executions>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>2.0.2</version>
<executions>
<execution>
<id>download-pdfjs-main</id>
<phase>initialize</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>
https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.min.js</url>
<toDir>
${project.resources[0].directory}/digital/slovensko/autogram/ui/gui/vendor/pdfjs</toDir>
<skipIfExists>true</skipIfExists>
</configuration>
</execution>
<execution>
<id>download-pdfjs-worker</id>
<phase>initialize</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>
https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js</url>
<toDir>
${project.resources[0].directory}/digital/slovensko/autogram/ui/gui/vendor/pdfjs</toDir>
<skipIfExists>true</skipIfExists>
</configuration>
</execution>
<execution>
<id>download-pdfjs-cmaps</id>
<phase>initialize</phase>
<goals>
<goal>download</goal>
</goals>
<configuration>
<url>https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}</url>
<fromDir>cmaps</fromDir>
<toDir>
${project.resources[0].directory}/digital/slovensko/autogram/ui/gui/vendor/pdfjs/cmaps</toDir>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>com.igormaznitsa</groupId>
<artifactId>mvn-jlink-wrapper</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void startVisualization(SigningJob job) {
}

try {
var visualization = DocumentVisualizationBuilder.fromJob(job);
var visualization = DocumentVisualizationBuilder.fromJob(job, settings);
ui.onUIThreadDo(() -> ui.showVisualization(visualization, this));
} catch (AutogramException e) {
ui.onUIThreadDo(() -> ui.showError(e));
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/digital/slovensko/autogram/core/UserSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class UserSettings implements PasswordManagerSettings, SignatureTokenSett
private boolean tsaEnabled;
private String customTsaServer;
private boolean bulkEnabled;
private int pdfDpi;

public static UserSettings load() {
var prefs = Preferences.userNodeForPackage(UserSettings.class);
Expand All @@ -51,6 +52,7 @@ public static UserSettings load() {
settings.setTsaServer(prefs.get("TSA_SERVER", "http://tsa.izenpe.com"));
settings.setCustomTsaServer(prefs.get("CUSTOM_TSA_SERVER", ""));
settings.setTsaEnabled(prefs.getBoolean("TSA_ENABLE", false));
settings.setPdfDpi(prefs.getInt("PDF_DPI", 100));

return settings;
}
Expand All @@ -75,6 +77,7 @@ public void save() {
prefs.put("TSA_SERVER", tsaServer);
prefs.put("CUSTOM_TSA_SERVER", customTsaServer);
prefs.putBoolean("TSA_ENABLE", tsaEnabled);
prefs.putInt("PDF_DPI", pdfDpi);
}

private void setSignatureType(String signatureType) {
Expand Down Expand Up @@ -260,4 +263,12 @@ public DriverDetector getDriverDetector() {
public boolean isBulkEnabled() {
return bulkEnabled;
}

public int getPdfDpi() {
return pdfDpi;
}

public void setPdfDpi(int value) {
pdfDpi = value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import javax.xml.parsers.ParserConfigurationException;

import digital.slovensko.autogram.core.UserSettings;
import eu.europa.esig.dss.model.DSSDocument;

import org.xml.sax.SAXException;
Expand All @@ -29,15 +30,15 @@ private DocumentVisualizationBuilder(DSSDocument document, SigningParameters par
this.parameters = parameters;
}

public static Visualization fromJob(SigningJob job) throws IOException, ParserConfigurationException, SAXException {
return new DocumentVisualizationBuilder(job.getDocument(), job.getParameters()).build(job);
public static Visualization fromJob(SigningJob job, UserSettings userSettings) throws IOException, ParserConfigurationException, SAXException {
return new DocumentVisualizationBuilder(job.getDocument(), job.getParameters()).build(job, userSettings);
}

private Visualization build(SigningJob job) throws IOException, ParserConfigurationException, SAXException {
return createVisualization(job);
private Visualization build(SigningJob job, UserSettings userSettings) throws IOException, ParserConfigurationException, SAXException {
return createVisualization(job, userSettings);
}

private Visualization createVisualization(SigningJob job)
private Visualization createVisualization(SigningJob job, UserSettings userSettings)
throws IOException, ParserConfigurationException, SAXException {

var documentToDisplay = document;
Expand Down Expand Up @@ -70,7 +71,7 @@ private Visualization createVisualization(SigningJob job)
return new PlainTextVisualization(new String(documentToDisplay.openStream().readAllBytes(), StandardCharsets.UTF_8), job);

if (documentToDisplay.getMimeType().equals(MimeTypeEnum.PDF))
return new PDFVisualization(documentToDisplay, job);
return new PDFVisualization(documentToDisplay, job, userSettings);

if (documentToDisplay.getMimeType().equals(MimeTypeEnum.JPEG) || documentToDisplay.getMimeType().equals(MimeTypeEnum.PNG))
return new ImageVisualization(documentToDisplay, job);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,49 @@
package digital.slovensko.autogram.core.visualization;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.ArrayList;

import digital.slovensko.autogram.core.SigningJob;
import digital.slovensko.autogram.core.UserSettings;
import digital.slovensko.autogram.ui.Visualizer;
import eu.europa.esig.dss.model.DSSDocument;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;

public class PDFVisualization extends Visualization {
private final DSSDocument document;
private final UserSettings settings;


public PDFVisualization(DSSDocument document, SigningJob job) {
public PDFVisualization(DSSDocument document, SigningJob job, UserSettings settings) {
super(job);
this.document = document;
this.settings = settings;
}

private String getBase64EncodedDocument() {
try (var is = document.openStream()) {
return new String(Base64.getEncoder().encode(is.readAllBytes()), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
private ArrayList<byte []> getPdfImages() throws IOException {
var pdfDocument = PDDocument.load(this.document.openStream());
var pdfRenderer = new PDFRenderer(pdfDocument);
var divs = new ArrayList<byte[]>();
for (int page = 0; page < pdfDocument.getNumberOfPages(); ++page) {
var os = new ByteArrayOutputStream();
var bim = pdfRenderer.renderImageWithDPI(page, settings.getPdfDpi(), ImageType.RGB);
ImageIO.write(bim, "png", os);
divs.add(os.toByteArray());
}

pdfDocument.close();

return divs;
}

@Override
public void initialize(Visualizer visualizer) {
public void initialize(Visualizer visualizer) throws IOException {
visualizer.setPrefWidth(getVisualizationWidth());
visualizer.showPDFVisualization(getBase64EncodedDocument());
visualizer.showPDFVisualization(getPdfImages());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
import digital.slovensko.autogram.core.SigningJob;
import digital.slovensko.autogram.ui.Visualizer;

import java.io.IOException;

public abstract class Visualization {
private final SigningJob job;

protected Visualization(SigningJob job) {
this.job = job;
}

public abstract void initialize(Visualizer visualizer);
public abstract void initialize(Visualizer visualizer) throws IOException;

public SigningJob getJob() {
return job;
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/digital/slovensko/autogram/ui/Visualizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import eu.europa.esig.dss.model.DSSDocument;

import java.util.ArrayList;

public interface Visualizer {
void showUnsupportedVisualization();

void showPDFVisualization(String base64EncodedDocument);
void showPDFVisualization(ArrayList<byte[]> base64EncodedDocument);

void showHTMLVisualization(String document);

Expand Down
11 changes: 10 additions & 1 deletion src/main/java/digital/slovensko/autogram/ui/gui/GUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,16 @@ public void showVisualization(Visualization visualization, Autogram autogram) {
var controller = new SigningDialogController(visualization, autogram, this, title, userSettings.isSignaturesValidity());
jobControllers.put(visualization.getJob(), controller);

var root = GUIUtils.loadFXML(controller, "signing-dialog.fxml");
Parent root;
try {
root = GUIUtils.loadFXML(controller, "signing-dialog.fxml");
} catch (AutogramException e) {
showError(e);
return;
} catch (Exception e) {
showError(new UnrecognizedException(e));
return;
}
var stage = new Stage();
stage.setTitle(title);
stage.setScene(new Scene(root));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class SettingsDialogController {
@FXML
private HBox localServerEnabledRadios;
@FXML
private ChoiceBox<String> pdfDpiChoiceBox;
@FXML
private ChoiceBox<String> slotIndexChoiceBox;
@FXML
private TextField customKeystorePathTextField;
Expand Down Expand Up @@ -81,6 +83,7 @@ public void initialize() {
initializeLocalServerEnabledCheckBox();
initializeTrustedCountriesList();
initializeSlotIndexSettings();
initializePdfDpiSettings();
initializeCustomKeystoreSettings();
}

Expand Down Expand Up @@ -277,6 +280,14 @@ private void initializeSlotIndexSettings() {
});
}

private void initializePdfDpiSettings() {
pdfDpiChoiceBox.getItems().addAll("50 dpi", "70 dpi", "100 dpi", "150 dpi", "200 dpi", "300 dpi");
pdfDpiChoiceBox.setValue(String.valueOf(userSettings.getPdfDpi()) + " dpi");
pdfDpiChoiceBox.getSelectionModel().selectedItemProperty()
.addListener((observable, oldValue, newValue) ->
userSettings.setPdfDpi(Integer.parseInt(newValue.replace(" dpi", ""))));
}

private void initializeCustomKeystoreSettings() {
customKeystorePathTextField.setText(userSettings.getCustomKeystorePath());
customKeystorePathTextField.setOnKeyTyped((e) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import digital.slovensko.autogram.core.Autogram;
import digital.slovensko.autogram.core.SignatureValidator;
import digital.slovensko.autogram.core.visualization.ImageVisualization;
import digital.slovensko.autogram.core.visualization.Visualization;
import digital.slovensko.autogram.ui.Visualizer;
import digital.slovensko.autogram.util.DSSUtils;
Expand All @@ -20,11 +21,17 @@
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.web.WebView;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.verapdf.xmp.impl.Base64;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;

import static digital.slovensko.autogram.ui.gui.GUIValidationUtils.*;

Expand All @@ -50,6 +57,10 @@ public class SigningDialogController implements SuppressedFocusController, Visua
@FXML
VBox webViewContainer;
@FXML
ScrollPane pdfVisualizationContainer;
@FXML
VBox pdfVisualizationBox;
@FXML
ImageView imageVisualization;
@FXML
ScrollPane imageVisualizationContainer;
Expand All @@ -73,7 +84,7 @@ public SigningDialogController(Visualization visualization, Autogram autogram, G
this.shouldCheckValidityBeforeSigning = shouldCheckValidityBeforeSigning;
}

public void initialize() {
public void initialize() throws IOException {
headerText.setText(title);
signaturesTable.setManaged(false);
signaturesTable.setVisible(false);
Expand Down Expand Up @@ -298,19 +309,20 @@ public void showHTMLVisualization(String html) {
webViewContainer.setManaged(true);
}

public void showPDFVisualization(String base64EncodedPdf) {
var engine = webView.getEngine();
engine.setJavaScriptEnabled(true);
engine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
engine.executeScript(
"displayPdf('" + base64EncodedPdf + "')");
}
public void showPDFVisualization(ArrayList<byte[]> data) {
data.forEach(page -> {
var imgView = new ImageView();
imgView.fitWidthProperty().bind(pdfVisualizationContainer.widthProperty().subtract(30));
imgView.setImage(new Image(new ByteArrayInputStream(page)));
imgView.setPreserveRatio(true);
imgView.setSmooth(true);

pdfVisualizationBox.getChildren().add(new HBox(imgView));
});
engine.load(getClass().getResource("visualization-pdf.html").toExternalForm());
webViewContainer.getStyleClass().add("autogram-visualizer-pdf");
webViewContainer.setVisible(true);
webViewContainer.setManaged(true);

pdfVisualizationContainer.setFitToWidth(true);
pdfVisualizationContainer.setVisible(true);
pdfVisualizationContainer.setManaged(true);
}

public void showImageVisualization(DSSDocument doc) {
Expand Down
Loading

0 comments on commit 48d032d

Please sign in to comment.