使用 pdfbox 从 pdf 中提取图像
Posted
技术标签:
【中文标题】使用 pdfbox 从 pdf 中提取图像【英文标题】:extract images from pdf using pdfbox 【发布时间】:2012-02-01 01:45:39 【问题描述】:我正在尝试。示例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 图像的解决方案?谢谢
【参考方案1】:
只需将.jpeg
添加到路径的末尾即可:
image.write2file("C:\\Users\\Pradyut\\Documents\\image" + i + ".jpeg");
这对我有用。
【讨论】:
【参考方案2】:您可以使用PDPage.convertToImage()
函数将PDF 页面转换为BufferedImage。接下来可以使用 BufferedImage 创建一个 Image。
使用以下参考资料了解更多详情:
PDFBox 中的所有 PDF 相关类都可以进入 Apache PDFBox 1.8.3 API Here可以查看PDPage相关文档。并且不要忘记在 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 您只考虑xObject
是PDFormXObject
或PDImageXObject
的情况。但根据the Javadoc,它也可能是PDPostScriptXObject
。 PDPostScriptXObject
不能还包含更多图像吗?【参考方案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();
【讨论】:
以上是关于使用 pdfbox 从 pdf 中提取图像的主要内容,如果未能解决你的问题,请参考以下文章