渲染二维码的着色器
Posted
技术标签:
【中文标题】渲染二维码的着色器【英文标题】:Shader to render QR code 【发布时间】:2017-09-04 07:12:53 【问题描述】:在 Qt Quick 应用程序中以图形方式表示 QR 码的最佳(就性能和内存消耗而言)方法是什么?
我认为 QR 码位图可以使用一些着色器以图形方式表示为黑白单元格的方阵。这将是性能最佳的解决方案。
目前我只能用一堆矩形创建一个GridView。这被认为是浪费内存来存储和 CPU/GPU 时间来渲染。
着色器的外观如何?
说,给定 QBitArray
的 n*n
大小。
【问题讨论】:
【参考方案1】:着色器本身是微不足道的,基本上你将片段位置 x 和 y 除以 qr 代码大小和得到行和列的地板,然后通过将两者相加找到 1d 索引,然后查找 qt 数据数组在该索引处,如果包含 0,则片段颜色为白色,如果包含 1,则颜色为黑色。
但是,QML 着色器目前不提供传递常规一维数组的工具。
您必须将数组转换为位图图像,并将其传递给数组,这意味着您还必须实现图像提供程序以使QImage
与 QML 一起使用,因为令人惊讶的是,它仍然默认情况下不会。
我不会太在意性能,这是过早的优化,在 99% 的情况下都是不好的。即使是简单的 100% QML 解决方案也足够快:
ApplicationWindow
id: main
visible: true
width: 640
height: 480
color: "darkgray"
property var qrdata: []
MouseArea
anchors.fill: parent
onClicked:
qrdata = []
for (var i = 0; i < (100 * 100); ++i) qrdata.push(Math.round(Math.random()))
code.requestPaint()
Canvas
id: code
width: 300
height: 300
onPaint:
console.time("p")
var c = getContext("2d")
c.fillStyle = Qt.rgba(1, 1, 1, 1);
c.fillRect(0, 0, width, height)
c.fillStyle = Qt.rgba(0, 0, 0, 1);
var l = qrdata.length
var step = Math.sqrt(l)
var size = width / step
for (var i = 0; i < l; ++i)
if (qrdata[i])
var rw = Math.floor(i / step), cl = i % step
c.fillRect(cl * size, rw * size, size, size)
console.timeEnd("p")
在我的系统上,绘制一个 100 x 100 的二维码大约需要 2 毫秒。 IMO 足够好,花时间制作更复杂的低级解决方案并不值得。
但是,我个人会做的是实现image provider,将二维码数据转换为图像,然后使用smooth: false
将图像缩放到我想要的任意大小,这将避免模糊并保持清晰的结果。这是迄今为止最直接、最有效和最直接的解决方案。
【讨论】:
是否可以生成非光栅图像?比如说,SVG xml? @Orient - 没有意义,因为 SVG 仍然被光栅化以呈现特定大小。 SVG QR 码将比位图占用更多空间。如果禁用平滑,位图将无限放大。【参考方案2】:如果您的应用程序中只有一个 QR 码,那么请节省您的时间并使用 GridView。
其他选项有:
C++ 自定义QQuickItem
:生成和加载纹理(Qt SceneGraph API)
C++ 自定义QQuickFramebufferObject
:生成和加载纹理(主要是纯 OpenGL API)
C++ 自定义QQuickPaintedItem
(QPainter 2D API)
QML-JS Canvas/Context2D (html 2D API)
QML-JS Canvas3D/Context3D:生成和加载纹理 (WebGL API) - 与所有其他 C++ 选项一样,但在 JS 版本的 OpenGL 中
C++ 自定义 QQuickImageProvider
:生成并加载纹理(ImageProvider 和 OpenGL API),同时将整个 QR 数据作为图像名称传递给您的自定义 QQuickImageProvider
(可能有点太聪明了)
使用 vertex-buffers/uniform-buffers 代替纹理可能有效,但它需要一个不寻常的着色器代码。我认为 QR 更适合作为纹理。
【讨论】:
相反,着色器实际上将是一个非常普通和琐碎的着色器。以上是关于渲染二维码的着色器的主要内容,如果未能解决你的问题,请参考以下文章