Распечатать PDF, содержащий изображения JBIG2

Пожалуйста, предложите мне несколько библиотек, которые помогут мне распечатать файлы PDF, содержащие изображения в кодировке JBIG2. PDFRenderer, PDFBox не помогай мне Эти библиотеки могут печатать простые PDF, но не PDF, содержащие изображения JBIG2. PDFRenderer пытается исправить это (в соответствии с ошибкой в ​​трекере ошибок PDFRedndrer), но некоторые страницы (особенно там, где существуют штрих-коды) не хотят печатать.

PS пользуюсь javax.print API в апплете

Спасибо!

ОБНОВЛЕНИЕ: также попробовал ICEPdf, тоже не хочу работать.

Я пришел к выводу, что все эти библиотеки (PDFRenderer, ICEPdf, PDFBox) используют JPedals декодер jbig2. Ошибка (некоторые страницы не печатались) происходят из этой библиотеки декодера. Версия этого декодера с открытым исходным кодом (которая используется в PDFRenderer, ICEPdf, PDFBox) больше не поддерживается, но JPedal есть новая коммерческая ветка проекта, и они написали, что ошибка была исправлена ​​в новой коммерческой версии, которая стоит $9k.

Есть идеи?

ОБНОВЛЕНИЕ 2: вчера я попытался заменить свободную библиотеку JPedal с другим открытым исходным кодом jbig2-imageio библиотеки. Но пока я не получаю никаких успешных результатов, поэтому я создал новую тему на странице их проекта (форум google-code - здесь). Буду благодарен за любую помощь.

Я также нашел некоторые полезные обсуждения Apache PDFBox баг-трекер: здесь и здесь.

5 ответов

Решение

Есть развилка библиотеки JPedal от Borisvl, расположенная по адресу

https://github.com/Borisvl/JBIG2-Image-Decoder

который содержит улучшения скорости, и я считаю, что это также должно исправить вашу ошибку.

РЕДАКТИРОВАТЬ: ошибка связана с простой проверкой диапазона. По сути, вам нужно запретить GetPixel доступ к значениям x,y за пределами растровых экстентов.

Вы должны убедиться, что выполняются следующие условия перед вызовом getPixel

col> = 0 и col = 0 и row

Вот некоторый код Delphi с парой небольших проверок диапазона. Я не могу сам протестировать код Java, но вам нужно внести изменения в src/org/jpedal/jbig2/image/JBIG2Bitmap.java

procedure TJBIG2Bitmap.combine(bitmap: TJBIG2Bitmap; x, y: Integer; combOp: Int64);
...
...
var
begin
  srcWidth := bitmap.width;
  srcHeight := bitmap.height;
  srcRow := 0;
  srcCol := 0;

  if (x < 0) then x := 0;
  if (y < 0) then y := 0;

  for row := y to Min(y + srcHeight - 1, Self.height - 1) do   // <<<<<<<<  HERE
  begin
    for col := x to x + srcWidth - 1 do
    begin
      srcPixel := bitmap.getPixel(srcCol, srcRow);

Эндрю.

Как проходит ваш комментарий в ответе yms т.е. "но какую библиотеку я могу использовать для извлечения изображений и (что более важно) вернуть их обратно в PDF?"

Вот простая демонстрация
1) Извлечение jbig2 или вы можете сказать все изображения из pdf,
2) Конвертация jbig2 изображение в любом другом формате, в моем случае его jpeg,
3) Создание нового pdf содержащий jpeg,

Использование библиотек jbig2-imageio и itext.

В приведенном ниже примере измените ресурсы и путь к каталогам в соответствии с вашими потребностями.
Для этого мне пришлось пройти через несколько ресурсов, которые я приложу в конце. Надеюсь это поможет.

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.parser.*;

import com.levigo.jbig2.JBIG2ImageReader;
import com.levigo.jbig2.JBIG2ImageReaderSpi;
import com.levigo.jbig2.JBIG2ReadParam;
import com.levigo.jbig2.io.DefaultInputStreamFactory;

import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;

public class JBig2Image {
    private String filepath;
    private int imageIndex;

    public JBig2Image() {
        this.filepath = "/home/blackadmin/Desktop/pdf/demo18.jbig2";
        this.imageIndex = 0;
        extractImgFromPdf();
        convertJBig2ToJpeg();
        createPDF();
    }

    private void extractImgFromPdf() {
        try {
            /////////// Extract all Images from pdf /////////////////////////

            PdfReader reader = new PdfReader("/home/blackadmin/Desktop/pdf/orig.pdf");
            PdfReaderContentParser parser = new PdfReaderContentParser(reader);
            MyImageRenderListener listener = new MyImageRenderListener("/home/blackadmin/Desktop/pdf/demo%s.%s");
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
                parser.processContent(i, listener);
            }
        } catch (IOException ex) {
            System.out.println(ex);
        }
    }

    private void convertJBig2ToJpeg() {
        InputStream inputStream = null;
        try {
            ///////// Read jbig2 image ////////////////////////////////////////
            inputStream = new FileInputStream(new File(filepath));
            DefaultInputStreamFactory disf = new DefaultInputStreamFactory();
            ImageInputStream imageInputStream = disf.getInputStream(inputStream);
            JBIG2ImageReader imageReader = new JBIG2ImageReader(new JBIG2ImageReaderSpi());
            imageReader.setInput(imageInputStream);
            JBIG2ReadParam param = imageReader.getDefaultReadParam();
            BufferedImage bufferedImage = imageReader.read(imageIndex, param);

            ////////// jbig2 to jpeg ///////////////////////////////////////////
            ImageIO.write(bufferedImage, "jpeg", new File("/home/blackadmin/Desktop/pdf/demo18.jpeg"));
        } catch (IOException ex) {
            System.out.println(ex);
        } finally {
            try {
                inputStream.close();
            } catch (IOException ex) {
                System.out.println(ex);
            }
        }
    }

    public void createPDF() {
        Document document = new Document();
        try {
            PdfWriter.getInstance(document,
                    new FileOutputStream("/home/blackadmin/Desktop/pdf/output.pdf"));
            document.open();
            PdfPTable table = new PdfPTable(1); //1 column.    
            Image image = Image.getInstance("/home/blackadmin/Desktop/pdf/demo18.jpeg");
            image.scaleToFit(800f, 600f);
            image.scaleAbsolute(800f, 600f);   // Give the size of image you want to print on pdf
            PdfPCell nestedImgCell = new PdfPCell(image);
            table.addCell(nestedImgCell);
            document.add(table);
            document.close();
            System.out.println(
                    "======== PDF Created Successfully =========");
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public static void main(String[] args) throws IOException {
        new JBig2Image();
    }
}



class MyImageRenderListener implements RenderListener {

    /**
     * The new document to which we've added a border rectangle.
     */
    protected String path = "";

    /**
     * Creates a RenderListener that will look for images.
     */
    public MyImageRenderListener(String path) {
        this.path = path;
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#beginTextBlock()
     */
    public void beginTextBlock() {
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#endTextBlock()
     */
    public void endTextBlock() {
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(
     * com.itextpdf.text.pdf.parser.ImageRenderInfo)
     */
    public void renderImage(ImageRenderInfo renderInfo) {
        try {
            String filename;
            FileOutputStream os;
            PdfImageObject image = renderInfo.getImage();
            if (image == null) {
                return;
            }
            filename = String.format(path, renderInfo.getRef().getNumber(), image.getFileType());
            os = new FileOutputStream(filename);
            os.write(image.getImageAsBytes());
            os.flush();
            os.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * @see com.itextpdf.text.pdf.parser.RenderListener#renderText(
     * com.itextpdf.text.pdf.parser.TextRenderInfo)
     */
    public void renderText(TextRenderInfo renderInfo) {
    }
}

Рекомендации:
1) Извлечение jbig2 от pdf ( извлечение изображений) ( MyImageRenderListener).
2) Конвертация jbig2 ( JBIG2ImageReaderDemo)

В качестве альтернативы, вы можете попробовать сделать это на стороне сервера:

Подход 1:
Преобразуйте файлы PDF в растровые изображения с помощью внешнего приложения и распечатайте его.

Подход 2:
Настройте PDF-файлы, сжимая изображения JBIG2:

1- Извлечение изображений, сжатых как JBIG2, из ваших файлов.

2-Сжать их с другим алгоритмом (JPEG, PNG и т. Д.). Для этого вам может потребоваться выйти за пределы Java, используя либо JNI, либо вызывая внешнее приложение. Вы можете попробовать с jbig2dec или ImageMagic, например, если GPL Lincense соответствует вашим потребностям.

3- Поместите повторно сжатые изображения обратно в PDF.


Этот подход приведет к некоторой потере качества этих изображений, но, по крайней мере, вы сможете распечатать файлы.

Вы можете сделать это на Java с помощью iText, в книге iText in Action (с примером кода) есть глава об изменении размера изображений. Идея состоит в том, чтобы извлечь изображение, изменить его размер (включая повторное сжатие) и вернуть его обратно. Вы можете использовать это в качестве отправной точки. Помните, что iText является проектом AGPL, поэтому вы не можете использовать его бесплатно в коммерческих приложениях с закрытым исходным кодом.

Если вы используете сервер на базе Windows и можете позволить себе коммерческий инструмент, вы также можете добиться этого с помощью Amyuni PDF Creator либо с C#/VB.Net, либо с C++ (для этого предложения применяется обычный отказ от ответственности). Вам просто нужно пройти через все объекты типа acObjectTypePicture и установить для атрибута Compression значение acJPegHigh, для этого подхода не требуется никакого внешнего декодера JBIG2 (я могу включить здесь некоторый пример кода, если вам интересно).

Если вы используете апплет только для печати ваших PDF-файлов, вы также можете попробовать сгенерировать PDF-файл, который показывает диалоговое окно печати при открытии.

Как насчет использования самого AcrobatReader? Это немного мутно, заставить его работать, и я не думаю, что это надежное решение. Но, вероятно, напечатает все это отлично. И быть свободным

Некоторая информация об этом маршруте;

http://vineetreynolds.blogspot.nl/2005/12/silent-print-pdf-print-pdf.html http://www.codeproject.com/Questions/98586/Programmatics-print-PDF-documents http://forums.adobe.com/message/2336723

У вас есть инструменты, такие как ImageMagick, которые обрабатывают изображения и конвертируют их во множество форматов. Я использовал его несколько лет назад, поэтому я не могу сказать вам, правильно ли по умолчанию обрабатывается формат jbig2 или вам нужно установить какой-нибудь плагин. Вы можете попробовать следующее, чтобы получить список поддерживаемых форматов, начинающихся с J, таких как JBIG2 Вы ищете:

$ convert -list format | grep -i J

Это действительно очевидно, чтобы конвертировать в PDF с помощью инструмента, в сочетании с gs инструмент ака GhostScript.

В противном случае вы не сможете отобразить версию изображения в формате PNG/JPEG и предоставить ссылку для загрузки исходного файла JBIG2 с его собственными метаданными.

Другие вопросы по тегам