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用于屏幕外图像,但我已尝试使用与上面相同的结果。
[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值有关?
你可以获得BufferedImage
的底层int[]
数组(确保使用兼容的格式:即由int[]
支持的格式)。
然后使用其alpha值为0的int[]
填充int[]
(0将执行;)
System.arraycopy
非常快。
你必须知道直接写入int[]
比使用setRGB快得多。
现在BufferedImage
在Java中是一种黑色艺术:取决于你正在做什么以及你正在做什么平台/ JVM,你可能会失去硬件加速(无论如何这可能永远不会出现在那里)。 除此之外,你可能完全不关心硬件加速,因为你可能没有工作,比如说需要60+ FPS才能玩的游戏等等。
这是一个非常复杂的主题,并且不止一种方法可以为BufferedImage
cat设置外观。 就我而言,当我不得不在像素级别处理时,我直接在int[]
工作,因为我觉得它比尝试使用更高级别的绘图原语更有意义而且我确实不这样做关心硬件加速的潜在损失。
使用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);
如果将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处。生成的矩形覆盖宽度为像素宽的区域宽度像素高。 使用图形上下文的当前颜色填充矩形。
这里没有明确说明将矩形设置为背景颜色,而另一个将使用前景颜色绘制在当前颜色之上,但这似乎是它的样子。
这是纯粹的猜测,但我认为关于屏幕外图像的注释与从屏幕外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
可能会更快,但至少这可能是硬件加速,就像任何其他绘图操作一样。
加点与arrays解决方案是a)没有额外的记忆和b)独立于颜色模型; 无论图像如何设置,这都应该有效。
与Composite解决方案相比,减号是它只允许清除矩形; 设置复合材料可以清除任何形状。
设置图形对象的背景似乎可以完成这项工作:
g.setBackground(new Color(0, 0, 0, 0));
(至少在绘制图像以进行缩放时)
尽管他想将前景像素设置为透明,但您的答案肯定是正确的答案。
private Color transparent = new Color(0,true);
((Graphics2D的)克).setBackground(透明);
g.clearRect(0,0,w,h);
将背景设置为透明。
BTW:其他答案主要是垃圾或简单的FUD。 请不要接受在技术论坛中谈论“缓冲图像是黑色艺术”的答案。