之间的区别。图形 fillRect 和 clearRect

Posted

技术标签:

【中文标题】之间的区别。图形 fillRect 和 clearRect【英文标题】:Difference btw. Graphics fillRect and clearRect 【发布时间】:2021-09-25 01:58:09 【问题描述】:

当我想用半透明背景色初始化一个 BufferedImage 时,我注意到了 fillRect 和 clearRect 之间的一些有趣的区别:

使用填充矩形:

Color someHalfTransparentColor = new Color(Integer.parseInt("77affe07", 16), true);
BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = bi.createGraphics();
g.setColor(someHalfTransparentColor);
g.fillRect(0, 0, 10, 10);
g.dispose();
        
System.out.println(Integer.toString(bi.getRGB(0, 0), 16));
// WORKS NOT AS EXPECTED: 77b0ff06 != 77affe07

使用 clearRect:

Color someHalfTransparentColor = new Color(Integer.parseInt("77affe07", 16), true);
BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g = bi.createGraphics();
g.setBackground(someHalfTransparentColor);
g.clearRect(0, 0, 10, 10);
g.dispose();
        
System.out.println(Integer.toString(bi.getRGB(0, 0), 16));
// WORKS AS EXPECTED: 77affe07 == 77affe07

使用 fillRect 时,颜色值似乎略有变化。有人可以解释这种行为吗?

【问题讨论】:

【参考方案1】:

不同之处在于fillRect 使用Graphics2D 的当前复合(getComposite),而clearRect 忽略它。默认情况下,复合为AlphaComposite.SrcOver。当绘制一个新的矩形时,这个组合将通过结合目的地的颜色和将要绘制的颜色与一些数学来决定最终的颜色。

另一方面,(至少在我的 JDK 版本上)clearRect 将复合临时设置为 AlphaComposite.Src(因此忽略当前复合),这完全忽略了目标,并简单地复制了您想要的颜色画到你想要的地方。

您可以看到,如果您在fillRect 之前执行g.setComposite(AlphaComposite.Src);,您将获得与clearRect 相同的输出。

文档中提到这一点的部分是:

clearRect:

此操作不使用当前的绘制模式。

setComposite:

为 Graphics2D 上下文设置 Composite。 Composite 用于所有绘图方法,例如drawImagedrawStringdrawfill。它指定在渲染过程中如何将新像素与图形设备上的现有像素组合。

可以这么说:

clearRect 不是“绘图方法”。它会擦除内容,因此setComposite 不适用于它。 合成是“绘画模式”的一部分(文档由于某种原因没有定义这个术语),因此clearRect 不使用它。

【讨论】:

感谢您的回答!因此,当 fillRect 在现有像素颜色上绘制并计算结果颜色时,基本上是一个舍入误差。 @jsteltze 我不确定它是否可以被视为“错误”。我还没有了解数学是如何工作的,但这可能是使用SRC_OVER 规则的预期结果,其中目标像素是完全透明的像素,源像素是你的someHalfTransparentColor

以上是关于之间的区别。图形 fillRect 和 clearRect的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList.clear=nullnew Arraylist之间的对比区别

第七周作业

Clear-Variable 和将变量设置为 NULL 之间的区别

Session.Abandon与Session.Clear之间的区别

在 C++ 中使用 FillRect()

影片剪辑和图形符号之间的性能有区别吗?