Во время работы со старым ПК 1 я нашел то, что, по моему мнению, было странной ошибкой рендеринга.
Проблема возникает, когда глубина цвета установлена на 16 бит (32768 цветов).
Особенно это проявляется при окрашивании цветов с низким значением альфа с помощью Graphics2D
. Следующее - это MVCE, чтобы воспроизвести проблему. Он просто рисует несколько наборов строк с белым цветом, значение альфа которого колеблется от 4 до 12. Результат запуска этой программы показан на следующем снимке экрана:
Можно видеть, что некоторые цвета на самом деле зеленые для некоторых альфа-значений, хотя, очевидно, должно быть 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
Причина такого поведения заключается в том, что цветовые компоненты (красный, зеленый и синий) представлены с различным количеством бит в 16-битном цветовом режиме.
16 бит распределены между компонентами цвета следующим образом:
Это означает, что 16-битный цвет имеет 2 5= 32 разных оттенка красного и синего, но 2 6= 64 оттенка зеленого.
(Зеленый получает дополнительный бит, потому что чувствительность человеческого глаза больше для оттенков зеленого цвета, чем для оттенков красного или синего)
Теперь, когда стандартный 24-битный цвет RGB преобразуется в 16-битный цвет, будут возникать ошибки выборки. В 24-битном цвете каждый компонент цвета имеет 8 бит. Они преобразуются в соответствующий компонент для 16-битного цвета, беря биты наивысшего порядка цветового компонента.
В скриншоте примера можно увидеть линии, которые окрашены альфа-значением 7. Представление RGB этого цвета - (7,7,7). Бинарное представление этого цвета (00000111 b, 00000111 b, 00000111 b). При использовании битов наивысшего порядка для каждого компонента цвета результаты
Таким образом, зеленый компонент является единственным компонентом с ненулевым значением. Зеленый компонент фактического цвета, который затем отображается на экране, можно представить как 6-битный зеленый компонент, сдвинутый слева на 2 бита:
Это подтверждается рассмотрением соответствующих пикселей на 0x000C00
экрана, которые сохраняются как 0x000C00
, или 24-битные значения RGB (0,12,0): темный оттенок зеленого.