打印包含JBIG2图像的PDF

时间:2012-08-21 13:48:34

标签: java pdf printing applet jbig2

请建议我一些能帮助我打印包含JBIG2编码图像的PDF文件的库。 PDFRendererPDFBox不帮助我。这些库可以打印简单的PDF,但不能打印包含JBIG2图像的PDF。 PDFRenderer尝试修复它(根据PDFRedndrer的错误跟踪器上的错误问题),但仍有一些页面(特别是存在条形码的地方)不想打印。

P.S。我在applet中使用javax.print API

谢谢!

UPDATE :也尝试了ICEPdf,太不想工作。

我得出结论,所有这些库(PDFRenderer,ICEPdf,PDFBox)都使用JPedals jbig2 decoder。 Bug(某些页面未打印)来自此解码器库。不再支持此解码器的开源版本(在PDFRenderer,ICEPdf,PDFBox中使用),但JPedal有一个新的项目商业分支,他们写道,该错误已在新商业中修复发布,售价9000美元。

有什么想法吗?

更新2 :昨天我尝试将JPedal's free library替换为其他开源jbig2-imageio库。但是我没有取得任何成功的结果,所以我在他们项目的页面上创建了一个新主题(谷歌代码的论坛 - here)。非常感谢任何帮助。

我还在Apache PDFBox错误跟踪器上发现了一些有用的讨论:herehere

5 个答案:

答案 0 :(得分:3)

yms 中回答你的评论,即。 “但我可以用什么库来提取图像,(更重要的是)将它们放回PDF格式?”

这是一个简单的示范  1)提取jbig2或者您可以说出来自pdf的所有图像  2)将jbig2图像转换为任何其他格式,在我的情况下为jpeg  3)创建包含pdf的新jpeg

使用库jbig2-imageioitext

在下面的示例中,请根据需要更改资源目录路径
为此我必须经历几个我最终会附加的资源。希望这会有所帮助。

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)从jbig2extract images)(MyImageRenderListener)中提取pdf
2)转换jbig2JBIG2ImageReaderDemo

答案 1 :(得分:1)

如何使用AcrobatReader本身?让它工作有点浑浊,而不是我认为的强大解决方案。但是可能会完美地打印出所有这些内容。并且是免费的

有关此路线的一些信息;

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

答案 2 :(得分:1)

作为替代方案,您可以尝试执行此服务器端:

方法1:
使用外部应用程序将PDF文件转换为光栅图像并进行打印。

方法2:
通过重新压缩JBIG2图像来调整PDF文件:

1-从文件中提取压缩为JBIG2的图像。

2-用其他算法(jpeg,png等)重新压缩它们。为此,您可能需要使用JNI或calling an external application来使用Java。例如,如果GPL lincense适合您的需要,您可以尝试使用jbig2dec或ImageMagic。

3-将重新压缩的图像放回PDF中

这种方法意味着这些图像会有一些质量损失,但至少你可以打印文件。

您可以使用iText在Java中执行此操作,有chapter about resizing images in the book iText in Action(带示例代码)。我们的想法是提取图像,调整图像大小(包括重新压缩)并将其放回原处。您可以将此作为起点。请注意,iText是一个AGPL项目,因此您无法在商业闭源应用程序中免费使用它。

如果您使用的是基于Windows的服务器并且可以买得起商业工具,那么您也可以使用C#/ VB.Net或C ++ {{3>通常免责声明适用于此建议Amyuni PDF Creator来实现此目的。 )。你只需要遍历acObjectTypePictureset the attribute Compression to acJPegHigh类型的所有对象,这种方法不需要任何外部JBIG2解码器(如果你感兴趣,我可以在这里包含一些示例代码)。

如果您使用小程序打印PDF文件,也​​可以尝试generating a PDF file that shows the print dialog when opened

答案 3 :(得分:1)

您有ImageMagick工具可处理图像并将其转换为多种格式。几年前我用过它,所以我不能告诉你默认是否正确处理了jbig2格式,或者你是否需要安装一些插件。 您可以尝试使用以下内容列出以J开头的受支持格式列表,例如您要搜索的JBIG2

$ convert -list format | grep -i J

使用工具转换为pdf非常明显,加上gs工具aka GhostScript

如果没有任何事实阻止您显示图像的PNG / JPEG版本,并提供原始JBIG2文件的下载链接及其自己的元数据。

答案 4 :(得分:1)

Borisvl有一个JPedal库的分支位于

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

其中包含速度改进,我相信它也应该修复你的错误。

编辑:该错误与简单范围检查有关。基本上,您需要阻止GetPixel访问位图范围之外的x,y值。

在调用getPixel

之前,您需要确保满足以下条件

col&gt; = 0且col&lt; bitmap.width   row&gt; = 0并且行&lt; bitmap.height

这是一些带有几个小范围检查的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);

安德鲁。