光栅化 Alpha8 格式的 QML SVG 图像
Posted
技术标签:
【中文标题】光栅化 Alpha8 格式的 QML SVG 图像【英文标题】:Rasterize QML SVG Image in Alpha8 format 【发布时间】:2016-11-26 17:25:41 【问题描述】:在 QML 中导入一组 80 个图标作为不可见图像用于着色器源(用于任意着色):
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 的内存。但是,这样的成本是不可接受的,尤其是在使用该应用程序定位手机的情况下。
我可以减小光栅化大小,但是,我希望图标美观且清晰。图标大小本身因设备显示而异,但为了获得最佳用户体验,它需要大约一英寸左右。鉴于大多数新的高端手机已经超过 500 dpi,我真的不想缩小图标并让它们显得模糊。
由于 SVG 应该以任意颜色着色,因此它们实际上只是 alpha 蒙版,这意味着我真正需要的只是这 4 个通道之一。不幸的是,QML 的Image
似乎没有提供任何类型的控制,SVG 被光栅化为 RGBA 图像。
确实,如果我
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。
任何想法如何节省一些内存?
【问题讨论】:
如果您不需要更改显示尺寸,您可以在 C++ 中执行此操作并缓存生成的图像/位图。根据平台,这甚至可能在安装时实现 qmlShaderEffect
需要图像,我还没有测试过它是否可以直接与QImage
一起使用,但如果它确实考虑到 qml 的设计决策和缺乏内置 qml 的 Image
和 QImage
之间的互操作性。
有趣,我会假设它可以工作,因为QImage
是像素数据图像的主要 C++ 类型,并且 QQuick Image
元素也使用它。
@KevinKrammer - QImage
在 qtquick1 中使用 QML,但在 qtquick2 中已删除,现在您需要推出自己的图像提供程序来获得互操作性。
我不确定 QtQuick1 有 ShaderEffect,我认为这是 QtQuick2 中的新功能。还是您的意思是Image
元素?它在内部使用QImage
IO 基础架构,是的,您可以使用图像提供程序来提供通过自定义 URL 在其他地方加载的图像。在缓存图像的情况下没有必要,因为当然可以简单地使用每个图像的文件 URI。
【参考方案1】:
2 小时后 - 好消息,首先,自定义 QQuickImageProvider
与 QImage::Format_Alpha8
开箱即用,没有问题。消除不必要的渠道。
但更重要的是,我意识到这些图标非常适合表示距离场。所以我现在使用 128x128 SDF 纹理,它可以很好地缩放到远高于 512x512,将图标的内存使用量减少到区区 1.25 mb,与初始实现相比,内存使用量总共减少了 64 倍。
唯一的缺点是 3-4 秒(在 Note 3 手机上)额外启动,因为距离场是在启动时计算的,但也有补救措施,我可能会切换到预先计算的 SDF 或卸载如果到着色器,这会稍微复杂一些,但应该将时间减少至少 5 倍。
【讨论】:
以上是关于光栅化 Alpha8 格式的 QML SVG 图像的主要内容,如果未能解决你的问题,请参考以下文章
QGis:如何将svg或光栅图像导入Quantum GIS?
我可以阻止静止的 SVG 图像在 QML 中使用过多的 CPU 资源吗?
iPhone Safari 中的 PNG 图像呈现光栅化问题