所谓的两张图片,右上角的fischer标志和稍微向下的小草图,都是通过用平铺图案填充页面上的一个区域来绘制,这个图案在其内容流中又会绘制相应的图像。
Adobe Reader不允许选择图案的内容,而自动图像提取器通常也不会遍历Pattern资源树。
PDFBox 1.8.10
您可以使用PDFBox相对容易地构建图案图像提取器,例如针对PDFBox 1.8.10:
public void extractPatternImages(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");
extractPatternImages(pages.get(i), pageFormat);
}
}
public void extractPatternImages(PDPage page, String pageFormat) throws IOException
{
PDResources resources = page.getResources();
if (resources == null)
return;
Map<String, PDPatternResources> patterns = resources.getPatterns();
for (Map.Entry<String, PDPatternResources> patternEntry : patterns.entrySet())
{
String patternFormat = String.format(pageFormat, "-" + patternEntry.getKey() + "%s", "%s");
extractPatternImages(patternEntry.getValue(), patternFormat);
}
}
public void extractPatternImages(PDPatternResources pattern, String patternFormat) throws IOException
{
COSDictionary resourcesDict = (COSDictionary) pattern.getCOSDictionary().getDictionaryObject(COSName.RESOURCES);
if (resourcesDict == null)
return;
PDResources resources = new PDResources(resourcesDict);
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(patternFormat, "-" + entry.getKey() + "%s", "%s");
if (xObject instanceof PDXObjectForm)
extractPatternImages((PDXObjectForm)xObject, xObjectFormat);
else if (xObject instanceof PDXObjectImage)
extractPatternImages((PDXObjectImage)xObject, xObjectFormat);
}
}
public void extractPatternImages(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)
extractPatternImages((PDXObjectForm)xObject, xObjectFormat);
else if (xObject instanceof PDXObjectImage)
extractPatternImages((PDXObjectImage)xObject, xObjectFormat);
}
Map<String, PDPatternResources> patterns = resources.getPatterns();
for (Map.Entry<String, PDPatternResources> patternEntry : patterns.entrySet())
{
String patternFormat = String.format(imageFormat, "-" + patternEntry.getKey() + "%s", "%s");
extractPatternImages(patternEntry.getValue(), patternFormat);
}
}
public void extractPatternImages(PDXObjectImage image, String imageFormat) throws IOException
{
image.write2OutputStream(new FileOutputStream(String.format(imageFormat, "", image.getSuffix())));
}
(ExtractPatternImages.java)
我将它应用到了你提供的样例PDF中,如下所示:
public void testtestDrJorge() throws IOException
{
try (InputStream resource = getClass().getResourceAsStream("testDrJorge.pdf"))
{
PDDocument document = PDDocument.load(resource);
extractPatternImages(document, "testDrJorge%s.%s");;
}
}
(ExtractPatternImages.java)
得到了两个图片:
这些图片失去了它们的红色部分。这很可能是因为PDFBox 1.x.x版本没有适当地支持CMYK图像提取,参考PDFBOX-2128 (不正确支持CMYK图像),而你的图片是CMYK格式的。
PDFBox 2.0.0 发布候选版
我将代码更新至PDFBox 2.0.0(目前仅作为发布候选版):
public void extractPatternImages(PDDocument document, String fileNameFormat) throws IOException
{
PDPageTree pages = document.getDocumentCatalog().getPages();
if (pages == null)
return;
for (int i = 0; i < pages.getCount(); i++)
{
String pageFormat = String.format(fileNameFormat, "-" + i + "%s", "%s");
extractPatternImages(pages.get(i), pageFormat);
}
}
public void extractPatternImages(PDPage page, String pageFormat) throws IOException
{
PDResources resources = page.getResources();
if (resources == null)
return;
Iterable<COSName> patternNames = resources.getPatternNames();
for (COSName patternName : patternNames)
{
String patternFormat = String.format(pageFormat, "-" + patternName + "%s", "%s");
extractPatternImages(resources.getPattern(patternName), patternFormat);
}
}
public void extractPatternImages(PDAbstractPattern pattern, String patternFormat) throws IOException
{
COSDictionary resourcesDict = (COSDictionary) pattern.getCOSObject().getDictionaryObject(COSName.RESOURCES);
if (resourcesDict == null)
return;
PDResources resources = new PDResources(resourcesDict);
Iterable<COSName> xObjectNames = resources.getXObjectNames();
if (xObjectNames == null)
return;
for (COSName xObjectName : xObjectNames)
{
PDXObject xObject = resources.getXObject(xObjectName);
String xObjectFormat = String.format(patternFormat, "-" + xObjectName + "%s", "%s");
if (xObject instanceof PDFormXObject)
extractPatternImages((PDFormXObject)xObject, xObjectFormat);
else if (xObject instanceof PDImageXObject)
extractPatternImages((PDImageXObject)xObject, xObjectFormat);
}
}
public void extractPatternImages(PDFormXObject form, String imageFormat) throws IOException
{
PDResources resources = form.getResources();
if (resources == null)
return;
Iterable<COSName> xObjectNames = resources.getXObjectNames();
if (xObjectNames == null)
return;
for (COSName xObjectName : xObjectNames)
{
PDXObject xObject = resources.getXObject(xObjectName);
String xObjectFormat = String.format(imageFormat, "-" + xObjectName + "%s", "%s");
if (xObject instanceof PDFormXObject)
extractPatternImages((PDFormXObject)xObject, xObjectFormat);
else if (xObject instanceof PDImageXObject)
extractPatternImages((PDImageXObject)xObject, xObjectFormat);
}
Iterable<COSName> patternNames = resources.getPatternNames();
for (COSName patternName : patternNames)
{
String patternFormat = String.format(imageFormat, "-" + patternName + "%s", "%s");
extractPatternImages(resources.getPattern(patternName), patternFormat);
}
}
public void extractPatternImages(PDImageXObject image, String imageFormat) throws IOException
{
String filename = String.format(imageFormat, "", image.getSuffix());
ImageIOUtil.writeImage(image.getOpaqueImage(), "png", new FileOutputStream(filename));
}
看起来有所改善... ;)