一次单据图片处理的优化实践 | 京东物流技术团队

文章讲述了在京东物流开发中,通过ApachePDFBox库将PDF转换为PNG时遇到的性能瓶颈,特别是编码阶段耗时过长。作者分析了原因,提出从颜色类型优化、位深度调整和自定义编码器等方面进行改进,最终大幅提升了编码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 引言

日常开发中接到这样的需求,上游系统请求获取一张A4单据用于仓库打印及展示,要求PNG图片格式,但是我们内部得到的单据格式为PDF,需要提取PDF文档的元素并生成一张PNG图片。目前已经有不少开源工具实现了这一功能,我们找了网上使用比较多的Apache PDFBox库来实现功能,如下

// Step 1
PDDocument document = PDDocument.load(content);
PDFRenderer pdfRenderer = new PDFRenderer(document);
// 获取第1页PDF文档
OutputStream os = new ByteArrayOutputStream()
// Step 2
// 为了保证图片的清晰,这里采用600DPI
BufferedImage image = pdfRenderer.renderImageWithDPI(0, 600);
// Step 3
ImageIO.write(image, "PNG", os);

实际测试时,明显感觉到卡顿,当一次请求的单据数目较多时尤其严重。

经统计,各步骤本机单次运行耗时如下:

pdf 初始化(Step 1):2ms
文档提取及图片绘制(Step 2):520ms
图片编码 (Step 3):3823ms

我们发现,最后一句代码耗时接近4秒,拖累了整体性能。我们要如何优化这样一个问题呢?

2 BufferedImage介绍

在讨论优化问题之前,首先要搞清楚待优化的代码是做什么的。如上代码中,使用renderImageWithDPI方法,将文档元素绘制为BufferedImage对象。

根据描述,BufferedImage用来描述一张图片,其内部保存了图片的颜色模型(ColorModel)及像素数据(Raster)。这里简单解释就是,内部的Raster实现类中,以某种数据结构(如Byte数组)表示图片的所有像素数据,而ColorModel实现类,则提供了将每个像素的数据,转换为对应RGB颜色的方式。

BufferedImage的构造函数中,可以传入图片类型来决定使用哪一种ColorModel和Raster。引言的示例中,PDFRender源码中默认生成的图片类型为 TYPE_INT_RGB,这种类型表示,每一个像素使用R、G、B三条数据表示,每条数据使用单字节(0~255)表示。

public BufferedImage(int width, int height, int imageType)

需要注意的是,BufferedImage并不表示某一张具体的位图,而是通过描述每个像素的数据,抽象地表达一张图片,因此,它可以在内存中通过操作像素数据,直接改变对应图片。而通过ImageIO.write方法,可以将BufferedImage编码为具体格式的图片数据流。此方法会根据formatName选择该文件格式的编码器,来对BufferedImage内部的像素数据进行编码。

public static boolean write(RenderedImage im, String formatName, OutputStream output) throws IOException

以下代码为BufferedImage的简单应用

将一个GIF图片读取到BufferedImage中,在坐标(10,10)位置打出ABC三个字符,并重新编码成PNG图片

BufferedImage image = ImageIO.read(new File("exmaple.gif"));
image.getGraphics().drawString("ABC", 10, 10);
ImageIO.write(image, "PNG", new FileOutputStream("result.png"));

下面这段代码展示了另一类型的例子,它将图片中所有的红色像素点重置成黑色像素点

BufferedImage image = ImageIO.read(new File("example.gif"));
for(int i = 0 ; i < imag
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值