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

时间:2019-04-09 20:50:58

标签: java swing undefined-behavior 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. 在两个面板中,选择CMYK并输入CMYK的任何有效数字。两个面板的值必须相同。
  2. 现在比较每个面板的RGB值。它们应该相同。
  3. 选择一个面板并将滑块重置为0。
  4. 现在将RGB值重新输入到同一面板中。
  5. 两个面板都切换到CMYK。我看到的面板中的值是不同的。

请注意,当以另一种方式使用(即首先选择RGB并重新输入CMYK值)时,所有操作均符合预期。我在想什么吗 对转换过程有什么期望,还是这是一个错误?

我正在Windows 10上运行Java 10,而我的IDE是Eclipse。

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

3 个答案:

答案 0 :(得分:4)

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

从JColorChooser到CMYK到RGB到CMYK永远无法完美运行的原因仅仅是因为JColorChooser显示 integers 而不是浮点数。例如,在CMYK模型中选择yellow = 255,然后返回RGB。您将看到此黄色是红色= 255和绿色= 255的混合色。现在回到CMYK,将黄色降低为254并检查RGB值-它仍然是red = 255和green = 255!

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

由于这些整数颜色模型的“颜色敏感度”不同,这一数字问题更加严重。 CMYK具有4个维度(青色,洋红色,黄色,键),因此可以表示256 ^ 4 = 4294967296不同的颜色RGB具有3个维度,并且只能表示256 ^ 3 = 16777216个颜色。因此,将CMYK转换为这种RGB时,您总是会丢失很多信息。

换句话说,平均而言,CMYK颜色空间中的256点仅由RGB颜色空间中的1点表示。当您将一种颜色从RGB转换回CMYK时,平均而言,CMYK空间中的255种颜色永远不会“达到”。

答案 1 :(得分:4)

我在JColorChooser,尤其是ColorModelCMYK(package-private类)使用的颜色模型中进行了一些调试。

除了将所有值0..255通过缩放255.0f转换为浮点数0.0..1.0之外,计算几乎都是简单的。这会在(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);
}

它被截断了!我不知道这是否是错误,但这当然是可用性问题。

答案 2 :(得分:1)

我也在Eclipse上的Windows上使用Java 8,它给了我相同的结果,但这不是问题。它对您来说很好用,但是将RGB转换为CMYK的方式与将CMYK转换为RGB的方式不同。 您可以在线查看此转换器中的内容:

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

CMYK适用于青色,品红色和黄色百分比。另一方面,红色,绿色和蓝色的RGB值在0到255之间。 在我通过的网络中,您放置了该转换的公式,并且无法以相同的双向方式工作。