Travailler avec les opérateurs PDF en Java
Introduction aux opérateurs PDF et à leur utilisation
Un opérateur est un mot-clé PDF spécifiant une action à effectuer, comme peindre une forme graphique sur la page. Un mot-clé opérateur se distingue d’un objet nommé par l’absence de caractère solidus initial (2Fh). Les opérateurs n’ont de sens qu’à l’intérieur du flux de contenu.
Un flux de contenu est un objet flux PDF dont les données sont constituées d’instructions décrivant les éléments graphiques à peindre sur une page. Plus de détails sur les opérateurs PDF peuvent être trouvés dans la spécification PDF.
Utilisez cette page lorsque vous avez besoin d’un contrôle direct sur un flux de contenu PDF en Java, par exemple en plaçant une image avec des mathématiques matricielles explicites, en réutilisant le même graphique plusieurs fois via un XForm ou en supprimant des instructions de dessin de bas niveau d’une page.
Ajouter une image avec les opérateurs PDF
Utilisez des opérateurs de bas niveau lorsque le placement des images doit être contrôlé précisément au niveau du flux de contenu plutôt que via des API de mise en page de niveau supérieur.
- Ouvrez le PDF source avec Document et obtenez la Page cible.
- Ajoutez le flux d’images d’entrée aux ressources de la page et conservez le nom de la ressource renvoyé.
- Créez un Rectangle qui définit la zone cible et construisez une Matrice à partir de ses limites.
- Utilisez GSave pour conserver l’état graphique actuel, ConcatenateMatrix pour positionner l’image, Do pour la peindre et GRestore pour restaurer l’état antérieur.
- Enregistrez le document PDF mis à jour.
public static void addImageUsingPdfOperators(Path inputFile, Path imageFile, Path outputFile) throws Exception {
try (Document document = new Document(inputFile.toString());
InputStream imageStream = Files.newInputStream(imageFile)) {
Page page = document.getPages().get_Item(1);
String imageName = page.getResources().getImages().add(imageStream);
Rectangle rectangle = new Rectangle(100, 100, 200, 200, true);
Matrix matrix = new Matrix(new double[]{
rectangle.getURX() - rectangle.getLLX(),
0,
0,
rectangle.getURY() - rectangle.getLLY(),
rectangle.getLLX(),
rectangle.getLLY()
});
page.getContents().add(new GSave());
page.getContents().add(new ConcatenateMatrix(matrix));
page.getContents().add(new Do(imageName));
page.getContents().add(new GRestore());
document.save(outputFile.toString());
}
System.out.println("Image added with PDF operators to " + outputFile);
}
Dessiner du contenu XForm réutilisable sur une page
Utilisez cette approche lorsque la même image ou le même graphique doit être rendu plusieurs fois sans dupliquer la ressource dans le fichier PDF.
- Ouvrez le PDF source avec Document, récupérez la Page cible et accédez à sa OperatorCollection.
- Enveloppez le contenu de la page existante avec GSave et GRestore afin que les transformations ultérieures ne s’infiltrent pas dans le flux de contenu d’origine.
- Créez une ressource XForm, ajoutez l’image aux ressources du formulaire et utilisez ConcatenateMatrix plus Do pour dessiner l’image à l’intérieur du formulaire.
- Placez le même formulaire sur plusieurs coordonnées de page en ajoutant une matrice de traduction et en exécutant le nom du formulaire avec l’opérateur
Do. - Restaurez l’état graphique et enregistrez le PDF de sortie.
public static void drawXFormOnPage(Path inputFile, Path imageFile, Path outputFile) throws Exception {
try (Document document = new Document(inputFile.toString());
InputStream imageStream = Files.newInputStream(imageFile)) {
Page page = document.getPages().get_Item(1);
OperatorCollection pageContents = page.getContents();
pageContents.insert(1, new GSave());
pageContents.add(new GRestore());
pageContents.add(new GSave());
XForm form = XForm.createNewForm(page, document);
page.getResources().getForms().add(form);
form.getContents().add(new GSave());
form.getContents().add(new ConcatenateMatrix(200, 0, 0, 200, 0, 0));
String imageName = form.getResources().getImages().add(imageStream);
form.getContents().add(new Do(imageName));
form.getContents().add(new GRestore());
addFormAt(pageContents, form.getName(), 100, 500);
addFormAt(pageContents, form.getName(), 100, 300);
pageContents.add(new GRestore());
document.save(outputFile.toString());
}
System.out.println("XForm drawn on page in " + outputFile);
}
private static void addFormAt(OperatorCollection pageContents, String formName, double x, double y) {
pageContents.add(new GSave());
pageContents.add(new ConcatenateMatrix(1, 0, 0, 1, x, y));
pageContents.add(new Do(formName));
pageContents.add(new GRestore());
}
Supprimer les opérateurs graphiques d’une page
Utilisez cet exemple lorsqu’une page contient des opérateurs de dessin vectoriel qui doivent être supprimés directement du flux de contenu.
- Ouvrez le PDF source avec Document et obtenez la page cible Page.
- Parcourez les opérateurs de contenu de la page et collectez les instances de Stroke, ClosePathStroke, et Fill.
- Supprimez les opérateurs collectés du contenu de la page et enregistrez le PDF mis à jour.
Cette technique supprime uniquement les instructions de dessin ciblées. Si la page contient aussi des libellés associés ou d’autres opérateurs non graphiques, ces éléments restent dans le flux de contenu et peuvent nécessiter un nettoyage distinct.
public static void removeGraphicsObjects(Path inputFile, Path outputFile) {
try (Document document = new Document(inputFile.toString())) {
Page page = document.getPages().get_Item(1);
List<Operator> operatorsToRemove = new ArrayList<>();
for (Object item : page.getContents()) {
Operator operator = (Operator) item;
if (operator instanceof Stroke || operator instanceof ClosePathStroke || operator instanceof Fill) {
operatorsToRemove.add(operator);
}
}
page.getContents().delete(operatorsToRemove);
document.save(outputFile.toString());
}
System.out.println("Graphics operators removed in " + outputFile);
}