我想使用Java netbeans从pdf中的按钮获取图像图标,并将其放在某些面板中。
但是我在这里碰到了一块砖。
我将PDFBox用作PDF导出器,但我似乎不太了解。
我已经成功读取了表单字段,但是没有按钮提取器,只要我尝试在PDFBox中找到它即可。
我应该怎么做?并且有可能使用这种方法,还是有其他解决方法。
提前致谢。

编辑:
我已经发现使用示例代码中的示例实用程序来提取图像:

       File myFile = new File(filename);
        try {

            //PDDocument pdDoc = PDDocument.loadNonSeq( myFile, null );
            PDDocument pdDoc = null;
            pdDoc = PDDocument.load( myFile );
            PDDocumentCatalog pdCatalog = pdDoc.getDocumentCatalog();
            PDAcroForm pdAcroForm = pdCatalog.getAcroForm();
            // dipakai untuk membaca isi file

            List pages = pdDoc.getDocumentCatalog().getAllPages();
            Iterator iter = pages.iterator();
             while( iter.hasNext() )
             {
                 PDPage page = (PDPage)iter.next();
                 PDResources resources = page.getResources();
                 Map images = resources.getImages();
                 if( images != null )
                 {
                     Iterator imageIter = images.keySet().iterator();
                     while( imageIter.hasNext() )
                     {
                         String key = (String  )imageIter.next();
                         PDXObjectImage image = (PDXObjectImage)images.get(key);
                         BufferedImage imagedisplay= image.getRGBImage();
                         jLabel5.setIcon(new ImageIcon(imagedisplay)); // NOI18N
                     }
                 }
             }


        } catch (Exception e) {
               JOptionPane.showMessageDialog(null, "error " + e.getMessage());


        }

但是我仍然无法读取按钮图像。
顺便说一句,我从此页面阅读了教程,将按钮图像添加到pdf。
https://acrobatusers.com/tutorials/how-to-create-a-button-form-field-to-insert-a-pdf-file

第二次编辑:
在这里,我还为您提供了带有图标的pdf链接。 PDF Link
先感谢您。

最佳答案

当您谈论PDF中的按钮时,我假设您的意思是交互式表单按钮。

一般来说

PDFBox中没有用于按钮的显式图标提取器。但是,由于带有自定义图标的按钮(通常是注释)将这些图标定义为它们的外观的一部分,因此可以简单地(递归地)遍历注释外观的资源,并使用子类型 Image 收集 XObject :

public void extractAnnotationImages(PDDocument document, String fileNameFormat) throws IOException
{
    List<PDPage> pages = document.getDocumentCatalog().getAllPages();
    if (pages == null)
        return;

    for (int i = 0; i < pages.size(); i++)
    {
        String pageFormat = String.format(fileNameFormat, "-" + i + "%s", "%s");
        extractAnnotationImages(pages.get(i), pageFormat);
    }
}

public void extractAnnotationImages(PDPage page, String pageFormat) throws IOException
{
    List<PDAnnotation> annotations = page.getAnnotations();
    if (annotations == null)
        return;

    for (int i = 0; i < annotations.size(); i++)
    {
        PDAnnotation annotation = annotations.get(i);
        String annotationFormat = annotation.getAnnotationName() != null && annotation.getAnnotationName().length() > 0
                ? String.format(pageFormat, "-" + annotation.getAnnotationName() + "%s", "%s")
                : String.format(pageFormat, "-" + i + "%s", "%s");
        extractAnnotationImages(annotation, annotationFormat);
    }
}

public void extractAnnotationImages(PDAnnotation annotation, String annotationFormat) throws IOException
{
    PDAppearanceDictionary appearance = annotation.getAppearance();
    extractAnnotationImages(appearance.getDownAppearance(), String.format(annotationFormat, "-Down%s", "%s"));
    extractAnnotationImages(appearance.getNormalAppearance(), String.format(annotationFormat, "-Normal%s", "%s"));
    extractAnnotationImages(appearance.getRolloverAppearance(), String.format(annotationFormat, "-Rollover%s", "%s"));
}

public void extractAnnotationImages(Map<String, PDAppearanceStream> stateAppearances, String stateFormat) throws IOException
{
    if (stateAppearances == null)
        return;

    for (Map.Entry<String, PDAppearanceStream> entry: stateAppearances.entrySet())
    {
        String appearanceFormat = String.format(stateFormat, "-" + entry.getKey() + "%s", "%s");
        extractAnnotationImages(entry.getValue(), appearanceFormat);
    }
}

public void extractAnnotationImages(PDAppearanceStream appearance, String appearanceFormat) throws IOException
{
    PDResources resources = appearance.getResources();
    if (resources == null)
        return;
    Map<String, PDXObject> xObjects = resources.getXObjects();
    if (xObjects == null)
        return;

    for (Map.Entry<String, PDXObject> entry : xObjects.entrySet())
    {
        PDXObject xObject = entry.getValue();
        String xObjectFormat = String.format(appearanceFormat, "-" + entry.getKey() + "%s", "%s");
        if (xObject instanceof PDXObjectForm)
            extractAnnotationImages((PDXObjectForm)xObject, xObjectFormat);
        else if (xObject instanceof PDXObjectImage)
            extractAnnotationImages((PDXObjectImage)xObject, xObjectFormat);
    }
}

public void extractAnnotationImages(PDXObjectForm form, String imageFormat) throws IOException
{
    PDResources resources = form.getResources();
    if (resources == null)
        return;
    Map<String, PDXObject> xObjects = resources.getXObjects();
    if (xObjects == null)
        return;

    for (Map.Entry<String, PDXObject> entry : xObjects.entrySet())
    {
        PDXObject xObject = entry.getValue();
        String xObjectFormat = String.format(imageFormat, "-" + entry.getKey() + "%s", "%s");
        if (xObject instanceof PDXObjectForm)
            extractAnnotationImages((PDXObjectForm)xObject, xObjectFormat);
        else if (xObject instanceof PDXObjectImage)
            extractAnnotationImages((PDXObjectImage)xObject, xObjectFormat);
    }
}

public void extractAnnotationImages(PDXObjectImage image, String imageFormat) throws IOException
{
    image.write2OutputStream(new FileOutputStream(String.format(imageFormat, "", image.getSuffix())));
}

(来自ExtractAnnotationImageTest.java)

不幸的是,OP没有提供样本PDF,所以我将代码应用于this example file

java - 如何使用Apache PDFBox从PDF中的按钮图标提取图像?-LMLPHP

(存储为资源),如下所示:
/**
 * Test using <a href="http://examples.itextpdf.com/results/part2/chapter08/buttons.pdf">buttons.pdf</a>
 * created by <a href="http://itextpdf.com/examples/iia.php?id=154">part2.chapter08.Buttons</a>
 * from ITEXT IN ACTION — SECOND EDITION.
 */
@Test
public void testButtonsPdf() throws IOException
{
    try (InputStream resource = getClass().getResourceAsStream("buttons.pdf"))
    {
        PDDocument document = PDDocument.load(resource);
        extractAnnotationImages(document, new File(RESULT_FOLDER, "buttons%s.%s").toString());;
    }
}

(来自ExtractAnnotationImageTest.java)

并得到了这些图像:

java - 如何使用Apache PDFBox从PDF中的按钮图标提取图像?-LMLPHP



java - 如何使用Apache PDFBox从PDF中的按钮图标提取图像?-LMLPHP

这里有两个问题:
  • 我们提取附加到注释外观的所有图像资源,并且不检查它们是否在外观流中的任何地方实际使用。因此,您可能会发现比预期更多的图标。在上述情况下,第一个图像不用作单独资源,而仅用作第二个图像的遮罩。
  • 我们仅提取图像资源,而不提取嵌入式图像,因此可能会丢失一些图像。

  • 因此,请在您的PDF中检查此代码。如果需要,可以进行改进。

    OP的文件

    OP同时提供了一个示例文件imageicon.pdf

    java - 如何使用Apache PDFBox从PDF中的按钮图标提取图像?-LMLPHP

    这样调用上面的方法
    /**
     * Test using <a href="http://www.docdroid.net/TDGVQzg/imageicon.pdf.html">imageicon.pdf</a>
     * created by the OP.
     */
    @Test
    public void testImageiconPdf() throws IOException
    {
        try (InputStream resource = getClass().getResourceAsStream("imageicon.pdf"))
        {
            PDDocument document = PDDocument.load(resource);
            extractAnnotationImages(document, new File(RESULT_FOLDER, "imageicon%s.%s").toString());;
        }
    }
    

    (来自ExtractAnnotationImageTest.java)

    输出此图像:

    java - 如何使用Apache PDFBox从PDF中的按钮图标提取图像?-LMLPHP

    因此,它工作正常!

    作为独立工具启动

    OP在评论中指出是

    仍然使用junit测试方法感到困惑,但是当我尝试将其调用到主程序中时,它总是返回“stream close”错误。我已经将该文件放在与jar相同的目录中,也尝试手动指定路径,但仍然存在相同的错误。

    因此,我在类中添加了main方法以允许

    无需使用JUnit框架和即可启动
  • 从命令行中文件名指定的本地文件系统中的任何PDF提取。

  • 在代码中:
    public static void main(String[] args) throws IOException
    {
        ExtractAnnotationImageTest extractor = new ExtractAnnotationImageTest();
    
        for (String arg : args)
        {
            try (PDDocument document = PDDocument.load(arg))
            {
                extractor.extractAnnotationImages(document, arg+"%s.%s");;
            }
        }
    }
    

    (来自ExtractAnnotationImageTest.java)

    10-07 19:10
    查看更多