【问题标题】:extract images from pdf using pdfbox使用 pdfbox 从 pdf 中提取图像
【发布时间】:2012-02-01 01:45:39
【问题描述】:

我正在尝试使用 pdfbox 从 pdf 中提取图像。示例pdfhere

但我只得到空白图像。

我正在尝试的代码:-

public static void main(String[] args) {
   PDFImageExtract obj = new PDFImageExtract();
    try {
        obj.read_pdf();
    } catch (IOException ex) {
        System.out.println("" + ex);
    }

}

 void read_pdf() throws IOException {
    PDDocument document = null; 
    try {
        document = PDDocument.load("C:\\Users\\Pradyut\\Documents\\MCS-034.pdf");
    } catch (IOException ex) {
        System.out.println("" + ex);
    }
    List pages = document.getDocumentCatalog().getAllPages();
    Iterator iter = pages.iterator(); 
    int i =1;
    String name = null;

    while (iter.hasNext()) {
        PDPage page = (PDPage) iter.next();
        PDResources resources = page.getResources();
        Map pageImages = resources.getImages();
        if (pageImages != null) { 
            Iterator imageIter = pageImages.keySet().iterator();
            while (imageIter.hasNext()) {
                String key = (String) imageIter.next();
                PDXObjectImage image = (PDXObjectImage) pageImages.get(key);
                image.write2file("C:\\Users\\Pradyut\\Documents\\image" + i);
                i ++;
            }
        }
    }

}

谢谢

【问题讨论】:

  • PDF 由 JBIG2 编码的图像组成。我不确定 pdfBox 是否支持这些。
  • 我可以在这个应用程序中使用库 jbig2-imageio:code.google.com/p/jbig2-imageio/wiki/Usage 吗?将其作为库 jar 或类路径添加到应用程序吗?
  • 我在测试您的代码时遇到了问题:“UnsupportedOper”
  • 你找到了如何解码 JBIG2 图像的答案吗?
  • @PradyutBhattacharya 您是否找到了如何使用jbig2-imageio 解码 JBIG2 图像的解决方案?谢谢

标签: java image pdf pdfbox


【解决方案1】:

只需将.jpeg 添加到路径的末尾即可:

image.write2file("C:\\Users\\Pradyut\\Documents\\image" + i + ".jpeg");

这对我有用。

【讨论】:

    【解决方案2】:

    您可以使用PDPage.convertToImage() 函数将PDF 页面转换为BufferedImage。接下来可以使用 BufferedImage 创建一个 Image。

    使用以下参考资料了解更多详情:

    并且不要忘记在 PDPage 类中查找PDPage.convertToImage() 函数。

    【讨论】:

      【解决方案3】:

      而不是调用

      image.write2file("C:\\Users\\Pradyut\\Documents\\image" + i);
      

      您可以使用ImageIO.write() 静态方法以您需要的任何格式写入 RGB 图像。这里我使用了 PNG:

      File outputFile = new File( "C:\\Users\\Pradyut\\Documents\\image" + i + ".png");
      ImageIO.write( image.getRGBImage(), "png", outputFile);
      

      【讨论】:

        【解决方案4】:

        下面的GetImagesFromPDF java 类获取04-Request-Headers.pdf 文件中的所有图像并将这些文件保存到目标文件夹PDFCopy

        import java.io.File;
        import java.util.Iterator;
        import java.util.List;
        import java.util.Map;
        
        import org.apache.pdfbox.pdmodel.PDDocument;
        import org.apache.pdfbox.pdmodel.PDPage;
        import org.apache.pdfbox.pdmodel.PDResources;
        import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
        
        @SuppressWarnings({ "unchecked", "rawtypes", "deprecation" })
        public class GetImagesFromPDF {
            public static void main(String[] args) {
                try {
                    String sourceDir = "C:/PDFCopy/04-Request-Headers.pdf";// Paste pdf files in PDFCopy folder to read
                    String destinationDir = "C:/PDFCopy/";
                    File oldFile = new File(sourceDir);
                    if (oldFile.exists()) {
                    PDDocument document = PDDocument.load(sourceDir);
        
                    List<PDPage> list = document.getDocumentCatalog().getAllPages();
        
                    String fileName = oldFile.getName().replace(".pdf", "_cover");
                    int totalImages = 1;
                    for (PDPage page : list) {
                        PDResources pdResources = page.getResources();
        
                        Map pageImages = pdResources.getImages();
                        if (pageImages != null) {
        
                            Iterator imageIter = pageImages.keySet().iterator();
                            while (imageIter.hasNext()) {
                                String key = (String) imageIter.next();
                                PDXObjectImage pdxObjectImage = (PDXObjectImage) pageImages.get(key);
                                pdxObjectImage.write2file(destinationDir + fileName+ "_" + totalImages);
                                totalImages++;
                            }
                        }
                    }
                } else {
                    System.err.println("File not exists");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        

        }

        【讨论】:

        • 有没有办法对此进行排序或确保它是连续完成的?
        • @Ian 你想按顺序获取图像吗?
        • @COBRA.cH 告诉我你正在尝试哪个版本?
        • 我没有找到表达式 pdResources.getImages();使用 pdfbox 2.0.25
        【解决方案5】:

        对于 PDFBox 2.0.1,pudaykiran 的回答必须稍作修改,因为某些 API 已更改。

        public static void testPDFBoxExtractImages() throws Exception {
            PDDocument document = PDDocument.load(new File("D:/Temp/Test.pdf"));
            PDPageTree list = document.getPages();
            for (PDPage page : list) {
                PDResources pdResources = page.getResources();
                for (COSName c : pdResources.getXObjectNames()) {
                    PDXObject o = pdResources.getXObject(c);
                    if (o instanceof org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject) {
                        File file = new File("D:/Temp/" + System.nanoTime() + ".png");
                        ImageIO.write(((org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject)o).getImage(), "png", file);
                    }
                }
            }
        }
        

        【讨论】:

        • 太棒了!为我工作。但在我的 cese 中添加了 jai-imageio-jpeg2000 依赖项来转换 jpeg2000 图像。
        【解决方案6】:

        这是使用 PDFBox 2.0.1 的代码,它将从 PDF 中获取所有图像的列表。这与其他代码的不同之处在于它将递归遍历文档,而不是尝试从顶层获取图像。

        public List<RenderedImage> getImagesFromPDF(PDDocument document) throws IOException {
                List<RenderedImage> images = new ArrayList<>();
            for (PDPage page : document.getPages()) {
                images.addAll(getImagesFromResources(page.getResources()));
            }
        
            return images;
        }
        
        private List<RenderedImage> getImagesFromResources(PDResources resources) throws IOException {
            List<RenderedImage> images = new ArrayList<>();
        
            for (COSName xObjectName : resources.getXObjectNames()) {
                PDXObject xObject = resources.getXObject(xObjectName);
        
                if (xObject instanceof PDFormXObject) {
                    images.addAll(getImagesFromResources(((PDFormXObject) xObject).getResources()));
                } else if (xObject instanceof PDImageXObject) {
                    images.add(((PDImageXObject) xObject).getImage());
                }
            }
        
            return images;
        }
        

        【讨论】:

        • 这应该被标记为正确答案。这在 Java11 和 PDFBox 2.0.12 上对我有用
        • @Matt 您只考虑xObjectPDFormXObjectPDImageXObject 的情况。但根据the Javadoc,它也可能是PDPostScriptXObjectPDPostScriptXObject 不能还包含更多图像吗?
        【解决方案7】:

        这是@Matt 答案的 kotlin 版本。

        fun <R> PDResources.onImageResources(block: (RenderedImage) -> (R)): List<R> =
                this.xObjectNames.flatMap {
                    when (val xObject = this.getXObject(it)) {
                        is PDFormXObject -> xObject.resources.onImageResources(block)
                        is PDImageXObject -> listOf(block(xObject.image))
                        else -> emptyList()
                    }
                }
        

        您可以像这样在 PDPage 资源上使用它:

        page.resources.onImageResources { image ->
            Files.createTempFile("image", "xxx").also { path-> 
                if(!ImageIO.write(it, "xxx", file.toFile()))
                    IllegalStateException("Couldn't write image to file")
            }
        }
        

        "xxx" 是您需要的格式(如 "jpeg"

        【讨论】:

          【解决方案8】:

          对于只想复制并粘贴此代码的人

          import org.apache.pdfbox.contentstream.PDFStreamEngine;
          import org.apache.pdfbox.contentstream.operator.Operator;
          import org.apache.pdfbox.cos.COSBase;
          import org.apache.pdfbox.cos.COSName;
          import org.apache.pdfbox.pdmodel.PDDocument;
          import org.apache.pdfbox.pdmodel.PDPage;
          import org.apache.pdfbox.pdmodel.graphics.PDXObject;
          import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
          import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
          
          import javax.imageio.ImageIO;
          import java.awt.image.BufferedImage;
          import java.io.File;
          import java.io.IOException;
          import java.util.List;
          import java.util.UUID;
          
          public class ExtractImagesUseCase extends PDFStreamEngine{
              private final String filePath;
              private final String outputDir;
          
              // Constructor
              public ExtractImagesUseCase(String filePath,
                                          String outputDir){
                  this.filePath = filePath;
                  this.outputDir = outputDir;
              }
          
              // Execute
              public void execute(){
                  try{
                      File file = new File(filePath);
                      PDDocument document = PDDocument.load(file);
          
                      for(PDPage page : document.getPages()){
                          processPage(page);
                      }
          
                  }catch(IOException e){
                      e.printStackTrace();
                  }
              }
          
              @Override
              protected void processOperator(Operator operator, List<COSBase> operands) throws IOException{
                  String operation = operator.getName();
          
                  if("Do".equals(operation)){
                      COSName objectName = (COSName) operands.get(0);
                      PDXObject pdxObject = getResources().getXObject(objectName);
          
                      if(pdxObject instanceof PDImageXObject){
                          // Image
                          PDImageXObject image = (PDImageXObject) pdxObject;
                          BufferedImage bImage = image.getImage();
          
                          // File
                          String randomName = UUID.randomUUID().toString();
                          File outputFile = new File(outputDir,randomName + ".png");
          
                          // Write image to file
                          ImageIO.write(bImage, "PNG", outputFile);
          
                      }else if(pdxObject instanceof PDFormXObject){
                          PDFormXObject form = (PDFormXObject) pdxObject;
                          showForm(form);
                      }
                  }
          
                  else super.processOperator(operator, operands);
              }
          }
          

          演示

          public class ExtractImageDemo{
              public static void main(String[] args){
                  String filePath = "C:\\Users\\John\\Downloads\\Documents\\sample-file.pdf";
                  String outputDir = "C:\\Users\\John\\Downloads\\Documents\\Output";
          
                  ExtractImagesUseCase useCase = new ExtractImagesUseCase(
                          filePath,
                          outputDir
                  );
                  useCase.execute();
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2011-07-25
            • 2023-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-01-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多