[英]Java: Filling a BufferedImage with transparent pixels
我有一个屏幕外的 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 值有关吗?
用 CLEAR 合成清除背景后,您需要将其设置回 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[]
(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);
尽管你说它不起作用,但我很好地使用了clearRect
。
通过用当前绘图表面的背景色填充指定的矩形来清除它。 此操作不使用当前的绘制模式。
从 Java 1.1 开始,屏幕外图像的背景颜色可能取决于系统。 应用程序应使用 setColor 后跟 fillRect 以确保将屏幕外图像清除为特定颜色。
填充指定的矩形。 矩形的左右边缘位于 x 和 x + 宽度 - 1。顶部和底部边缘位于 y 和 y + 高度 - 1。生成的矩形覆盖区域宽度像素宽 x 高度像素高。 矩形使用图形上下文的当前颜色填充。
它没有明确指出这里是一个将设置矩形的背景色,而其他将与当前颜色的顶部前景色画,但它是什么,似乎做的。
这纯粹是猜测,但我认为关于屏幕外图像的说明与从屏幕外 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) 独立于颜色模型; 无论图像如何设置,这都应该有效。
与 Composite 解决方案相比的一个缺点是它只允许清除矩形; 设置复合允许您清除任何类型的形状。
设置图形对象的背景似乎可以完成这项工作:
g.setBackground(new Color(0, 0, 0, 0));
(至少在为缩放目的绘制图像时)
尽管他想将前景像素设置为透明,但您的答案肯定是正确的答案。
private Color transparent = new Color(0, true);
((Graphics2D) g).setBackground(transparent);
g.clearRect(0, 0, w, h);
将背景设置为透明。
顺便说一句:其他答案大多是垃圾,或者只是FUD。 请不要在技术论坛中接受有关“缓冲图像是妖术”的答案。
为了完整起见,这里有一个跨平台兼容的工作、测试和快速功能。
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.