打印包含JBIG2图像的PDF

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

PS我在applet中使用javax.print API

谢谢!

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

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

有任何想法吗?

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

我还在Apache PDFBox错误跟踪器上找到了一些有用的讨论: 这里和这里 。

Borisvl有一个JPedal图书馆的分支

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

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

编辑:该错误与简单范围检查有关。 基本上,您需要阻止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)创建包含jpegpdf

使用库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)从pdf提取jbig2 ( 提取图像 )( MyImageRenderListener )。
2)转换jbig2 ( JBIG2ImageReaderDemo )

如何使用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

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

 $ convert -list format | grep -i J 

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

事实上,没有什么可以阻止您显示图像的PNG / JPEG版本,并提供具有自己的元数据的原始JBIG2文件的下载链接。

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

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

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

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

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

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

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

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

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

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