Java 以16位颜色深度在图形2D中绘制时颜色错误

Java 以16位颜色深度在图形2D中绘制时颜色错误,java,colors,alpha,graphics2d,Java,Colors,Alpha,Graphics2d,在使用旧的PC1时,我发现了一些我认为是奇怪的渲染错误 当颜色深度设置为16位(32768种颜色)时,会出现问题 特别是,当使用Graphics2D绘制低alpha值的颜色时,它会显示出来。以下是重现该问题的示例。它只绘制了几组线,带有一种白色颜色,其alpha值范围为4到12。运行此程序的结果显示在以下屏幕截图中: 我们可以看到,对于某些alpha值,有些颜色实际上是绿色的,尽管显然应该有50 9个灰度 (同样,它仅在颜色深度设置为16位时显示!) 导入java.awt.Color; 导入j

在使用旧的PC1时,我发现了一些我认为是奇怪的渲染错误

颜色深度设置为16位(32768种颜色)时,会出现问题

特别是,当使用
Graphics2D
绘制低alpha值的颜色时,它会显示出来。以下是重现该问题的示例。它只绘制了几组线,带有一种白色颜色,其alpha值范围为4到12。运行此程序的结果显示在以下屏幕截图中:

我们可以看到,对于某些alpha值,有些颜色实际上是绿色的,尽管显然应该有50 9个灰度

(同样,它仅在颜色深度设置为16位时显示!)

导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.SwingUtilities;
公共类油漆测试
{
公共静态void main(字符串[]args)
{
SwingUtilities.invokeLater(新的Runnable()
{
@凌驾
公开募捐
{
createAndShowGUI();
}
});
}
私有静态void createAndShowGUI()
{
JFrame f=新的JFrame();
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f、 getContentPane().add(新的JPanel())
{
@凌驾
受保护的组件(图形组)
{
超级油漆组件(gr);
Graphics2D g=(Graphics2D)gr;
g、 设置颜色(颜色为黑色);
g、 fillRect(0,0,getWidth(),getHeight());

对于(int a=4;a而言,此行为的原因是颜色组件(红色、绿色和蓝色)在中用不同数量的位表示

16位按如下方式分布在颜色分量中:

  • 红色用5位表示
  • 绿色用6位表示
  • 蓝色用5位表示
这意味着16位颜色有25=32种不同的红色和蓝色,但26=64种绿色

(绿色接收附加位,因为人眼对绿色的敏感度大于红色或蓝色)

现在,当标准转换为16位颜色时,将发生采样错误。在24位颜色中,每个颜色分量有8位。通过获取颜色分量的最高阶位,这些值将转换为16位颜色的对应分量

在示例屏幕截图中,可以看到绘制的线的alpha值为7。此颜色的RGB表示为(7,7,7)。此颜色的二进制表示为(00000 111b,00000 111b,00000 111b)。当为每个颜色分量获取最高阶位时,结果为

  • 红色的5位:00000111b->00000b
  • 绿色6位:00000111b->000001b
  • 5位蓝色:00000111b->00000b
因此,绿色分量是唯一具有非零值的分量。然后显示在屏幕上的实际颜色的绿色分量可以想象为6位绿色分量,左移2位:


  • 000001b此行为的原因是颜色组件(红色、绿色和蓝色)在中用不同的位数表示

    16位按如下方式分布在颜色分量中:

    • 红色用5位表示
    • 绿色用6位表示
    • 蓝色用5位表示
    这意味着16位颜色有25=32种不同的红色和蓝色,但26=64种绿色

    (绿色接收附加位,因为人眼对绿色的敏感度大于红色或蓝色)

    现在,当标准转换为16位颜色时,将发生采样错误。在24位颜色中,每个颜色分量有8位。通过获取颜色分量的最高阶位,这些值将转换为16位颜色的对应分量

    在示例屏幕截图中,可以看到绘制的线的alpha值为7。此颜色的RGB表示为(7,7,7)。此颜色的二进制表示为(00000 111b,00000 111b,00000 111b)。当为每个颜色分量获取最高阶位时,结果为

    • 红色的5位:00000111b->00000b
    • 绿色6位:00000111b->000001b
    • 5位蓝色:00000111b->00000b
    因此,绿色分量是唯一具有非零值的分量。然后显示在屏幕上的实际颜色的绿色分量可以想象为6位绿色分量,左移2位:


    • 这是一个很好的解释!坚持下去!(至于我自己,我知道这件事,但不能写这么好的答案,真的很好!)这是一个很好的解释!坚持下去!(至于我自己,我知道这件事,但不能写这么好的答案,真的很好!)
      import java.awt.Color;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.SwingUtilities;
      
      public class _WTFPaintTest
      {
          public static void main(String[] args)
          {
              SwingUtilities.invokeLater(new Runnable()
              {
                  @Override
                  public void run()
                  {
                      createAndShowGUI();
                  }
              });
          }
      
          private static void createAndShowGUI()
          {
              JFrame f = new JFrame();
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      
              f.getContentPane().add(new JPanel()
              {
                  @Override
                  protected void paintComponent(Graphics gr)
                  {
                      super.paintComponent(gr);
                      Graphics2D g = (Graphics2D)gr;
                      g.setColor(Color.BLACK);
                      g.fillRect(0,0,getWidth(),getHeight());
      
                      for (int a=4; a<=12; a++)
                      {
                          int x = (a-3) * 50;
                          g.setColor(Color.WHITE);
                          g.drawString(String.valueOf(a), x, 25);
      
                          g.setColor(new Color(255,255,255,a));
                          for (int j=0; j<3; j++)
                          {
                              for (int i=0; i<50; i++)
                              {
                                  g.drawLine(x,50+i,x+25,75);
                              }
                          }
                      }
                  }
              });
      
              f.setSize(550,200);
              f.setLocationRelativeTo(null);
              f.setVisible(true);
          }
      }