当前位置: 首页 > 知识库问答 >
问题:

图像的快速Java2D硬件缩放

徐飞龙
2023-03-14

我正在尝试在运行时使用Java2D和某种像样的抗锯齿插值(如双线性)来扩展backbuffer。我的想法是将场景渲染到此图像,然后在全屏模式下放大图像,以匹配用户具有的任何分辨率。

请注意,全屏模式很重要。这在窗口模式下不会发生。

有没有一种使用硬件扩展的快速方法?Javadocs建议它存在(-Dsun.java2d.ddscale=true),但它对我没有影响。

代码如下:

// Initialization in AWT Canvas
buffer_ = createImage(1280, 800);

// Several hundred large draw calls into the buffer that renders the entire scene - executes fast (~10ms)
drawScene(buffer_.getGraphics());

// Upscaling buffer to screen. If I don't upscale it executes very fast (<1ms)
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(buffer_, 0, 0, 1920, 1200, null);

结果是:

  • 最近邻(约2ms)

该图像是TYPE\u INT\u RGB不透明缓冲图像,我正在AWT画布上绘制。

我尝试过的其他事情:

  • VolatileImage(无性能变化)
  • Dsun.java2d.ddscale=true(无变化)
  • Dsun.java2d.opengl=true(所有命令大约慢3倍)
  • AffineTransform(无变化)
  • 通过调用Graphics2D. scale创建BufferPolicy和“预缩放”(慢得多,缩放每个绘制调用而不是1个大缓冲区)。请注意,没有缩放的BufferPolicy无论如何都不会提高速度。
  • JPanel而不是Canvas(大约慢1.5倍)
  • imgScalr"库"(这只是调用g.draw图像与我上面的完全一样)

其他一些有用的注释:

  • buffer_u。getCapabilities(gc)。isAccelerated()返回false(在窗口模式下为true)

感谢您的任何帮助。在这一点上,我很遗憾地考虑将所有内容转换为GL,只是为了这一件事...不过一定有答案!

共有2个答案

巫新知
2023-03-14

在上述情况下,我还没有获得全屏独占模式,但我确实有一个解决方法。

保持窗口模式,将窗口大小设置为与屏幕大小匹配,将其位置设置为图形设备。getDefaultConfiguration()。getBounds(),然后设置未装饰(true)。最后,使用java。awt。Robot将鼠标指针限制在窗口。

不理想,但在视觉上它与全屏无法区分,至少现在双线性比例很快。不幸的是,这意味着用户不能将他们的全屏分辨率设置为低于他们的原始分辨率。

顺便说一句,我看到使用BufferedImage(从2毫秒下降到1毫秒)和使用VolatileImage(下降到0.3毫秒)可以获得一些非常显著的绘制性能改进,前提是我在VM参数中有-Dsun.java2d.accthreshold=0。但是在全屏模式下,这些性能改进消失了(可能求助于软件扩展解决方案)

阚正真
2023-03-14

虽然我认为你的方法在技术上是可行的,但我想知道为什么你如此热衷于以固定的分辨率渲染。

从图形质量的角度来看,应该立即渲染到目标分辨率,完全消除缩放。我意识到位图图形(如平铺等)需要在某个点进行缩放,只是我不明白为什么需要在关键路径上(实时)进行缩放。我的首选方法是将位图预缩放到其所需的分辨率一次(然后要么将其缓存在内存中,要么甚至在磁盘上,这取决于哪个更可行)。

您可能需要检查几件事,确保内部使用的图像类型与渲染表面兼容(不要使用硬编码的type\u INT\u RGB,而是使用createCompatibleImage的变体创建后台缓冲区,以确保不需要格式转换)。此外,还有一整套选项可以改变Graphics2D在引擎盖下使用的内容:http://docs.oracle.com/javase/7/docs/technotes/guides/2d/flags.html.

最后,您可能需要检查您没有对缓冲图像执行任何“禁止”操作,例如直接访问底层缓冲阵列(无法加速像素修改的缓冲图像),这会干扰Java使用硬件加速的能力。

 类似资料:
  • 问题内容: 我试图创建一个执行大量2D转换和形状渲染的快速图像生成器,所以我试图使用BufferedImage然后获取Graphics2D对象来执行所有绘图。我现在主要关心的是制作速度非常快,因此我正在创建一个BufferedImage,如下所示: 但是,如果我这样做: 输出始终为 false ,即使我使用-Dsun.java2d.opengl = True启动JVM也会显示以下行: 我正在执行B

  • 问题内容: 使用Graphics2D,我如何拍摄黑白图像,并用来定义 在另一幅图像上应该渲染和不应该渲染的图像? 例如,如果我有一个图像,例如一个字段,并且在该字段上是一头 母牛,那么在用Java渲染时 , 在相同尺寸的另一幅图像上,我会在黑色背景上以与母牛相同的坐标绘制一个白框图像会是 全黑的,除了我有白盒子的那头牛? 问题答案: 编辑:基于聊天中的长时间讨论,很明显有人 对意图有误解,而最初的

  • 问题内容: 使用Graphics2D,我如何拍摄黑白图像,并用来定义 在另一幅图像上应该渲染和不应该渲染的图像? 例如,如果我有一个图像,例如一个字段,并且在该字段上是一头 母牛,那么在用Java渲染时 , 在相同尺寸的另一幅图像上,我会在黑色背景上以与母牛相同的坐标绘制一个白框图像会是 全黑的,除了我有白盒子的那头牛? 问题答案: 编辑:基于聊天中的长时间讨论,很明显有人 对意图有误解,而最初的

  • 使用Graphics2D,我如何拍摄黑白图像,并使用它定义应该在另一个图像上渲染什么和不应该在另一个图像上渲染什么? E、 g如果我有一个图像,比如说,一个字段,在该字段上是一头奶牛,在另一个相同尺寸的图像上,我在黑色背景上,在奶牛的相同坐标处绘制一个白色框,当用Java渲染时,除了我有白色框的奶牛之外,图像将全部为黑色?

  • 整数除法的硬件指令在历史上一直非常慢。例如,对于64位输入,Skylake上的DIVQ具有42-95个周期[1]的延迟(以及24-90的倒数吞吐量)。 然而,有一些新处理器性能更好:Goldmont有14-43延迟,Ryzen有14-47延迟[1],M1显然有“每分频2个时钟周期的吞吐量”[2],甚至Raspberry Pico也有“每核8周期有符号/无符号分频/模电路”(虽然这似乎适用于32位输

  • 问题内容: 我正在开发Midlet应用程序。我发现自己经常需要缩放图像。这已经成为一个问题,因为某些电话速度很慢,缩放时间太长。 目前,我正在使用Image.createRGBImage(int,int,int,boolean)缩放图像。 我想知道你们中是否有人知道一种非常有效和快速的缩放图像的方法。 注意: 这是一个Midlet应用程序,因此仅JavaME可用,这意味着我无权访问完整Java版本