着色器渲染QR码

时间:2017-09-04 07:12:54

标签: qt shader opengl-es-2.0 qr-code qtquick2

Qt Quick 应用程序中以图形方式表示QR代码的最佳方式(在性能和内存消耗方面)是什么?

我认为QR码位图可以使用一些着色器以图形方式表示为黑白单元的方阵。这将是性能最佳的解决方案。

目前我只能使用一堆 Rectangle 创建 GridView 。它被认为是存储和CPU / GPU渲染时间的浪费。

着色器怎么样?

假设QBitArray大小为n*n

2 个答案:

答案 0 :(得分:1)

如果您在应用程序中只有一个QR码,那么请节省您的时间并进行GridView。

其他选项包括:

  • C ++ custom QQuickItem:生成并加载纹理(Qt SceneGraph API)
  • C ++ custom QQuickFramebufferObject:生成并加载纹理(主要是纯OpenGL API)
  • C ++ custom QQuickPaintedItem(QPainter 2D API)
  • QML-JS Canvas / Context2D(HTML 2D API)
  • QML-JS Canvas3D / Context3D:生成并加载纹理(WebGL API) - 与所有其他C ++选项一样,但在JS版本的OpenGL中
  • C ++ custom QQuickImageProvider:生成并加载纹理(ImageProvider和OpenGL API),同时将整个QR数据作为图像名称传递给自定义QQuickImageProvider(可能有点太聪明)

使用顶点缓冲区/均匀缓冲区而不是纹理可能有效,但它需要一个不寻常的着色器代码。我认为QR更符合纹理。

答案 1 :(得分:1)

着色器本身是微不足道的,基本上你将片段位置x和y除以qr代码大小和地板来获取行和列,然后通过添加两个来找到1d索引,然后查找qt数据数组在该索引处,如果它包含0,则片段颜色为白色,如果它包含1,则颜色为黑色。

但是,QML着色器目前还没有提供传递常规1d数组的工具。

您必须将数组转换为位图图像,并将其传递给数组,这意味着您还必须实现图像提供程序才能使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 qr代码大约需要2毫秒。 IMO非常好,花时间制作是不值得的更复杂的低级解决方案。

但是,我个人要做的是实现image provider,将qr代码数据转换为图像,然后使用smooth: false将图像缩放到我想要的大尺寸,这样可以避免模糊并保留结果很清晰。这是迄今为止最直接,最有效和最直接的解决方案。