关于qt:以Alpha8格式栅格化QML SVG图像

Rasterize QML SVG Image in Alpha8 format

在QML中导入80个图标集作为不可见图像以用于着色器源(用于任意着色):

1
2
  property Image action: Image { sourceSize.width: 512; sourceSize.height: 512; source:"icons/action.svg"; mipmap: true; antialiasing: true }
  // 79 more of those

我发现我的内存消耗猛增,从45 mb增长到128 mb,增幅高达185%,也就是80个图标增加了83 mb。

毕竟,512 * 512 * 4 / 1024 / 1024恰好构成了1 mb的内存。但是,这笔费用是不可接受的,尤其是在使用该应用定位手机的情况下。

我可以减小栅格化的大小,但是,我希望图标既美观又清晰。图标大小本身根据设备显示的不同而有所不同,但是为了获得最佳的用户体验,图标大小大约需要1英寸左右。考虑到大多数新的高端手机已经将速度提高到500 dpi以上,我真的很讨厌缩小图标的大小并使它们显得模糊。

由于SVG应该以任意颜色进行着色,因此它们实际上只是alpha蒙版,这意味着我真正需要的只是这4个通道之一。不幸的是,QML的Image似乎没有提供任何控制,SVG被光栅化为RGBA图像。

确实,如果我

1
2
3
4
5
6
7
8
9
10
11
  QVector<QImage> imgs;
  imgs.reserve(80);
  QDirIterator it(":/icons", QDirIterator::Subdirectories);
  while (it.hasNext()) {
      QSvgRenderer renderer (it.next());
      QImage ic(512, 512, QImage::Format_Alpha8);
      ic.fill(Qt::transparent);
      QPainter pp(&ic);
      renderer.render(&pp);
      imgs.append(ic);
  }

我得到了预期的20 mb内存使用量的适度增长。

有什么想法可以节省一些内存吗?


2小时后-好消息,首先,自定义QQuickImageProviderQImage::Format_Alpha8一起工作即可使用,在那里没有问题。 消除了不必要的渠道。

但更重要的是,我意识到这些图标非常适合用于距离场表示。 因此,我现在使用128x128 SDF纹理,可以很好地缩放到512x512以上,将图标的内存使用量减少到仅1.25 mb,与最初的实现相比,总共可以减少ram使用量64倍。

唯一的缺点是需要额外启动3-4秒(在Note 3手机上),因为距离字段是在启动时计算的,但是对此也有解决方法,我可能会切换到预先计算的SDF或卸载到着色器中 ,这会有些复杂,但应将时间减少至少5倍。