对于一个学校项目,我正在为 PDF 开发图像提取器,为此我正在使用 PDFBox 库。我现在面临的问题是获取元数据,到目前为止,我只设法从 PDF 本身而不是从 PDF 中的图像获取元数据。
是否可以使用 PDFBox 从 PDF 中的所有图像中获取元数据?如果是这样,有人可以给我举个例子吗?到目前为止,我发现的所有示例都是针对 PDF 本身的元数据,而不是针对图像。
我还听说创建 PDF 时,它会从其中的对象中删除任何元数据,这是真的吗?
希望stackoverflow上的人可以帮助我。
我不同意其他人的观点,并为您的问题提供了 POC:您可以通过以下方式使用pdfbox提取图像的 XMP 元数据:
public void getXMPInformation() { // Open PDF document PDDocument document = null; try { document = PDDocument.load(PATH_TO_YOUR_DOCUMENT); } catch (IOException e) { e.printStackTrace(); } // Get all pages and loop through them List pages = document.getDocumentCatalog().getAllPages(); Iterator iter = pages.iterator(); while( iter.hasNext() ) { PDPage page = (PDPage)iter.next(); PDResources resources = page.getResources(); Map images = null; // Get all Images on page try { images = resources.getImages(); } catch (IOException e) { e.printStackTrace(); } if( images != null ) { // Check all images for metadata Iterator imageIter = images.keySet().iterator(); while( imageIter.hasNext() ) { String key = (String)imageIter.next(); PDXObjectImage image = (PDXObjectImage)images.get( key ); PDMetadata metadata = image.getMetadata(); System.out.println("Found a image: Analyzing for Metadata"); if (metadata == null) { System.out.println("No Metadata found for this image."); } else { InputStream xmlInputStream = null; try { xmlInputStream = metadata.createInputStream(); } catch (IOException e) { e.printStackTrace(); } try { System.out.println("--------------------------------------------------------------------------------"); String mystring = convertStreamToString(xmlInputStream); System.out.println(mystring); } catch (IOException e) { e.printStackTrace(); } } // Export the images String name = getUniqueFileName( key, image.getSuffix() ); System.out.println( "Writing image:" + name ); try { image.write2file( name ); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); } System.out.println("--------------------------------------------------------------------------------"); } } } }
和“辅助方法”:
public String convertStreamToString(InputStream is) throws IOException {
/*
* To convert the InputStream to String we use the BufferedReader.readLine()
* method. We iterate until the BufferedReader return null which means
* there's no more data to read. Each line will appended to a StringBuilder
* and returned as String.
*/
if (is != null) {
StringBuilder sb = new StringBuilder();
String line;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
} finally {
is.close();
}
return sb.toString();
} else {
return "";
}
}
private String getUniqueFileName( String prefix, String suffix ) {
/*
* imagecounter is a global variable that counts from 0 to the number of
* extracted images
*/
String uniqueName = null;
File f = null;
while( f == null || f.exists() ) {
uniqueName = prefix + "-" + imageCounter;
f = new File( uniqueName + "." + suffix );
}
imageCounter++;
return uniqueName;
}
注意:这是一个快速而肮脏的概念证明,而不是一个风格良好的代码。
在构建 PDF 文档之前,在 InDesign 中放置的图像必须具有 XMP 元数据。例如,可以使用 Photoshop 设置 XMP-Metdadata。请注意,并非所有 IPTC/Exif/... 信息都转换为 XMP 元数据。只有少数字段被转换。
我在 JPG 和 PNG 图像上使用此方法,这些图像放置在使用 InDesign 构建的 PDF 中。它运行良好,我可以在制作步骤后从准备好的 PDF(图片涂层)中获取所有图像信息。