8

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

PS 我javax.print在小程序中使用 API

谢谢!

更新:也试过ICEPdf,太不想工作了。

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

有任何想法吗?

更新 2:昨天我尝试用其他开源库替换JPedal 的免费jbig2-imageio库。但是我没有得到任何成功的结果,所以我在他们的项目页面上创建了一个新主题(google-code 的论坛 -这里)。将不胜感激任何帮助。

我还发现了一些关于Apache PDFBoxbug-tracker 的有用讨论:herehere

4

5 回答 5

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)jbig2pdf提取图像)(MyImageRenderListener)中提取。
2)转换jbig2JBIG2ImageReaderDemo

于 2012-08-30T18:12:50.550 回答
1

You have tools as ImageMagick which handle images and convert them to a lot of formats. I used it some years ago so I can't tell you if the jbig2 format is properly handled by default or if you have to install some plugin. You can try the following to have a list of supported formats beginning with J like the JBIG2 you are searching for:

$ convert -list format | grep -i J

It is really obvious to convert to pdf with with tool too, coupled with gs tool aka GhostScript.

If fact nothing prevent you to display a PNG/JPEG version of the image and provide a download link to the original JBIG2 file with its own metadatas.

于 2012-08-27T15:44:34.687 回答
1

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

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

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

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

2- 使用其他算法(jpeg、png 等)重新压缩它们。为了做到这一点,您可能需要在 Java 之外使用 JNI 或调用外部应用程序。例如,如果 GPL lincense 适合您的需要,您可以尝试使用jbig2dec或 ImageMagic。

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


这种方法将意味着这些图像的一些质量损失,但至少您将能够打印文件。

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

如果您使用的是基于 Windows 的服务器并且您负担得起商业工具,您也可以使用 C#/VB.Net 或 C++的Amyuni PDF Creator实现此目的(通常免责声明适用于此建议)。您只需要检查所有类型为acObjectTypePicture的对象并将属性 Compression 设置为 acJPegHigh,这种方法不需要任何外部 JBIG2 解码器(如果您有兴趣,我可以在此处包含一些示例代码)。

如果您使用小程序仅打印 PDF 文件,您还可以尝试生成一个 PDF 文件,该文件在打开时显示打印对话框

于 2012-08-24T14:04:10.557 回答
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

于 2012-08-23T15:59:33.817 回答
1

Borisvl 的 JPedal 库有一个分支,位于

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

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

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

在调用 getPixel 之前,您需要确保满足以下条件

col >= 0 并且 col < bitmap.width 行 >= 0 并且 row < 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);

安德鲁。

于 2012-09-07T10:40:40.900 回答