iText PDF;如何使用 Java 将 jpeg2000 转换为 jpg

     2023-02-25     28

关键词:

【中文标题】iText PDF;如何使用 Java 将 jpeg2000 转换为 jpg【英文标题】:iText PDF; howto convert jpeg2000 to jpg using Java 【发布时间】:2011-12-19 01:30:42 【问题描述】:

我正在尝试使用 java、iText 和 Java 高级成像库来解决问题。我的软件系统使用 ghostscript 从 PDF 文件创建 jpg 缩略图等。然而,在 CentOS 5.x 上,ghostscript 的最高版本是 8.7,它的一个已知问题是无法处理其中包含 JPEG 2000 图像的 PDF 文件。我的计划是先扫描文件,看看它是否包含 jpeg2000 图像(我已经弄清楚了这部分);如果是这样,则使用 iText 和 Java Advanced Imaging 库(包含 jpeg2000 读写编解码器)将包含的 jpeg2000 文件转换为常规 jpeg 文件,然后将新的 PDF 文件传递​​给 ghostscript。下面的代码尝试这样做,但会生成另一个包含 jpeg2000 文件的文件。对此的任何帮助将不胜感激。

public class ImageReplacer
    public static void main(String [] args)
        try
            String RESULT = "";
            PdfReader reader = new PdfReader("pdf_containing_jpeg2000_images.pdf");
            PdfReaderContentParser parser = new PdfReaderContentParser(reader);
            MyImageRenderListener listener = new MyImageRenderListener(RESULT);
            MyImageConverterListener clistener = new MyImageConverterListener(RESULT);
            clistener.setReader(reader);
            for (int i = 1; i <= reader.getNumberOfPages(); i++) 
                parser.processContent(i, clistener);
               
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("out.pdf"));
            stamper.close();            
        catch(Exception e)
            e.printStackTrace();    
        
    

class MyImageConverterListener implements RenderListener 
    protected String path = "";
    protected PdfReader reader;
    public MyImageConverterListener(String path) 
        this.path = path;
    
    public void beginTextBlock()  
    public void endTextBlock()  
    public void renderImage(ImageRenderInfo renderInfo) 
        try 
            PdfImageObject image = renderInfo.getImage();
            PdfName filter = (PdfName)image.get(PdfName.FILTER);
            if (PdfName.JPXDECODE.equals(filter)) 
                if(image.getDictionary().isStream())
                    BufferedImage bi = image.getBufferedImage();
                    if (bi == null) return; 
                    int width = (int)bi.getWidth();
                    int height = (int)bi.getHeight();
                    ByteArrayOutputStream imgBytes = new ByteArrayOutputStream(); 
                    ImageIO.write(bi, "JPG", imgBytes);
                    PRStream stream = new PRStream(reader,imgBytes.toByteArray());
                    stream.clear();
                    stream.setData(imgBytes.toByteArray(), false, PRStream.NO_COMPRESSION);
                    stream.put(PdfName.TYPE, PdfName.XOBJECT);
                    stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
                    stream.put(new PdfName("foo"+Math.random()), new PdfName("bar"+Math.random()));
                    stream.put(PdfName.FILTER, PdfName.DCTDECODE);
                    stream.put(PdfName.WIDTH, new PdfNumber(width));
                    stream.put(PdfName.HEIGHT, new PdfNumber(height));
                    stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
                    stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
                
            
         catch (Exception e) 
            e.printStackTrace();
        
    
    public void renderText(TextRenderInfo renderInfo)  
    public void setReader(PdfReader r)
        reader = r;
    

【问题讨论】:

【参考方案1】:

所以我设法自己解决了这个问题(在 iText 的帮助下,Bruno Lowagie 的行动 - 很棒的书)。重申一下,我的意图是使用 iText 扫描 PDF 以查看它是否包含任何 JPEG2000 图像,以及它是否输出相同的 PDF,但内部 JPEG2000 图像替换为常规 JPEG 图像。这解决了致命的 ghostscript 8.7“无法处理 JPXDecode 数据”错误,但也有助于使 PDF 的 iOS 兼容。

所以孩子们不用再做任何事情了;来了……

步骤 1) 下载 iText 5.x .jar 文件,并下载 jai_imageio-1.1.jar(Java 高级成像库,可让您转换 JPEG2000 文件)

步骤 2) 创建一个名为 PDFConverter.java 的文件并将此代码放入其中:

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.parser.PdfImageObject;
import com.itextpdf.text.pdf.PdfNumber;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.*;

public class PDFConverter
    public static void main(String [] args)
        if(args.length==1)
            if(hasJpeg2000(args[0]))
                System.out.println("Contains JPEG2000 images: Converting them to JPEG..."); 
                convertPDF(args[0]);
                System.out.println("Done...");
            else
                System.out.println("Doesn't contain any JPEG2000 images: Nothing to be done...");   
            
        else
            System.out.println("Please specify a PDF filename as a command line argument!");    
        
    
    public static boolean hasJpeg2000(String s)
        try
            PdfReader reader = new PdfReader(s); 
            int n = reader.getXrefSize();
            PdfObject object; 
            PRStream stream; 
            for (int i = 0; i < n; i++) 
                object = reader.getPdfObject(i); 
                if (object == null || !object.isStream())continue; 
                stream = (PRStream)object; 
                PdfImageObject image = new PdfImageObject(stream);
                PdfName filter = (PdfName)image.get(PdfName.FILTER);
                if (PdfName.JPXDECODE.equals(filter)) 
                    return true;
                
            
        catch(Exception e)
            e.printStackTrace();
        
        return false;
    
    public static void convertPDF(String s)
        try
            PdfReader reader = new PdfReader(s); 
            int n = reader.getXrefSize();
            PdfObject object; 
            PRStream stream; 
            for (int i = 0; i < n; i++) 
                object = reader.getPdfObject(i); 
                if (object == null || !object.isStream())continue; 
                stream = (PRStream)object; 
                PdfImageObject image = new PdfImageObject(stream);
                PdfName filter = (PdfName)image.get(PdfName.FILTER);
                if (PdfName.JPXDECODE.equals(filter)) 
                    BufferedImage bi = image.getBufferedImage(); 
                    if (bi == null) continue; 
                    int width = (int)(bi.getWidth());
                    int height = (int)(bi.getHeight());
                    ByteArrayOutputStream imgBytes = new ByteArrayOutputStream(); 
                    ImageIO.write(bi, "JPG", imgBytes); 
                    stream.clear(); 
                    stream.setData(imgBytes.toByteArray(),false, PRStream.NO_COMPRESSION); 
                    stream.put(PdfName.TYPE, PdfName.XOBJECT); 
                    stream.put(PdfName.SUBTYPE, PdfName.IMAGE); 
                    stream.put(new PdfName("foo"+Math.random()), new PdfName("bar"+Math.random())); 
                    stream.put(PdfName.FILTER, PdfName.DCTDECODE); 
                    stream.put(PdfName.WIDTH, new PdfNumber(width)); 
                    stream.put(PdfName.HEIGHT, new PdfNumber(height)); 
                    stream.put(PdfName.BITSPERCOMPONENT,new PdfNumber(8)); 
                    stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
                
            
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("out.pdf")); stamper.close();
        catch(Exception e)
            e.printStackTrace();
        
    
 

步骤3)按如下方式编译上述文件:

javac -cp .:iText-5.0.4.jar:jai_imageio-1.1.jar PDFConverter.java

第 4 步)使用 PDF 运行程序...

java -cp .:iText-5.0.4.jar:jai_imageio-1.1.jar PDFConverter PDFFileName.pdf

嘘……

【讨论】:

【参考方案2】:

效果很好,但我在使用 GlassFish v3.1 时遇到了一些问题。 Glassfish 的行为就像 Classpath 中没有 jai_imageio-1.1.jar 一样。我修复了这个问题,将 jai_imageio.jar 放在我的“/path/to/glassfish/domains/domain1/lib/ext/”文件夹中。

【讨论】:

【参考方案3】:

我在使用 Reece 的 PDFConverter 时遇到了一些 NullPointer 问题,因为我的 PDF 在 GhostScript on CentOS 5.3 - Unable to process JPXDecode data 中有不同类型的嵌入元素。所以我做了一些对象/类型检查并将输出文件名添加到命令行。

其他一切都很棒,并且非常适合图像 jpeg2000 问题。感谢里斯 :)

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.parser.PdfImageObject;
import com.itextpdf.text.pdf.PdfNumber;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.*;

public class PDFConverter

    public static void main(String [] args)
        if(args.length==2)
            if(hasJpeg2000(args[0]))
                System.out.println("Contains JPEG2000 images: Converting them to JPEG..."); 
                convertPDF(args[0], args[1]);
                System.out.println("Done...");
            else
                System.out.println("Doesn't contain any JPEG2000 images: Nothing to be done...");
            
        else
            System.out.println("Please specify a PDF filename and a output filename as a command line arguments!");
        
    

    public static boolean hasJpeg2000(String s)
        try
            PdfReader reader = new PdfReader(s); 
            int n = reader.getXrefSize();
            PdfObject object; 
            PRStream stream; 
            for (int i = 0; i < n; i++) 
                object = reader.getPdfObject(i); 
                if (object == null || !object.isStream())continue; 
                stream = (PRStream)object; 
                PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
                System.out.println(pdfsubtype);
                if (pdfsubtype != null && pdfsubtype.toString().equals(PdfName.IMAGE.toString())) 
                    PdfImageObject image = new PdfImageObject(stream);
                    PdfName filter = (PdfName)image.get(PdfName.FILTER);
                    if (PdfName.JPXDECODE.equals(filter)) 
                        return true;
                    
                
            
        catch(Exception e)
            e.printStackTrace();
        
        return false;
    

    private static void filterObject(PdfImageObject image,PdfName filter,PRStream stream) throws java.io.IOException 
        if (PdfName.JPXDECODE.equals(filter)) 
            BufferedImage bi = image.getBufferedImage();
            if (bi == null) return;
            int width = (int)(bi.getWidth());
            int height = (int)(bi.getHeight());
            ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
            ImageIO.write(bi, "JPG", imgBytes);
            stream.clear();
            stream.setData(imgBytes.toByteArray(),false, PRStream.NO_COMPRESSION);
            stream.put(PdfName.TYPE, PdfName.XOBJECT);
            stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
            stream.put(new PdfName("foo"+Math.random()), new PdfName("bar"+Math.random()));
            stream.put(PdfName.FILTER, PdfName.DCTDECODE);
            stream.put(PdfName.WIDTH, new PdfNumber(width));
            stream.put(PdfName.HEIGHT, new PdfNumber(height));
            stream.put(PdfName.BITSPERCOMPONENT,new PdfNumber(8));
            stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
        
    

    public static void convertPDF(String s, String out)
        try
            PdfReader reader = new PdfReader(s); 
            int n = reader.getXrefSize();
            PdfObject object; 
            PRStream stream; 
            for (int i = 0; i < n; i++) 
                object = reader.getPdfObject(i); 
                if (object == null || !object.isStream())continue; 
                stream = (PRStream)object; 
                PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
                if (pdfsubtype != null && pdfsubtype.toString().equals(PdfName.IMAGE.toString())) 
                    PdfImageObject image = new PdfImageObject(stream);
                    Object listOrName = image.get(PdfName.FILTER);
                    if (listOrName instanceof PdfName) 
                        PdfName filter = (PdfName)image.get(PdfName.FILTER);
                        filterObject(image, filter, stream);
                    
                    else if (listOrName instanceof PdfArray) 
                        PdfArray list = (PdfArray)image.get(PdfName.FILTER);
                        for (int j = 0; j < list.size(); j++) 
                            PdfName filter = list.getAsName(j);
                            filterObject(image, filter, stream);
                        
                    
                    else 
                        System.err.println("Unknown Obejcttype: " + listOrName);
                    
                
            
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(out)); stamper.close();
         catch(Exception e)
            e.printStackTrace();
        
    

 

【讨论】:

如何运用java组件itext生成pdf

  如何使用Java组件itext生成pdf?iText是一个能够快速产生PDF文件的java类库。iText的java类对于那些要产生包含文本,表格,图形的只读文档是很有用的。它的类库尤其与javaServlet有很好的给合。使用iText与PDF能够使你正确的控制Se... 查看详情

如何使用 iText 为我的 (pdf-) 文本添加背景颜色以使用 Java 创建它

】如何使用iText为我的(pdf-)文本添加背景颜色以使用Java创建它【英文标题】:HowcanIaddabackgroundcolortomy(pdf-)textusingiTexttocreateitwithJava【发布时间】:2012-08-1418:42:44【问题描述】:起初:我对可用于创建pdf的框架的了解并不是最好的... 查看详情

java示例代码_使用iText将内容写入pdf

java示例代码_使用iText将内容写入pdf 查看详情

java示例代码_使用iText将HTML转换为PDF

java示例代码_使用iText将HTML转换为PDF 查看详情

如何使用 iText 将 HTML 转换为 PDF [重复]

】如何使用iText将HTML转换为PDF[重复]【英文标题】:HowtoconvertHTMLtoPDFusingiText[duplicate]【发布时间】:2013-07-2310:38:16【问题描述】:importjava.io.File;importjava.io.FileOutputStream;importjava.io.OutputStream;importcom.itextpdf.text.Document;impo 查看详情

如何运用java组件itext生成pdf

 首先从iText的官网下载这个开源的小组件。  iText官方网站  Java版iText组件  Java版工具包  C#版iText组件  C#版工具包  这里笔者使用的是Java版itext-5.2.1。  将itext-5.2.1.zip压缩包解压缩后得到7个文件:itextpdf-5.2.1.... 查看详情

使用 iText 将字体嵌入 PDF 文件

...。我想使用iText将XML数据文件转换为PDF。问题是XML转PDF时如何在目标PDF中嵌入字体(如波兰字体、中文字体)?【问题讨论】:【参考方案1】:如果您正在使用iText做更多的工作,您可能想要投资iTex 查看详情

如何使用 iText 获取 Pdf 表单字段的自定义格式脚本?

】如何使用iText获取Pdf表单字段的自定义格式脚本?【英文标题】:HowdoIgetCustomFormatScriptofPdfformfieldsusingiText?【发布时间】:2014-04-0212:42:01【问题描述】:我有一个pdf表单,我正在使用iText和Java通过代码将一些数据写入pdf字段。... 查看详情

无论如何使用iText保存交互式pdf?

】无论如何使用iText保存交互式pdf?【英文标题】:IsthereanywaytosaveaninteractivepdfusingiText?【发布时间】:2014-01-1421:19:50【问题描述】:我们向用户显示一个pdf,其中有空白字段需要填写。现在,用户必须填写pdf,在他/她的机器上... 查看详情

如何使用 iText 将带有图像和超链接的 HTML 转换为 PDF?

】如何使用iText将带有图像和超链接的HTML转换为PDF?【英文标题】:HowcanIuseiTexttoconvertHTMLwithimagesandhyperlinkstoPDF?【发布时间】:2016-06-0606:19:21【问题描述】:我正在尝试在使用MVC、和webforms的ASP.NETWeb应用程序中使用iTextSharp将HTML... 查看详情

java示例代码_使用Java和IText,如何从PDF中提取AcroForm字段名

java示例代码_使用Java和IText,如何从PDF中提取AcroForm字段名 查看详情

如何使用 iText 将没有所有者密码的仅用户密码添加到 PDF

】如何使用iText将没有所有者密码的仅用户密码添加到PDF【英文标题】:HowtoaddonlyuserpasswordwithoutownerpasswordtoaPDFusingiText【发布时间】:2013-01-2001:10:02【问题描述】:如何在不使用iText添加所有者密码的情况下仅向pdf文件添加用户... 查看详情

如何使用 iText 获取使用多种字体呈现的 pdf

】如何使用iText获取使用多种字体呈现的pdf【英文标题】:HowtouseiTextgetpdfrenderedwithmultiplefonts【发布时间】:2020-02-1207:20:20【问题描述】:我正在使用iText将包含英文和中文字符的html解析为pdf。我正在使用//forpdfrenderingcompilegroup:\'... 查看详情

使用 iText 7 将 HTML 模板转换为 PDF:如何移动跨页打印的表格

】使用iText7将HTML模板转换为PDF:如何移动跨页打印的表格【英文标题】:ConvertHTMLTemplatetoPDFusingiText7:howtomoveatablethatprintsacrosspages【发布时间】:2021-07-2200:20:57【问题描述】:我正在开发一个asp.netmvc项目,并且我正在使用一个html... 查看详情

如何在 PHP 中使用 iText java PDF 库?

】如何在PHP中使用iTextjavaPDF库?【英文标题】:HowtouseiTextjavaPDFlibrarywithPHP?【发布时间】:2011-05-2209:34:10【问题描述】:Google搜索结果表明可以通过PHP/JavaBridge进行。此网桥需要Java应用程序服务器。我的主机(bluehost)不允许运行任... 查看详情

如何使用 iText7 检测 PDF 中的 fontawesome 图标

】如何使用iText7检测PDF中的fontawesome图标【英文标题】:HowtodetectafontawesomeiconinaPDFusingiText7【发布时间】:2022-01-0516:40:43【问题描述】:我有几千个PDF,我正在使用Powershell和iText7处理,将PDF的文本导出到Excel。PDF是从HTML生成的—... 查看详情

使用java和itext,如何从pdf中提取acroform字段名称?

我正在寻找一个简单的API示例,它将PDF文件/模板作为输入读取,并迭代PDF表单中定义的字段(我认为它被称为AcroForm)答案好的,我找到了解决方案publicstaticvoidscanFields(Stringpath)throwsIOException{PdfReaderpdfReader=newPdfReader(path);AcroFieldsa... 查看详情

java已经获取pdf代码,如何把他pdf文件保存到本机要求用输出流做

一、iText介绍  iText是着名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。  iText的安装非常方便,在http://www.lowagie.com/iTex... 查看详情