Я пытаюсь редактировать изображения в PDF файле, используя библиотеку PDFBox. Как у меня есть пример работы только для jpeg-изображений. ImageIO.read() не может декодировать изображения с суффиксом "png". Вот пример кода. Итак, мой вопрос: как сделать то же самое для всех типов изображений в PDF-документах? Могу ли я использовать ImageIO для него или нужен другой подход?
public static void main(String[] args) throws Exception {
PDDocument doc = PDDocument.load("docs/input1.pdf");
// Get all images from first page
Map<String, PDXObjectImage> pageImages = ((PDPage) doc.getDocumentCatalog().getAllPages().get(0)).getResources().getImages();
if (pageImages != null)
{
// iterate by images
Iterator<String> imageIter = pageImages.keySet().iterator();
while (imageIter.hasNext())
{
String key = imageIter.next();
PDXObjectImage image = pageImages.get(key); // get page image object
String suffix = image.getSuffix(); // get image suffix
String imageName = key+'.'+suffix; // compose image name
System.out.print("process "+imageName+"... ");
COSStream s = image.getCOSStream(); // get COSStream to manipulate
BufferedImage img = ImageIO.read(s.getFilteredStream()); // get BufferedImage to edit
if(img == null)
{
System.out.println("Can't decode");
}
else
{
paint(img.createGraphics()); // draw on it
ImageIO.write(img, suffix, new File("out/"+imageName)); // write file to check result...
// encode image back to COSStream
OutputStream out = s.createFilteredStream();
ImageIO.write(img, suffix, out);
out.close();
System.out.println("done");
}
}
}
doc.save("out/output1.pdf"); // save document
}
/**
* Draw red rectangular to test
* @param g graphics
*/
public static void paint(Graphics2D g) {
int xpoints[] = {25, 245, 245, 25};
int ypoints[] = {25, 25, 545, 545};
g.setColor(Color.RED);
g.fillPolygon(xpoints, ypoints, 4);
}
Лучше работать не с потоком PDXObjectImage, а создавать новый экземпляр PDXObjectImage и заменять его в сборе ресурсов. Это более общий и универсальный способ. Используйте getRGBImage() для преобразования PDXObjectImage в BufferedImage и конструктор (PDPixelMap, PDJpeg и т.д.), Чтобы преобразовать отредактированный результат обратно в PDXObjectImage. Обратите внимание, что по-прежнему возникают проблемы с изображениями JBIG2 и Jpeg2000 из-за ошибок. Вот пример кода, который я использую для поиска и преобразования всех изображений в документ:
// Recursive resource processor
// Here can be images inside in PDXObjectForm objects
protected static void processResources(PDResources resources, PDDocument doc, String filename) throws IllegalArgumentException, SecurityException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, JBIG2Exception, ColorSpaceException, ICCProfileException
{
if(resources == null) return;
Map<String, PDXObject> xObjects = resources.getXObjects();
if (xObjects == null) return;
// iterate by images
Iterator<String> imageIter = xObjects.keySet().iterator();
while (imageIter.hasNext())
{
String key = imageIter.next();
PDXObject o = xObjects.get(key);
if(o instanceof PDXObjectImage)
xObjects.put(key, processImage((PDXObjectImage) o /*, some additional parms... */));
if(o instanceof PDXObjectForm)
processResources(((PDXObjectForm) o).getResources(), doc, filename);
}
resources.setXObjects(xObjects);
}
Вызовите вызов resources.setXObjects() в конце - без изменений, внесенных вами в коллекцию, полученную resource.getXObjects(), не будут возвращены в документ.