• 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. }

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

  • 相关阅读:
    mysql面试题4:MySQL中什么是聚集索引、非聚集索引?什么是MySQL主键索引、唯一索引、全文索引?
    opencv的approxPolyDP函数
    在Centos上配置bgp路由
    linux shell 脚本 入门到实战详解[⭐建议收藏!!⭐]
    IPTABLES问题:DNAT下如何解决内网访问内部服务器问题
    获取店铺所有商品API 返回值说明
    springcloud:1.Eureka详细讲解
    亿发软件:智慧门店商超系统,2023新零售POS数字运营一体化管理
    VW ware安装Ubuntu虚拟机及环境配置
    七月集训(2)字符串
  • 原文地址:https://blog.csdn.net/luansxx/article/details/126566337