为什么QFile::size()与QImage::sizeInBytes()差异大,Qt转PDF后文件过大?
问题原因及解决方案
1. 磁盘文件大小与QImage内存大小差异问题
你观察到的40KB磁盘文件大小和1MB左右的内存大小差异是完全正常的:
- 磁盘上的图像是经过压缩的格式(比如PNG、CCITT压缩的TIFF等),专门针对单色位图做了压缩优化,所以体积很小。
- QImage存储的是解压缩后的原始像素数据,你这张2479×3508分辨率的1位深度单色图,未压缩的原始大小计算为
2479 * 3508 / 8 = 1094496 字节,和你获取的sizeInBytes完全一致,不存在额外的内存开销,这个是位图加载的正常逻辑。
2. PDF体积过大的核心原因
你判断问题出在PDF写入环节是正确的,Qt默认的QPdfWriter存在两个导致体积膨胀的逻辑:
- 默认压缩级别极低,甚至部分旧版本Qt默认关闭了图像压缩
- 写入单色图像时默认会转换为24位RGB格式存储,直接把图像数据体积翻了24倍
3. 优化方案
代码层面优化(无需引入第三方库)
修改你的转换代码,添加两个核心优化点:
- 开启QPdfWriter最高压缩级别(Qt 5.10及以上版本支持)
- 强制保持图像为1位单色格式,避免Qt自动转高位格式
修改后的代码如下:
void Project::convertImgToPdf() { unsigned int i; QString path = projectPath + "/" + projectName + "/output/"; QDir dir(path + "/img"); // 过滤出真实的图像文件,避免遍历到.和..等特殊目录 QStringList imgList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); const QString fileName(path + "out.pdf"); const QPoint imageCoordinates(0,0); QPdfWriter pdfWriter(fileName); pdfWriter.setResolution(300); pdfWriter.setPageSize(QPageSize(QPageSize::A4)); // 开启最高级别的Deflate压缩,大幅减小体积 pdfWriter.setCompressionLevel(9); QPainter painter(&pdfWriter); for(i=0;i<imgList.size();i++) { QImage image(path + "img/" + imgList.at(i)); // 强制转换为1位单色格式,避免Qt自动转成高深度格式 image = image.convertToFormat(QImage::Format_Mono); if(i>0) { pdfWriter.newPage(); } painter.drawImage(imageCoordinates, image); } painter.end(); }
进一步压缩方案
如果修改后体积还是不符合要求,可以采用两步转换的方式:
- 先将所有图像批量保存为压缩后的PNG格式(你已经验证过单张仅35KB)
- 使用支持直接嵌入压缩PNG的PDF生成库(如libHaru、Poppler)将PNG直接嵌入PDF,不需要二次解码编码,最终PDF体积会和所有PNG的总大小基本一致。
内容的提问来源于stack exchange,提问作者user10782681
相关产品推荐
相关产品推荐

