专栏首页跟Qt君学编程Qt读取图片之小坑

Qt读取图片之小坑

❝来自于Qt技术交流群群友提出的问题,QImage读取不同的png图像,有些可以读取到有些读取不了,究竟是什么回事呢?❞

0x01 问题重现

  • 有图片1.png2.png
  • 1.png使用QImage读取成功,而2.png则不能正确读取图片。
qDebug() << "1.png: " << QImage("1.png");
qDebug() << "2.png: " << QImage("2.png");

分别输出:

1.png:  QImage(QSize(1222, 900),format=QImage::Format_ARGB32,depth=32,devicePixelRatio=1,bytesPerLine=4888,sizeInBytes=4399200)
2.png:  QImage(null)

0x02 问题分析

  可能是图片格式不对,于是使用二进制软件分别打开两个图片查看究竟是什么情况。 1.png图片内容:

2.png图片内容:

  通过查找资料可以看到png格式文件有固定头,解析出来的能看到有png字符串:

89 50 4E 47 0D 0A 1A 0A

  通过查看1.png格式的文件头内容是png格式文件的固定头内容,所以推断1.pngpng格式文件。  通过查看jpeg格式头内容和比对2.png的格式头内容可以断定2.pngjpeg格式的文件。   一般jpeg格式头内容为:(注:图片存储格式之一,由JPEG格式衍生而来,后缀为".jfif"。)

FF D8 FF E0 00 10 4A 46 49 46 00

0x03 问题解决

  • 方法1:使用图像软件转换为正确的图像,但该方法较为繁琐。
  • 方法2:使用QImage::fromData正确读取。如:
QFile file("2.png"); // 实际为jpeg格式
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
qDebug() << QImage::fromData(data);

输出:QImage(QSize(1048, 1234),format=QImage::Format_RGB32,depth=32,devicePixelRatio=1,bytesPerLine=4192,sizeInBytes=5172928)
  • 方法3:可以去除文件后缀然后再使用QImage读取。如:
qDebug() << QImage("2");
输出:
QImage(QSize(1048, 1234),format=QImage::Format_RGB32,depth=32,devicePixelRatio=1,bytesPerLine=4192,sizeInBytes=5172928)

或:

QImageReader reader("2");
qDebug() << reader.imageFormat() << reader.format();
输出:
QImage::Format_RGB32 "jpeg"

0x04 一些疑问解答

  1. 「究竟为什么会是jpeg格式的内容却是png的后缀呢?」 Qt君认为可能有保存图片的时候强制保存为带有png后缀的图片。
  2. 「为什么看图软件都能打开,而QImage却不能正确读取呢?」因为大多数看图软件都是通过读文件头信息去判断图片的格式,而「QImage是通过文件后缀去获取图片格式」,这就会有导致图片格式误判的问题。猜测可能是Qt出于性能考虑的原因吧。
  1. 「关于方法3为什么去除后缀后可以正确读取的问题?」 因为QImageReader内部会先判断文件是否有后缀,「如果有后缀」:就认为是改后缀图片再去验证图片是否有效,「如果没有后缀」,则会读取文件内容再去判断图片格式和验证图片是否有效的操作。

0x05 关于更多

  • 查看图片源内容软件:VScode的插件hexdump

本文分享自微信公众号 - Qt君(qtjuna),作者:Prosa

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Qt官方示例-使用布局

      通常,子窗口小部件使用布局对象而不是通过显式指定位置和大小来安排在窗口内。在这里,我们构造了一个QLabel和QLineEdit控件并使用QHBoxLayo...

    Qt君
  • QString的isEmpty与isNull区别

    (1)由于历史原因,Qt对无效字符串和空字符串进行了区分。对于大多数应用程序,重要的是字符串是否包含任何数据,这可以使用isEmpty()函数来确定;

    Qt君
  • Qt官方示例-TCP客户端/服务器示例

      这里比较有意思的是,客户端连接到服务器->客户端(tcpClient)触发startTransfer槽函数->调用tcpClient.write->触发QI...

    Qt君
  • 智能云上手指南:如何将历史数据迁移到万象优图

    6 月 21 日,腾讯云在 2017「云+未来」峰会上推出了战略新品——智能云,宣布将腾讯积累近 20 年的 AI 能力向政府、企业和开发者开放,其中首批开放计...

    云加社区
  • JavaScript与WebAssembly进行比较+在哪些情况下会优于JavaScript

    这是专门探索JavaScript及其构建组件的系列的第6期。在识别和描述核心元素的过程中,我们还分享了构建SessionStack时使用的一些经验法则,这是一个...

    前端博客 : alili.tech
  • Silverlight学习笔记:布局之stackpanel

    在用户界面设计方面的竞争多半是围绕着如何制作出有吸引力、实用、灵活的用户界面而展开的。在基于浏览器的应用中进行界面的设计则是一项更加需要技巧的工作,因为我们的客...

    大江小浪
  • 移动端,input输入框被手机输入法解决方案

    首先绑定触发元素(input)框,scrollIntoView(alignWithTop)  属性滚动浏览器窗口或容器元素,以便在当前视窗的可见范围看见当前元素...

    Happy、Liu
  • leetcode: 85. Maximal Rectangle

    From LeetCode 笔记系列 18 Maximal Rectangle [学以致用]:

    JNingWei
  • typecho对QQ社交软件的卡片分享优化

    1. 主要找到主题位置 /usr/theme/ 主题名称 / 2. 进行搜索文件名相关 head 的文件

    乔千
  • 【ACMMM2017硅谷盛宴】多媒体领域各大奖项出炉!电子科大斩获最佳论文!中科院自动化所多媒体计算组获得IEEE期刊最佳论文!

    【导读】第25届ACM国际多媒体会议(ACM International Conference onMultimedia, 简称ACM MM)于2017年10月...

    WZEARW

扫码关注云+社区

领取腾讯云代金券