gpt4 book ai didi

java - 图像缓存和性能

转载 作者:行者123 更新时间:2023-11-30 11:42:55 25 4
gpt4 key购买 nike

我目前正在尝试改进 map 渲染库的性能。在准时符号的情况下,图书馆实际上经常只是在每个位置上一次又一次地绘制相同的图像。不过,绘制过程可能真的很复杂,因为符号的参数化非常丰富。对于每个点,我都有一个树结构来计算要绘制的图像。当参数不依赖于我正在处理的数据时,正如我之前所说,我只是多次绘制一个复杂的符号。

我已经尝试实现缓存机制。我把已经绘制好的图片存储起来,如果遇到已经满足的配置,我就拿到图片重新绘制。我所做的第一个测试是针对一个非常简单的符号。这是一个形状和内部都被填充的圆。

我知道这个符号在所有位置都是不变的,我缓存它然后从缓存的图像中再次绘制它。这行得通......但我面临两个重要问题:

  • 绘制符号的质量几乎没有损坏。
  • 问题更多:使用缓存渲染 map 所需的时间确实比不使用缓存要长。这对于缓存来说是相当令人失望的 ^_^

开启缓存机制时的核心代码如下:

if(pc.isCached(map)){
BufferedImage bi = pc.getCachedValue(map);
drawCachedImageOnGeometry(g2, sds, fid, selected, mt, the_geom, bi);
} else {
BufferedImage bi = g2.getDeviceConfiguration().createCompatibleImage(200, 200);
Graphics2D tg2 = bi.createGraphics();
graphic.draw(tg2, map, selected, mt, AffineTransform.getTranslateInstance(100, 100));
drawCachedImageOnGeometry(g2, sds, fid, selected, mt, the_geom, bi);
pc.cacheSymbol(map, bi);
}

在 drawCachedImageOnGeometry 中唯一有趣的调用是

g2.drawRenderedImage(bi, AffineTransform.getTranslateInstance(x-100,y-100));

我已经尝试使用 VolatileImage 实例而不是 BufferedImage...但这会导致更深层次的问题(我无法确保每次需要时图像都能正确呈现)。

我也做了一些分析,似乎在使用我的缓存时,花费时间最长的操作是在 awt 中进行的渲染操作。

也就是说,我想我的策略是错误的...因此,我的问题是:

  • 是否有任何有效的方法可以实现我所解释的目标?
  • 更准确地说,存储用于绘制我的符号的 AWT 指令并根据需要翻译它们会更快吗?我假设有可能检索用于构建符号的“命令”......我没有在万维网上找到很多关于它的信息......如果可能的话,那将节省符号的计算时间(如前所述,这可能非常复杂)和符号的质量。

提前感谢您提供给我的所有信息和资源:-)

年龄。

编辑:这里有一些关于可以渲染的图形的细节。根据我正在实现的符号模型,图形可以非常简单(即一个填充正方形及其形状)也可以非常复杂(例如,形状和填充都用影线绘制的标签,即使光晕如果我愿意,可以围绕它)。我想使用缓存,因为我确信在大多数配置中我都能够:

  • 区分用于绘制具有相同样式的同一来源的两个不同符号的参数。
  • 确保具有相同参数(位置除外)的两个源将针对相同的样式生成相同的符号,但在两个不同的位置(只需要翻译)。

因为这两点,缓存似乎是一个很好的策略。此外,可能有数千个重复符号要绘制在同一图像中。

最佳答案

对于您的绘图真正需要什么样的操作,您非常模糊,所以我只能给您一些非常笼统的指示。

1.) 绘制预渲染图像不一定比使用 Graphics2D 操作绘制相同图像更快。这在很大程度上取决于绘制图像所需的复杂性。作为一种极端情况,请考虑包含预渲染矩形的图像的 fillRect() 与 drawImage()(fillRect 仅写入目标像素,其中 drawImage 还需要从源复制)。

2.) 在大多数情况下,您从不 想直接弄乱 VolatileImage。 BufferedImage 会自动利用 VolatileImage,除非您弄乱了 Image DataBuffer。如果您有许多预渲染图像,您也可能会耗尽加速视频内存,这会降低图像绘制性能。

3.) 预渲染图像的即时缩放/旋转等可能会非常昂贵(取决于平台和当前的图形转换)。

4.) 您创建的“兼容图像”可能与绘图目标并不真正兼容。您获得与默认屏幕设备兼容的图像,这可能与多监视器设置中的实际目标不兼容。使用实际的目标组件 createImage() 可能会获得更好的结果。

编辑:

5.) 翻译渲染操作的坐标可能改变生成的目标像素。一个明显的情况是当坐标是非整数时(在坐标本身中或间接通过图形上设置的 AffineTransform)。此外,文本和可能的其他图元的抗锯齿可能会受到坐标的轻微影响(想到亚像素渲染)。


您可以尝试一种方法来区分符号的呈现速度是快还是慢。快的直接渲染,慢的缓存。这里的主要问题是决定哪些快/慢,我希望这个决定很重要。

此外,我想知道您何时说要呈现数千个符号,因为我想应该将其中的大部分剪掉,因为只有一小部分图形适合窗口/框架?如果是这样的话,不要太在意缓存。完全在当前剪辑边界之外的绘图操作将相对便宜 - 所有图形目标真正为它们做的是检测它们是否完全不可见以及它们什么都不做。如果目标是生成要保存到磁盘/打印(无论如何)的图像,我不会太在意加速渲染,因为这是一个相对罕见的操作,实际打印可能远远超过渲染所需的时间无论如何图表。

如果以上都不适用于您的情况,请注意您的缓存不会使用比实际节省的渲染时间更多的时间/内存来确定缓存版本是否存在。您还需要考虑到,如果从不重复使用该图像,那么构建缓存图像而不是直接渲染到目标会花费您一些时间。如果图像被重复使用至少一次,最好是多次,则缓存只能提高一些速度。

如果您通过组合原始渲染操作对象(例如矩形、光晕和文本渲染对象子类)从原始操作构建您的符号,您可能希望为它们中的每一个分配一个成本指示器,并且只缓存那些超过的符号一些(待定)成本阈值。此外,为每个原始操作和符号本身实现一个 hashCode() 以进行快速(呃)等于检测可能是个好主意。

关于java - 图像缓存和性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11471621/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com