Java 旋转BuffereImage时,如何生成清晰的绘制结果?

Java 旋转BuffereImage时,如何生成清晰的绘制结果?,java,transform,transformation,interpolation,bufferedimage,Java,Transform,Transformation,Interpolation,Bufferedimage,一种尝试的方法是使用TexturePaint和g.fillRect()绘制图像。但是,这需要您在每次绘制图像时创建一个新的TexturePaint和Rectangle2D对象,这并不理想,而且也没有任何帮助 当我使用g.drawImage(BuffereImage,…)时,旋转后的图像看起来模糊/柔和 我熟悉渲染提示和双缓冲(我想这就是我正在做的),我只是觉得很难相信在Java中你不能轻松有效地旋转图像,从而产生清晰的结果 使用TexturePaint的代码如下所示 Grahics2D g2d

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

当我使用
g.drawImage(BuffereImage,…)
时,旋转后的图像看起来模糊/柔和

我熟悉渲染提示和双缓冲(我想这就是我正在做的),我只是觉得很难相信在Java中你不能轻松有效地旋转图像,从而产生清晰的结果

使用TexturePaint的代码如下所示

Grahics2D g2d = (Graphics2D)g; 
g2d.setPaint(new TexturePaint(bufferedImage, new Rectangle2D.Float(0,0,50,50)));
g2d.fillRect(0,0,50,50);
我正在使用仿射变换将一手牌旋转成扇形。 快速绘制好看图像的最佳方法是什么

下面是一个屏幕截图:

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);
}
我应该如何以不同的方式处理这个问题? 谢谢

编辑:

没有渲染提示

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

以下是我目前如何绘制它们(比TexturePaint快得多):

我所有的卡都是80x120,shadow.png是86x126,这样可以在卡周围留下3倍的半透明阴影。我知道这不是一个真实的阴影,但看起来不错

所以问题变成了。。。旋转BuffereImage时,如何生成清晰的绘制结果

参考前面关于扇形卡盘手的问题:

赏金编辑: 好的,在进行了大量讨论之后,我制作了一些test.svg卡,以了解svg Salamander将如何渲染它们。不幸的是,表演很糟糕。我的实现足够干净,就像双缓冲的BuffereImage一样,绘制速度非常快。这意味着我已经回到了原来的问题上来了

我会把50美元悬赏给任何能给我一个解决办法的人,让他可以快速旋转。有人建议在绘制前将图像放大,缩小比例,并使用双三次插值。如果这些是唯一可能的解决方案,那么我真的不知道从这里走到哪里,我可能不得不处理模糊的旋转-因为这两个都会带来性能上的挫折

如果我能找到一个好方法,我就能完成我的比赛。
谢谢大家。:)

在中设置插值类型以及抗锯齿值可以提供一些改进。类型
双三次类型
,虽然速度较慢,但通常是最好的质量;文中列举了一个例子。请注意,您可以提供多个。另一个陷阱是每次渲染图像时未能应用提示。您可能还需要根据建议调整背景的透明度。最后,考虑创建一个包含你的实际图像的一个。

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

如果大量旋转和动画是UI的一部分,那么光栅化图像可能是错误的技术;特别是对于具有大量曲线的复杂图像。等你试着放大你的画布。我可能建议看一个基于向量的图形库。它们将以较少的伪影可能性呈现您想要的各种效果


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

然后,在绘制图像时,动态调整大小:

g.drawImage(bufferedImage, x, y, desiredWidth, desiredHeight, observer);
建议使用双线性插值进行旋转


guido的建议值得称赞。

我看不出您在哪里设置了
渲染提示
@Moonbeam:RenderingHints对图像没有帮助,而只对我们绘制的形状有帮助。如果您查看API,它会说:“反走样提示控制Graphics2D对象的几何体渲染方法是否会尝试减少形状边缘的走样瑕疵。”因此,他甚至不尝试在这里使用它们是正确的。@Rudi:如果您在内存中保留较大的图像,在可视化之前旋转后会缩小尺寸?@偏执安卓以任意角度旋转图像意味着破坏数据;图像越大,丢失的数据就越少,因此,如果您负担不起切换到矢量,它可能是唯一的选择graphics@paranoid-android因为我只给出了一个提示,没有实现,所以最好用一些示例代码回答自己并接受它。注意,我没有建议放大(这是有损的),只是为了在可视化之前保持更大的图像并缩小,谢谢你指出这一点。下次我会考虑这个办法。事实上,我的游戏是可伸缩的,所有的宽度、高度和位置都与面板大小有关。我已经检查过了,这些卡片的尺寸是正确的。在上面的示例中,我只是硬编码了大小,以适应默认面板大小1280x720。@paranoid:我想我在某处看到过公共域SVG图像扑克牌,因此已经有合适的图像可供您使用。让我看看能不能再找到他们。编辑:这里有一些:@气垫船上满是鳗鱼:由于缺乏支持/可靠的答案,我要走了
g.drawImage(bufferedImage, x, y, desiredWidth, desiredHeight, observer);