Java:用透明像素填充 BufferedImage
我有一个离屏 BufferedImage,其构造类型为 BufferedImage.TYPE_INT_ARGB 。它可以包含任何内容,我正在寻找一种方法(相当有效地)用透明像素完全覆盖图像,从而产生“不可见”图像。
使用这样的东西:
(bufimg.getGraphics()).setColor(new Color(10, 10, 100, 0));
(bufimg.getGraphics()).fillRect (0, 0, x, y);
没有效果。一种可能的方法可能只是覆盖 BufferedImage 中的每个像素,但我不确定这是最好的解决方案。你会怎么做?
[编辑]
图形文档建议不要对屏幕外图像使用clearRect,但我已经尝试过,结果与上面相同。
[编辑2]
在尝试了 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 值有关吗?
I have an off-screen BufferedImage, constructed with the type BufferedImage.TYPE_INT_ARGB
. It can contain anything, and I'm looking for a way to (fairly efficiently) completely overwrite the image with transparent pixels, resulting in an 'invisible' image.
Using something like this:
(bufimg.getGraphics()).setColor(new Color(10, 10, 100, 0));
(bufimg.getGraphics()).fillRect (0, 0, x, y);
Has no effect. One possible method might be just to write over every pixel in the BufferedImage, but I'm not sure this is the best solution. How would you do it?
[edit]
The Graphics documentation advises against using clearRect for off-screen images, but I have tried it with the same results as above.
[edit2]
After experimenting with MeBigFatGuy's code (thanks!), it does clear an image. But it also stops further painting to that image (or appears to). This code for example:
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);
Results in nothing seen on the image (I'm drawing the image to a JPanel). Is this something to do with the addition of alpha values?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使用 CLEAR 复合清除背景后,需要将其设置回 SRC_OVER 才能再次正常绘制。前任:
After you clear the background with the CLEAR composite, you need to set it back to SRC_OVER to draw normally again. ex:
您可以获取
BufferedImage
的底层int[]
数组(确保使用兼容的格式:即由int[] 支持的格式)。
然后用 alpha 值为 0 的整数填充
int[]
(0 即可;)System.arraycopy
将非常快。你要知道,直接写入
int[]
比使用setRGB快很多。现在,
BufferedImage
在 Java 中有点像魔法:根据您正在执行的操作以及执行该操作的平台/JVM,您可能会失去硬件加速功能(无论如何,可能从来就不存在)。除此之外,您可能根本不关心硬件加速,因为您可能不会开发需要 60+ FPS 才能玩的游戏等。这是一个非常复杂的问题主题,并且有不止一种方法可以为
BufferedImage
猫换肤。就我而言,当我必须在像素级别搞乱时,我直接在int[]
中工作,因为我认为这比尝试使用更高级别的绘图基元更有意义而且我确实真的不关心硬件加速的潜在损失。You could get the underlying
int[]
array of yourBufferedImage
(make sure to use a compatible format: that is, one that is backed by anint[]
).Then fill the
int[]
with ints whose alpha value are 0 (0 will do ; )A
System.arraycopy
will be very fast.You have to know that directly writing in the
int[]
is a lot faster than using setRGB.Now
BufferedImage
are a bit of a black art in Java: depending on what you're doing and on which platform/JVM you're doing it, you may lose hardware acceleration (which may never have been there in the first place anyway). In addition to that, you may very well not care at all about hardware acceleration anyway because you may not be working on, say, a game requiring 60+ FPS to be playable etc.This is a very complicated topic and there's more than one way to skin the
BufferedImage
cat. As far as I'm concerned I work directly in theint[]
when I've got to mess at the pixel level because I think it makes much more sense than trying to use higher-level drawing primitives and I do really don't care about the potential lost of hardware acceleration.如果将 Graphics 对象转换为 Graphics2D 对象,则可以通过设置 Composite 对象
If you cast the Graphics object to a Graphics2D object, you can set a Composite object thru
为了完整起见,这里是一个跨平台兼容的工作、测试和快速函数。
For the sake of completeness, here is a working, testing, and fast function that is cross-platform compliant.
尽管你说它不起作用,但我使用
clearRect
效果很好。这里没有明确说明,一个将矩形设置为背景颜色,而另一个将在当前颜色之上使用前景色进行绘制,但事实就是如此看来确实如此。
这纯粹是猜测,但我认为有关屏幕外图像的注释与从屏幕外 AWT 组件获取的 Graphics 对象相关,因为它们是本机的。我很难想象 BufferedImage 的背景颜色如何与系统相关。由于 API 文档适用于
Graphics
,因此这可能是不适用于BufferedImage
情况的概括。我的测试代码:
结果是右上角两个白色方块。如果没有绘制白色,或者使用
clearRect
覆盖白色,则结果是浅灰色,即框架的默认背景颜色。就性能而言,它是常规绘图。 arraycopy 可能会更快,我不知道,但至少这可能像任何其他绘图操作一样进行硬件加速。
与阵列解决方案相比,优点是 a) 无需额外内存,b) 独立于颜色模型;无论图像如何设置,这都应该有效。
与复合解决方案相比,缺点是它只允许清除矩形;设置复合允许您清除任何类型的形状。
Despite you saying it doesn't work, I used
clearRect
quite fine.It is not clearly stated here that one will set the rectangle to the background color, while the other will paint with the foreground color on top of the current colors, but it's what it seems to do.
This is pure speculation, but I think the note about offscreen images relates to
Graphics
objects obtained from offscreen AWT components, as they are native. I can hardly imagine how the background color of aBufferedImage
could be system dependent. As the API doc is forGraphics
, this could be a generalization not applying to theBufferedImage
case.My testing code:
the result is two white squares, top right. Where no white was painted, or
clearRect
was used to overwrite the white, the result is a light gray, the frame's default background color.Performance-wise, it's regular drawing.
arraycopy
might well be faster, I don't know, but at least this is likely hardware accelerated just as any other drawing operation.A plus point versus the array solution is a) no additional memory and b) independence from the color model; this should work no matter how the image was set up.
A minus point versus the Composite solution is that it only allows clearing rectangles; setting the composite allows you to clear any kind of shape.
设置图形对象的背景似乎可以完成这项工作:(
至少在出于缩放目的绘制图像时)
Setting the background of the graphics Object seems to do the job:
(at least when drawing images for scaling purposes)