我有一个屏幕外的BufferedImage,用类型BufferedImage.TYPE_INT_ARGB
构造。它可以包含任何内容,我正在寻找一种(相当有效地)用透明像素完全覆盖图像的方法,从而产生"不可见"的图像。
像这样使用:
(bufimg.getGraphics()).setColor(new Color(10, 10, 100, 0));
(bufimg.getGraphics()).fillRect (0, 0, x, y);
无效。一种可能的方法可能只是重写BufferedImage中的每个像素,但我不确定这是最好的解决方案。你会怎么做?
[编辑]
图形文档建议不要对屏幕外图像使用clearRect,但我已经尝试过了,结果与上面相同。
[edit2]
在试用了MeBigFatGuy的代码后(谢谢!),它确实可以清除图像。但它也停止了进一步的描绘(或似乎)。下面的代码例如:
BufferedImage img = new BufferedImage (600, 600, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.createGraphics ()
g.drawLine (100, 100, 500, 500);
AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
g.setComposite(composite);
g.setColor(new Color(0, 0, 0, 0));
g.fillRect(0, 0, 600, 600);
graphicsAI.setColor(new Color (10, 10, 10, 255));
graphicsAI.drawLine (100, 100, 500, 500);
结果在图像上看不到任何东西(我正在将图像绘制到JPanel)。这与alpha值的添加有关吗?
使用clear composite清除背景后,需要将其设置为SRC_OVER才能再次正常绘制。例:
//clear
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2.fillRect(0,0,256,256);
//reset composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//draw
g2.setPaint(Color.RED);
g2.fillOval(50,50,100,100);
您可以获得BufferedImage
的底层int[]
数组(确保使用兼容的格式:即由int[]
支持的格式)。
然后用alpha值为0的int填充int[]
(0也可以;)
System.arraycopy
将非常快。
你必须知道直接在int[]
中写入比使用setRGB快得多。
现在BufferedImage
在Java中有点黑魔法:取决于你在做什么以及你在哪个平台/JVM上做它,你可能会失去硬件加速(可能从一开始就没有)。除此之外,你可能根本不关心硬件加速,因为你可能并不是在制作一款需要60+ FPS才能玩的游戏。
这是一个非常复杂的话题,有不止一种方法来给BufferedImage
猫剥皮。就我而言,我直接在int[]
中工作,当我在像素级别上搞砸了,因为我认为这比尝试使用更高级别的绘图原语更有意义,我做真的不关心硬件加速的潜在损失。
如果将Graphics对象强制转换为Graphics2D对象,则可以通过
设置Composite对象AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setComposite(composite);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.fillRect(0, 0, 10, 10);
为了完整起见,这里是一个工作、测试和快速的跨平台兼容函数。
static public BufferedImage createTransparentBufferedImage(int width, int height) {
// BufferedImage is actually already transparent on my system, but that isn't
// guaranteed across platforms.
BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufferedImage.createGraphics();
// To be sure, we use clearRect, which will (unlike fillRect) totally replace
// the current pixels with the desired color, even if it's fully transparent.
graphics.setBackground(new Color(0, true));
graphics.clearRect(0, 0, width, height);
graphics.dispose();
return bufferedImage;
}
尽管你说它不工作,我使用clearRect
相当好。
用背景色填充指定矩形,从而清除指定矩形当前绘图表面的。该操作不使用当前绘制模式
从Java 1.1开始,屏幕外图像的背景颜色可能系统依赖。应用程序应该使用setColor和fillRect以确保将屏幕外图像清除到指定的颜色。
填充指定的矩形。的左右边缘矩形是x和x + width - 1。顶部和底部边缘是相等的Y和Y +高- 1。得到的矩形覆盖一个区域宽度像素宽乘以高度像素高。填充矩形图形上下文的当前颜色。
这里没有明确说明,一个将将矩形设置为背景色,而另一个将将与前景色一起绘制在当前颜色的顶部,但它似乎是这样做的。
这是纯粹的猜测,但我认为关于屏幕外图像的说明与从屏幕外AWT组件获得的Graphics
对象有关,因为它们是原生的。我很难想象BufferedImage
的背景颜色是如何依赖于系统的。由于API文档是针对Graphics
的,所以这可能不适用于BufferedImage
的情况。
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage img = new BufferedImage(200, 300, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = img.createGraphics();
//fill right half with opaque white
g.setColor(Color.WHITE);
g.fillRect(100, 0, 100, 300);
//leave top third as it is
//fill middle third with transparent color
g.setColor(new Color(0, true));
g.fillRect(0, 100, 200, 100);
//clear bottom third with transparent color
g.setBackground(new Color(0, true));
g.clearRect(0, 200, 200, 100);
g.dispose();
jf.add(new JLabel(new ImageIcon(img)));
jf.pack();
jf.setVisible(true);
的结果是右上方的两个白色方块。如果没有涂上白色,或者使用clearRect
覆盖白色,则结果是浅灰色,这是框架的默认背景色。
性能方面,它是常规绘图。arraycopy
可能更快,我不知道,但至少这可能是硬件加速,就像任何其他绘图操作。
相对于数组解决方案的一个优点是A)没有额外的内存和b)独立于颜色模型;无论图像是如何设置的,这都应该有效。
与复合解决方案相比,一个缺点是它只允许清除矩形;
设置图形对象的背景似乎完成了工作:
g.setBackground(new Color(0, 0, 0, 0));
(至少在绘制图像用于缩放时)