JColorChooser 中的异常行为(或可能的错误)

Anomalous behavior (or possible bug) in JColorChooser

使用 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. 在两个面板中,select CMYK 并输入任何有效的 CMYK 数字。两个面板必须具有相同的值。
  2. 现在比较每个面板的 RGB 值。他们应该是一样的。
  3. Select 单个面板并将滑块重置为 0。
  4. 现在在同一个面板中重新输入 RGB 值。
  5. 将两个面板切换为 CMYK。我看到的面板中的值不同。

请注意,当采用另一种方式时(即先 selecting RGB 并重新输入 CMYK 值),一切都如预期的那样工作。我错过了什么吗 转换过程需要什么,或者这是一个错误?

我是 运行 Java 10 Windows 10 我的 IDE 是 Eclipse。

也发布在 http://www.javaprogrammingforums.com/java-theory-questions/41836-possible-bug-jcolorchooser.html

我也在 E​​clipse 上使用 Java 8 和 Windows,它给了我相同的结果,但这不是问题所在。它对您来说工作正常,但将 RGB 转换为 CMYK 的方式与将 CMYK 转换为 RGB 的方式不同。 你可以在这个在线转换器中看到它:

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

CMYK 适用于青色、品红色和黄色百分比。另一方面,RGB 具有从 0 到 255 的红色、绿色和蓝色值。 在我传递给您的网络中,您输入了该转换的公式,并且无法以相同的双向方式工作。

从一种(离散)颜色模型到另一种(离散)颜色模型的转换永远不可能完美。

CMYK 到 RGB 到 CMYK 在 JColorChooser 中永远无法完美工作的原因很简单,因为 JColorChooser 显示 整数 而不是浮点数。例如在 CMYK 模型中选择 yellow=255 并返回到 RGB。您会看到这种黄色是由 red=255 和 green=255 混合而成的。现在回到 CMYK,将黄色降低为 254 并检查 RGB 值 - 它仍然是 red=255 和 green=255!

现在将 CMYK 中的黄色更改为 253,然后返回到 RGB。红色和绿色仍然是 255,蓝色加上值 1。CMYK 黄色 = 254(之前的情况)的正确值可能是蓝色 = 0.4,但为了使使用更简单,JColorChooser 中只显示整数,因此蓝色显示为0.

由于这些整数颜色模型的 'color sensitivity' 不同,这个数字问题变得更加严重。虽然 CMYK 有 4 个维度(青色、品红色、黄色、基调),因此可以表示 256^4 = 4294967296 种不同的颜色,但 RGB 有 3 个维度,只能表示 256^3 = 16777216 种颜色。因此,在将 CMYK 转换为这种类型的 RGB 时,您总是会丢失很多信息。

换句话说,平均而言,CMYK 颜色 space 中的 256 个点仅由 RGB 颜色 space 中的 1 个点表示。当您将一种颜色从 RGB 转换回 CMYK 时,平均而言,CMYK space 中的 255 种颜色永远不会是 'reached'.

我在 JColorChooser 使用的颜色模型中进行了一些调试,特别是 ColorModelCMYK(包私有 class)。

除了所有值 0..255 通过按 255.0f 缩放转换为浮点数 0.0..1.0 之外,计算大部分都很简单。这在最低有效位(IEEE754 浮点表示)中引入了舍入误差。

这里 C=254 被转换为 ~R=1(请注意,两个数组是同一个对象,并且就地更新,因此 CMYK 值在转换中丢失。

在转换回用于显示的整数值时进行适当的半向上舍入,这应该不是任何问题。但是,深入研究 ColorModel 本身,我发现将浮点数组转换为打包的 32 位 RGB 值的例程使用了此函数:

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

它被截断了!我不知道这是否是一个错误,但这肯定是一个可用性问题。