30

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

但我只得到空白图像。

我正在尝试的代码:-

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 ++;
            }
        }
    }

}

谢谢

4

8 回答 8

32

这是使用 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;
}
于 2016-06-06T18:11:02.700 回答
11

下面的GetImagesFromPDFjava 类获取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();
    }
}

}

于 2014-01-23T06:51:59.517 回答
10

对于 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);
            }
        }
    }
}
于 2016-05-12T03:21:49.883 回答
2

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

使用以下参考了解更多详细信息:

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

于 2013-01-20T07:17:40.753 回答
2

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

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

这对我行得通。

于 2012-07-09T12:11:59.327 回答
1

对于只想复制并粘贴此准备使用代码的人

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();
    }
}
于 2020-08-13T16:48:22.947 回答
1

这是@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"

于 2020-06-12T12:11:19.013 回答
0

而不是打电话

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);
于 2013-01-29T21:14:49.463 回答