• Qt 中大尺寸图片的处理


    我们的程序(用 Qt 实现),因为一个用户图标,在发到用户的产品中崩溃了。

    起因是这样的,我们允许用户注册上传自己的头像。然后中售卖的设备屏幕界面上,也会展示用户自己的头像。

    有一个用户上传了一个超大的头像图片,6144 x 6144 像素,jpg 的图片有 1.8M。然后他的设备的UI界面就经常卡死、崩溃。

    计算一下,假如图片每个像素 rgb 3 字节,那么 6144 * 6144 * 3 为 108M,对于 1个嵌入式平台,108 M已经很大了,申请这么大的内存很容易失败,那么程序崩溃就不足为奇了。

    虽然这个问题应该在输入端(即用户上传头像时)解决,但是展示端都应该自我保护,无论如何,不能够崩溃。

    下面看看 Qt/Qml 中怎么处理这种大尺寸图片。

    缩小展示

    对于这种大尺寸图片,可以改变输出图片的尺寸,将图片缩小展示。

    QImageReader

    中 Qt 中,除了直接用 QImage 加载图片,还有 QImageReader 这个更底层的 API。

    1. QImageReader reader(file);
    2. QImage image = reader.read();

    对于大尺寸图片,使用 QImageReader 可以设置输出图片的尺寸。根据实际需要展示的尺寸,来配置 QImageReader。

    1. QImageReader reader(file);
    2. reader.setScaledSize({60, 60});
    3. QImage image = reader.read();

    这样不管输入图片的尺寸是多少,输出图片最大只有 60 x 60 ,内存使用就很少了。 

    那么是否可以用 QImage::scaled 方法呢?像下面这样:

    1. QImage image(file);
    2. image = image.scaled({60, 60});

    不行的,因为应该中间图片尺寸任然很大, 还是有可能内存不足。

    实际上,QImageReader 是直接用目标尺寸来解压缩图片(比如 jpg 格式),与 QImage 的 scaled 方法无关。

    Image(QML)

    在 Qml 中,并不能直接使用 QImageReader,而是使用 Image 控件。能不能处理大尺寸图片呢?

    答案是肯定的,Image 有一个 sourceSize 属性,与 setScaledSize 是一样的。

    1. Image
    2. {
    3. source: "1.jpg"
    4. sourceSize: Qt.size(60, 60)
    5. }

    或者:

    1. Image
    2. {
    3. source: "1.jpg"
    4. sourceSize.width: 60
    5. sourceSize.height: 60
    6. }

    局部展示

    除了缩小展示图片,还可以不缩小图片,而是拖动图片以浏览各个区域。比如浏览一张大的全景照片,想要看到拍摄的局部细节。

    当然,内存的限制仍然存在。

    中 Qt 中,针对这种需求,也提供的相关的机制。

    QImageReader

    除了 scaledSize,QImageReader 还支持 clipRect、scaledClipRect。这里我们不需要 scale,直接用 setClipRect、用 setScaledClipRect 也是一样的。根据屏幕的展示尺寸来配置。

    1. QImageReader reader(file);
    2. reader.setClipRect({0, 0, 1280, 720});
    3. QImage image = reader.read();

    上面只展示大图片的左上角 1280 x 720 的大小。当用户拖动图片时,调整 clipRect 的 left、top 重新 read 即可。

    Image(QML)

    在 Qml 的 Image 中,也有相应的 sourceClipRect 属性。

    1. Image {
    2. source: "1.svg"
    3. sourceSize.width: 1024
    4. sourceSize.height: 1024
    5. sourceClipRect: Qt.rect(100, 100, 512, 512)
    6. }

    以上只是基础性介绍,实际使用中要考虑提高效率,不要因为只拖动了一点点,就要重新加载整个屏幕的图片。具体的方法要等以后遇到相关需求,研究后再来介绍。

  • 相关阅读:
    企业域名和企业邮箱究竟有什么关系?
    TCP和UDP的区别与联系以及网络字节序和主机字节序的转换函数实践
    HarmonyOS鸿蒙原生应用开发设计- 元服务(原子化服务)图标
    Java学习笔记6.1.2 字节流 - 文件字节输入流和文件字节输出流
    分享一个Redis自带的压测工具:redis-benchmark
    Spring系列-bean标签内autowire属性应用
    java基础巩固16
    web远程访问Windows桌面(二)
    在CentOS7上安装RabbitMQ(RPM安装方式)
    生物信息学如何学习R语言(知乎高赞)
  • 原文地址:https://blog.csdn.net/luansxx/article/details/126566337