Редактировать изображения в файле PDF с помощью объекта COSStream

1

Я пытаюсь редактировать изображения в 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);
}
Теги:
pdf
pdfbox
javax.imageio

1 ответ

1
Лучший ответ

Лучше работать не с потоком 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(), не будут возвращены в документ.

  • 1
    JBIG2 работает, если вы добавляете плагин levigo JBIG2 в ваш путь к классам. JPEG2000 работает "большую часть времени" с java imageio.
  • 0
    Да, levigo JBIG2 работает нормально. Декодирование JPEG2000 1-bit все еще проблематично.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню