Аномальное поведение (или возможная ошибка) в JColorChooser - PullRequest
7 голосов
/ 09 апреля 2019

При использовании JColorChooser введенные значения CMYK переводятся в определенный цвет RGB. Когда этот цвет вводится вручную на стороне RGB, значения CMYK не такие, как раньше.

Следующая программа может использоваться для демонстрации поведения, с которым я сталкиваюсь.

import java.awt.*;
import javax.swing.*;

public class ColorChooserProblem {
    JFrame f = new JFrame("Testing Color Chooser");

    public static void main(String[] args) {
        new ColorChooserProblem().start();
    }

    public void start() {
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JColorChooser jc1 = new JColorChooser();
        JColorChooser jc2 = new JColorChooser();
        f.add(jc1, BorderLayout.NORTH);
        f.add(jc2, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}
  1. На обеих панелях выберите CMYK и введите любые допустимые числа для CMYK. Обе панели должны иметь одинаковые значения.
  2. Теперь сравните значения RGB для каждой панели. Они должны быть одинаковыми.
  3. Выберите одну панель и установите ползунки на 0.
  4. Теперь заново введите значения RGB на той же панели.
  5. Переключиться на CMYK для обеих панелей. Значения на панелях, которые я вижу, отличаются.

Обратите внимание, что при выборе другого пути (т. Е. Сначала выбирая RGB и повторно вводя значения CMYK), все работает так, как можно было ожидать. Я что-то упускаю в что ожидается от процесса конвертации или это ошибка?

Я использую Java 10 в Windows 10, и моя IDE - Eclipse.

Также опубликовано в http://www.javaprogrammingforums.com/java-theory-questions/41836-possible-bug-jcolorchooser.html

Ответы [ 3 ]

4 голосов
/ 17 апреля 2019

Преобразование из одной (дискретной) цветовой модели в другую (дискретную) цветовой модели никогда не может быть идеальным.

Причина, по которой CMYK-RGB-CMYK никогда не будет идеально работать в JColorChooser, заключается в том, что JColorChooser отображает целых вместо плавающих чисел.Например, выберите желтый = 255 в модели CMYK и вернитесь к RGB.Вы увидите, что этот желтый цвет смешан с красным = 255 и зеленым = 255.Теперь вернитесь к CMYK, понизьте желтый до 254 и проверьте значения RGB - он все еще красный = 255 и зеленый = 255!

Теперь измените желтый на 253 в CMYK и вернитесь к RGB.Красный и зеленый по-прежнему равны 255, а синий добавляется со значением 1. Правильное значение для CMYK: желтый = 254 (предыдущий случай) может быть синим = 0,4, но для упрощения использования в JColorChooser отображаются только целые числа, поэтому синий цвет отображается как0.

Эта числовая проблема усугубляется тем фактом, что «цветовая чувствительность» этих целочисленных цветовых моделей отличается.Хотя CMYK имеет 4 измерения (голубой, пурпурный, желтый, ключевой) и поэтому может представлять 256 ^ 4 = 4294967296 разных цветов, RGB имеет 3 измерения и может представлять только 256 ^ 3 = 16777216 цветов.Таким образом, вы всегда потеряете достаточно информации при преобразовании CMYK в этот тип RGB.

Другими словами, в среднем 256 точек в цветовом пространстве CMYK представлены только 1 точкой в ​​цветовом пространстве RGB.При обратном преобразовании одного цвета из RGB в CMYK в среднем 255 цветов в пространстве CMYK никогда не будут «достигнуты».

4 голосов
/ 19 апреля 2019

Я выполнил некоторую отладку внутри цветовых моделей, используемых JColorChooser, в частности ColorModelCMYK (пакетный класс).

Расчет в основном прост, за исключением того, что все значения 0..255 конвертируются в число с плавающей запятой 0.0..1.0 путем масштабирования на 255.0f. Это приводит к ошибкам округления в младшем значащем бите (из представления с плавающей запятой IEEE754).

Здесь C = 254 преобразуется в ~ R = 1 (обратите внимание, что оба массива являются одним и тем же объектом, и он обновляется на месте, поэтому значения CMYK теряются при преобразовании. rgb[0]*255f = 0.99999994

При правильном округлении до половины при преобразовании обратно в целочисленные значения для отображения это не должно быть проблемой. Однако, копаясь в самом ColorModel, я обнаружил, что эта функция используется подпрограммой, которая преобразует массив с плавающей запятой в упакованное 32-битное значение RGB:

private static int to8bit(float value) {
    return (int) (255.0f * value);
}

Это усечено! Я не знаю, является ли это ошибкой, но это, безусловно, проблема с удобством использования.

1 голос
/ 17 апреля 2019

Я использую Java 8 с Windows на Eclipse, и это дает мне тот же результат, но это не проблема. Он работает нормально для вас, но преобразование RGB в CMYK не работает так же, как CMYK в RGB. Вы можете видеть это в этом конвертере онлайн:

https://www.rapidtables.com/convert/color/rgb-to-cmyk.html

CMYK работает с голубым, пурпурным и желтым процентами. С другой стороны RGB со значениями от 0 до 255 красного, зеленого и синего. В сети, которую я пропустил, вы помещаете формулы этого преобразования и не работаете так же, как двунаправленный.

...