You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么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. 优化方案

代码层面优化(无需引入第三方库)

修改你的转换代码,添加两个核心优化点:

  1. 开启QPdfWriter最高压缩级别(Qt 5.10及以上版本支持)
  2. 强制保持图像为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:00:02