请建议我一些能帮助我打印包含JBIG2编码图像的PDF文件的库。 PDFRenderer
,PDFBox
不帮助我。这些库可以打印简单的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)。非常感谢任何帮助。
答案 0 :(得分:3)
在 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
(extract images)(MyImageRenderListener)中提取pdf
。
2)转换jbig2
(JBIG2ImageReaderDemo)
答案 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来实现此目的。 )。你只需要遍历acObjectTypePicture和set 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);
安德鲁。