旋转BufferedImage时如何产生清晰的绘画效果?

一种尝试的方法是使用TexturePaintg.fillRect()来绘制图像。 然而,这需要您在每次绘制图像时创建一个新的TexturePaint和Rectangle2D对象,这是不理想的 – 并且无论如何都没有帮助。

当我使用g.drawImage(BufferedImage,...) ,旋转的图像看起来模糊/柔和。

我熟悉RenderingHints和双缓冲(我认为这就是我正在做的事情),我发现很难相信你不能轻易有效地在Java中旋转产生尖锐结果的图像。

使用TexturePaint代码看起来像这样。

 Grahics2D g2d = (Graphics2D)g; g2d.setPaint(new TexturePaint(bufferedImage, new Rectangle2D.Float(0,0,50,50))); g2d.fillRect(0,0,50,50); 

我正在使用AffineTransform将一手牌旋转成一个风扇。 什么是快速绘制好看图像的最佳方法?

这是一个截图:
模糊旋转的示例
9是清脆的,但其余的卡肯定不那么尖锐。

问题可能出在我创建每张卡片图像并将其存储在数组中时。
这就是我现在正在做的事情:

 // i from 0 to 52, card codes. ... GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gs.getDefaultConfiguration(); BufferedImage img = gc.createCompatibleImage(86, 126, Transparency.TRANSLUCENT); Graphics2D g = img.createGraphics(); setRenderingHints(g); g.drawImage(shadow, 0, 0, 86, 126, null); g.drawImage(white, 3, 3, 80, 120, null); g.drawImage(suit, 3, 3, 80, 120, null); g.drawImage(value, 3, 3, 80, 120, null); g.dispose(); cardImages[i] = img; } private void setRenderingHints(Graphics2D g){ g.setRenderingHint(KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.setRenderingHint(KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); } 

我应该如何区别对待? 谢谢。

编辑:
没有RenderingHints的手的示例
没有RenderingHints

设置AA提示没有区别。 此外,在创建图像时设置RenderingHints也没有区别。 只有在使用AffineTransform进行旋转并使用g.drawImage(...)绘制时,它们才会模糊。
上图显示了默认(最近邻居)和双线性插值之间的差异。

这是我当前正在绘制它们的方式(比TexturePaint快得多):

 // GamePanel.java private void paintCard(Graphics2D g, int code, int x, int y){ g.drawImage(imageLoader.getCard(code), x, y, 86, 126, null); } // ImageLoader.java public BufferedImage getCard(int code){ return cardImages[code]; } 

我的所有卡片都是80×120,而影子.png是86×126,这样可以在卡片周围留下3px的半透明阴影。 这不是我所知道的真实影子,但它看起来还不错。

所以问题变成了…… 当旋转BufferedImage时,如何产生清晰的绘画结果?

关于扇形卡片手的参考前一个问题:
如何在Java中检测Image对象上的鼠标单击事件?

Bounty-Edit:好的,经过多次讨论,我做了一些测试.svg卡片,看看SVG Salamander将如何渲染它们。 不幸的是,表现很糟糕。 我的实现足够干净,看到双缓冲的BufferedImage,这幅画非常快。 这意味着我已经完整了,我又回到了原来的问题。

我会给那些可以给我一个解决方案以获得明显的BufferedImage旋转的50分。 建议在绘画之前使图像比它们需要的更大并缩小尺寸,并使用双三次插值。 如果这些是唯一可行的解​​决方案,那么我真的不知道从哪里开始,我可能只需要处理模糊的旋转 – 因为这两者都会造成性能挫折。

如果我能找到一种方法来做到这一点,我可以完成我的游戏。 谢谢大家。 🙂

旋转光栅化图像(例如BufferedImage)时,会丢失数据。 最好的解决方案是保存比您需要的图像更大的图像,并在绘制时动态缩小图像。 我发现你需要1.5倍的尺寸是一个很好的起点。

然后,当您绘制图像时,请立即resize:

 g.drawImage(bufferedImage, x, y, desiredWidth, desiredHeight, observer); 

建议使用双线性插值进行旋转。

建议归功于圭多。

这个建议可能在您的设计中有点晚,但值得一提。

如果大量旋转和动画是UI的一部分,则栅格化图像可能是错误的技术; 特别是有大量曲线的复杂图像。 等到你尝试扩展你的游说。 我可能会建议查看基于矢量的图形库。 它们将呈现您想要的各种效果,而不会产生伪影。

http://xmlgraphics.apache.org/batik/using/swing.htm

AffineTransformOp设置插值类型以及消除锯齿值可能会提供一些改进。 TYPE_BICUBIC类型虽然较慢,但通常质量最好; 这里概述了一个例子。 请注意,您可以提供多个RenderingHints 。 每次渲染图像时都无法应用提示,从而产生了另一个陷阱。 您可能还需要调整背景的透明度,如此处所示 。 最后,考虑创建一个包含一个实际图像的sscce 。