旋转BufferedImage时如何产生清晰的绘画效果? [英] How can you produce sharp paint results when rotating a BufferedImage?

查看:1025
本文介绍了旋转BufferedImage时如何产生清晰的绘画效果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

One attempted approach was to use TexturePaint and g.fillRect() to paint the image. This however requires you to create a new TexturePaint and Rectangle2D object each time you paint an image, which isn't ideal - and doesn't help anyway.

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

When I use g.drawImage(BufferedImage,...), the rotated images appear to be blurred/soft.

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

I'm familiar with RenderingHints and double-buffering (which is what I'm doing, I think), I just find it difficult to believe that you can't easily and efficiently rotate an image in Java that produces sharp results.

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

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

我正在使用 AffineTransform 来轮播把手变成粉丝。
快速绘制好看图像的最佳方法是什么?

I'm using AffineTransform to rotate a hand of cards into a fan. What would be the best approach to paint good-looking images quickly?

以下是截图:



9很清脆,但其余的牌肯定不那么锋利。

当我创建每张卡片图像并将其存储在一个数组中时,问题可能就出现了。

这就是我现在的表现:

It could be possible that the problem lies in when I create each card image and store it in an array.
Here's how I'm doing it at the moment:

// 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);
}

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

How should I approach this differently? Thanks.

编辑:



没有RenderingHints

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

Setting AA hints made no difference. Also, setting RenderingHints when creating the images makes no difference either. It's only when they are being rotated with AffineTransform and painted using g.drawImage(...) that they seem to blur.
The image above shows the difference between default (nearest neighbor) and bilinear interpolation.

以下是我当前绘制它们的方式(比TexturePaint快得多):

Here is how I'm currently painting them (much faster than 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];
  }

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

All my cards are 80x120 and the shadow .png is 86x126, so as to leave 3px semi-transparent shadow around the card. It's not a realistic shadow I know, but it looks okay.

所以问题变成了...... 旋转BufferedImage时如何产生清晰的绘画效果?

And so the question becomes... How can you produce sharp paint results when rotating a BufferedImage?

上一个关于扇形卡片手的问题的参考:

如何在Java中检测Image对象上的鼠标单击事件?

Reference to a previous question also regarding a fanned card hand:
How can you detect a mouse-click event on an Image object in Java?

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

Bounty- Okay so after much discussion I made a few test .svg cards to see how SVG Salamander would go about rendering them. Unfortunately, the performance is terrible. My implementation is clean enough, seeing as with double-buffered BufferedImage's the painting was incredibly fast. Which means I have come full circle and I'm back to my original problem.

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

I'll give the 50 bounty to whoever can give me a solution to get sharp BufferedImage rotations. Suggestions have been to make the images bigger than they need to be and downscale before painting, and to use bicubic interpolation. If these are the only possible solutions, then I really don't know where to go from here and I may just have to deal with the blurred rotations - because both of those impose performance setbacks.

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

I can finish my game if I can find a way to do this well. Thanks to everyone. :)

推荐答案

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

When you rotate a rasterized image (such as a BufferedImage), you lose data. The best solution is to save your images larger than you'll need them, and downscale on the fly when you paint them. I've found that 1.5x the size you need is a good starting point.

然后,当你在绘制图像时,立即调整大小:

Then, when you're painting the image, resize on the fly:

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

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

建议的信用额转到guido。

这篇关于旋转BufferedImage时如何产生清晰的绘画效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆