当前位置: 首页 > 知识库问答 >
问题:

使用PDFBOX从PDF中获取可见签名?

蓬森
2023-03-14

是否可以用开放源码软件库pdfbox提取已签名PDF的可见签名(图像)?

工作流:

    null

像下面这样的oop风格的东西会很棒:

PDFSignatures [] sigs = document.getPDFSignatures()
sig[0].getCN()
...
(Buffered)Image visibleSig = sig[0].getVisibleSignature()

找到了类PDSignature和如何签署一个PDF,但没有解决方案提取一个可见的签名作为图像。

共有1个答案

丁文轩
2023-03-14

由于没有人上来回答,我自己在对你的问题的评论中尝试了我的建议。第一个结果:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdfviewer.PageDrawer;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDGraphicsState;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;

public class AnnotationDrawer extends PageDrawer
{
    public AnnotationDrawer(int imageType, int resolution) throws IOException
    {
        super();
        this.imageType = imageType;
        this.resolution = resolution;
    }

    public Map<String, BufferedImage> convertToImages(PDPage p) throws IOException
    {
        page = p;
        final Map<String, BufferedImage> result = new HashMap<String, BufferedImage>();

        List<PDAnnotation> annotations = page.getAnnotations();
        for (PDAnnotation annotation: annotations)
        {
            String appearanceName = annotation.getAppearanceStream();
            PDAppearanceDictionary appearDictionary = annotation.getAppearance();
            if( appearDictionary != null )
            {
                if( appearanceName == null )
                {
                    appearanceName = "default";
                }
                Map<String, PDAppearanceStream> appearanceMap = appearDictionary.getNormalAppearance();
                if (appearanceMap != null) 
                {
                    PDAppearanceStream appearance = 
                        (PDAppearanceStream)appearanceMap.get( appearanceName ); 
                    if( appearance != null ) 
                    {
                        BufferedImage image = initializeGraphics(annotation);
                        setTextMatrix(null);
                        setTextLineMatrix(null);
                        getGraphicsStack().clear();
                        processSubStream( page, appearance.getResources(), appearance.getStream() );

                        String name = annotation.getAnnotationName();
                        if (name == null || name.length() == 0)
                        {
                            name = annotation.getDictionary().getString(COSName.T);
                            if (name == null || name.length() == 0)
                            {
                                name = Long.toHexString(annotation.hashCode());
                            }
                        }

                        result.put(name, image);
                    }
                }
            }
        }

        return result;
    }

    BufferedImage initializeGraphics(PDAnnotation annotation)
    {
        PDRectangle rect = annotation.getRectangle();
        float widthPt = rect.getWidth();
        float heightPt = rect.getHeight();
        float scaling = resolution / (float)DEFAULT_USER_SPACE_UNIT_DPI;
        int widthPx = Math.round(widthPt * scaling);
        int heightPx = Math.round(heightPt * scaling);
        //TODO The following reduces accuracy. It should really be a Dimension2D.Float.
        Dimension pageDimension = new Dimension( (int)widthPt, (int)heightPt );
        BufferedImage retval = new BufferedImage( widthPx, heightPx, imageType );
        Graphics2D graphics = (Graphics2D)retval.getGraphics();
        graphics.setBackground( TRANSPARENT_WHITE );
        graphics.clearRect( 0, 0, retval.getWidth(), retval.getHeight() );
        graphics.scale( scaling, scaling );
        setGraphics(graphics);
        pageSize = pageDimension;
        graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
        graphics.setRenderingHint( RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON );
        setGraphicsState(new PDGraphicsState(new PDRectangle(widthPt, heightPt)));

        return retval;
    }

    void setGraphics(Graphics2D graphics)
    {
        try {
            Field field = PageDrawer.class.getDeclaredField("graphics");
            field.setAccessible(true);
            field.set(this, graphics);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static final int DEFAULT_USER_SPACE_UNIT_DPI = 72;
    private static final Color TRANSPARENT_WHITE = new Color( 255, 255, 255, 0 );

    private int imageType;
    private int resolution;
}

如果要呈现给定PDPage页的批注,只需执行以下操作:

AnnotationDrawer drawer = new AnnotationDrawer(8, 288);
Map<String, BufferedImage> images = drawer.convertToImages(page);

构造函数参数与pdpage.convertToImage(int imageType,int resolution)的参数相对应。

a.基于PDFBox 1.8.2一起被黑;它可能包含特定于版本的代码;b.只是检查了我这里的一些可见的签名注释;它可能是不完整的,对于其他批注类型,它尤其可能失败。

 类似资料:
  • 链接到pdf 当我尝试从上面的pdf中提取文本时,我得到了在evince viewer中不可见的文本和可见的文本的混合。此外,一些所需的文本缺少查看器中没有缺少的字符,例如,“FALCONS”中的“S”和许多缺少的“½”字符。我认为这是由于不可见文本的干扰,因为在查看器中突出显示pdf时,可以看到不可见文本与可见文本重叠。 有没有办法去掉不可见的文字?还是有别的解决办法? 代码: 输出(粗体文本为

  • 问题内容: 链接到pdf 当我尝试从上面的pdf中提取文本时,我混合了在evince查看器中不可见的文本和可见的文本。此外,某些所需的文本缺少查看器中未缺少的字符,例如“ FALCONS”中的“ S”和许多缺少的“ 1/2”字符。我认为这是由于来自不可见文本的干扰,因为在查看器中突出显示pdf时,可以看到不可见文本与可见文本重叠。 有没有办法删除不可见的文字?还是有其他解决方案? 码: 输出(粗体

  • 我有一个场景,我需要用iText7库从pdf中获取签名信息。签名可能存在,也可能不存在。当我为没有任何数字签名的PDF实例化一个新的对象时,会出现异常 “没有相关的PdfWriter用于进行间接操作。” .如果有签名,就很好用。我不确定如何纠正这个异常。 更新为包含代码示例

  • 我正在尝试使用pdfbox库签署pdf。我现在卡住了,真的需要帮助。 这是我的代码: 然后我正在保存我的pdf,但是:1)我注意到sign method从来没有被调用2)我应该在哪里附加CertyFicate?在sign method中? 以下是我保存PDF的方法:

  • 我想从现有的pdf中获取图像字段,并用其他图像填充它,以使用java中的pdfbox库创建新的pdf文件

  • 我正在从PDF中删除一个带有书签链接的页面。删除页面后,指向此页面的书签链接不再有效。 我没有从PDFBox api中找到一种方法来完成这项工作 有没有办法删除这个书签?有没有办法删除全部书签? 提前感谢