如何判断PDImageXObject为earth.png并获取插入时的原文件名?
PDFBox中识别图片原文件名并匹配目标图片
问题描述
将sun.png、moon.png、sea.png、earth.png、sky.png通过PDFBox插入PDF后,读取时能识别出PDImageXObject实例,但无法判断当前实例是否对应earth.png,也无法获取图片插入时的原文件名。
解决方案
方案1:插入图片时主动保留原文件名(推荐,适用于自己生成的PDF)
PDF本身不会自动存储图片的原文件名,因此插入图片时需要手动给PDImageXObject添加自定义元数据,将原文件名存入PDF的XObject字典中:
// 插入earth.png到PDF的示例代码 PDImageXObject pdImage = PDImageXObject.createFromFile("earth.png", document); // 自定义键名存储原文件名,这里用"OriginalFileName" pdImage.getCOSObject().setString(COSName.getPDFName("OriginalFileName"), "earth.png"); // 将图片添加到PDF资源(后续绘制逻辑省略) PDResources resources = new PDResources(); resources.putXObject("earth_img", pdImage);
读取PDF时,从PDImageXObject的COS对象中取出自定义元数据,判断是否为目标图片:
PDXObject pdxObject = getResources().getXObject(objectName); if (pdxObject instanceof PDImageXObject) { PDImageXObject image = (PDImageXObject) pdxObject; COSBase cosBase = image.getCOSObject().getItem(COSName.getPDFName("OriginalFileName")); if (cosBase instanceof COSString) { String originalFileName = ((COSString) cosBase).getString(); if ("earth.png".equals(originalFileName)) { BufferedImage bImage = image.getImage(); ImageIO.write(bImage, "PNG", new File(originalFileName)); System.out.println(originalFileName + " saved."); } } }
方案2:通过图片哈希值匹配(适用于无法控制PDF生成过程的场景)
如果PDF不是自己生成的,无法提前添加元数据,可以通过计算图片内容的哈希值(如MD5)来匹配原图片:
首先计算原earth.png的哈希值:
private static String calculateImageHash(String imagePath) throws IOException, NoSuchAlgorithmException { BufferedImage img = ImageIO.read(new File(imagePath)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(img, "PNG", baos); byte[] imgBytes = baos.toByteArray(); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hashBytes = md.digest(imgBytes); StringBuilder sb = new StringBuilder(); for (byte b : hashBytes) { sb.append(String.format("%02x", b)); } return sb.toString(); }
读取PDF时,计算每个PDImageXObject的哈希值并与原图片哈希对比:
// 先获取原earth.png的哈希 String targetHash = calculateImageHash("earth.png"); PDXObject pdxObject = getResources().getXObject(objectName); if (pdxObject instanceof PDImageXObject) { PDImageXObject image = (PDImageXObject) pdxObject; BufferedImage bImage = image.getImage(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bImage, "PNG", baos); byte[] imgBytes = baos.toByteArray(); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] hashBytes = md.digest(imgBytes); StringBuilder sb = new StringBuilder(); for (byte b : hashBytes) { sb.append(String.format("%02x", b)); } String currentHash = sb.toString(); if (targetHash.equals(currentHash)) { ImageIO.write(bImage, "PNG", new File("earth.png")); System.out.println("earth saved."); } }
内容的提问来源于stack exchange,提问作者Shahid Ghafoor
相关产品推荐
相关产品推荐

