Comment identifier et supprimer le texte caché du PDF à l'aide de PDFBox Java

Sep 17 2020

Je lis du texte à partir de PDF en utilisant la bibliothèque pdfbox et je l'enregistre dans un fichier texte. Il lit également le texte caché qui n'est pas visible lorsque le PDF est visualisé via PDF Reader. Mon exigence est d'obtenir certaines caractéristiques de ces textes cachés qui peuvent le distinguer du texte normal.

Réponses

mkl Sep 27 2020 at 22:02

Un critère possible pour les textes à ignorer dans vos fichiers d'exemple est la couleur du texte, blanc CMJN pur dans un cas, 0,753 dans un espace colorimétrique basé sur ICC Gray Gamma 2,2 XYZ dans l'autre cas.

Alors étendons le stripper de texte par une option de filtrage des couleurs. Cela signifie en particulier l'ajout de processeurs d'opérateurs pour les instructions de réglage des couleurs, car PDFTextStripperpar défaut, les ignorent:

public class PDFFilteringTextStripper extends PDFTextStripper {
    public interface TextStripperFilter {
        public boolean accept(TextPosition text, PDGraphicsState graphicsState);
    }

    public PDFFilteringTextStripper(TextStripperFilter filter) throws IOException {
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetStrokingColorSpace());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetNonStrokingColorSpace());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetStrokingColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetNonStrokingColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetStrokingColorN());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetNonStrokingColorN());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetStrokingDeviceGrayColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetNonStrokingDeviceGrayColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetStrokingDeviceRGBColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetNonStrokingDeviceRGBColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetStrokingDeviceCMYKColor());
        addOperator(new org.apache.pdfbox.contentstream.operator.color.SetNonStrokingDeviceCMYKColor());

        this.filter = filter;
    }

    @Override
    protected void processTextPosition(TextPosition text) {
        PDGraphicsState graphicsState = getGraphicsState();
        if (filter.accept(text, graphicsState))
            super.processTextPosition(text);
    }

    final TextStripperFilter filter;
}

( Classe PDFFilteringTextStripper )

En utilisant cette classe de décapage de texte, nous pouvons filtrer le texte blanc du premier exemple de PDF comme ceci:

float[] colorToFilter = new float[] {0,0,0,0};

PDDocument document = ...;
PDFFilteringTextStripper stripper = new PDFFilteringTextStripper((text, gs) -> {
    PDColor color = gs.getNonStrokingColor();
    return color == null || !((color.getColorSpace() instanceof PDDeviceCMYK) && Arrays.equals(color.getComponents(), colorToFilter));
});
String text = stripper.getText(document);

( Test ExtractFilteredTexttestExtractNoWhiteText... )

De même, nous pouvons filtrer le texte gris du deuxième exemple de PDF comme ceci:

float[] colorToFilter = new float[] {0.753f};

PDDocument document = ...;
PDFFilteringTextStripper stripper = new PDFFilteringTextStripper((text, gs) -> {
    PDColor color = gs.getNonStrokingColor();
    return color == null || !((color.getColorSpace() instanceof PDICCBased) && Arrays.equals(color.getComponents(), colorToFilter));
});
String text = stripper.getText(document);

( Test ExtractFilteredTexttestExtractNoGrayText... )


Dans un commentaire que vous avez demandé

Une question rapide - ce texte en 0.753 dans un espace de couleurs basé sur ICC XYZ Gray Gamma 2.2 - texte invisible? Ou est-ce simplement à cause de l'espace de couleurs, le texte n'est pas visible dans le PDF?

C'est visible! (Ainsi, à proprement parler, vous ne devez pas le supprimer du texte extrait.)

C'est tout simplement assez petit. Sur la page de titre, zoomez sur l'année "2016":