旋转BufferedImage时如何产生清晰的绘画效果?
一种尝试的方法是使用TexturePaint
和g.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
设置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的一部分,则栅格化图像可能是错误的技术; 特别是有大量曲线的复杂图像。 等到你尝试扩展你的游说。 我可能会建议查看基于矢量的图形库。 它们将呈现您想要的各种效果,而不会产生伪影。
在AffineTransformOp
设置插值类型以及消除锯齿值可能会提供一些改进。 TYPE_BICUBIC
类型虽然较慢,但通常质量最好; 这里概述了一个例子。 请注意,您可以提供多个RenderingHints
。 每次渲染图像时都无法应用提示,从而产生了另一个陷阱。 您可能还需要调整背景的透明度,如此处所示 。 最后,考虑创建一个包含一个实际图像的sscce 。