在Graphics2D中以16位色深绘画时颜色错误

时间:2014-08-24 15:31:19

标签: java colors alpha graphics2d

在使用旧PC 1 时,我发现了一些我认为是奇怪的渲染错误的东西。

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

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

OddColors

可以看到一些颜色实际上是绿色的某些alpha值,但显然应该 50 9灰度。

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

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);
    }
}

(我在这里用它的原名发布,以强调我发现这有多刺激......)

在这种情况下,奇数色彩渲染的原因是什么?


1 :WinXP,32位,NVIDIA GeForce 2显卡

1 个答案:

答案 0 :(得分:3)

此行为的原因是颜色组件(红色,绿色和蓝色)在16-bit color mode中用不同的位数表示。

16位分布在颜色分量中,如下所示:

  • 红色以 5
  • 表示
  • 绿色以 6
  • 表示
  • 蓝色以 5
  • 表示

这意味着16位颜色具有2 5 = 32种不同的红色和蓝色,但是2 6 = 64种绿色阴影。

(绿色接收额外的位,因为对于绿色阴影,人眼的灵敏度比红色或蓝色阴影更大)

现在,当标准24 bit RGB color转换为16位颜色时,将发生采样错误。在24位颜色中,每个颜色分量具有8位。通过获取颜色分量的最高位,将它们转换为16位颜色的相应分量。

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

  • 红色的5位: 00000 111 b - &gt; 00000 <子> B'/子>
  • 6位为绿色: 000001 11 b - &gt; 00000的 1 <子> B'/子>
  • 蓝色的5位: 00000 111 b - &gt; 00000 <子> B'/子>

绿色组件因此是唯一具有非零值的组件。然后,屏幕上显示的实际颜色的绿色分量可以想象为6位绿色分量,左移2位:

  • 000001 b &lt;&lt; 2 = 00000100 b

通过检查屏幕截图中的相应像素来确认这一点,这些像素存储为0x000C00或24位RGB值(0,12,0):深绿色阴影。