【问题标题】:Anomalous behavior (or possible bug) in JColorChooserJColorChooser 中的异常行为(或可能的错误)
【发布时间】:2019-08-31 05:45:09
【问题描述】:

使用 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

【问题讨论】:

    标签: java swing undefined-behavior cmyk jcolorchooser


    【解决方案1】:

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

    计算非常简单,除了所有值 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);
    }
    

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

    【讨论】:

      【解决方案2】:

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

      CMYK 到 RGB 到 CMYK 无法在 JColorChooser 中完美运行的原因仅仅是因为 JColorChooser 显示 整数 而不是浮点数。例如在 CMYK 模型中选择黄色=255 并返回到 RGB。你会看到这个黄色是由 red=255 和 green=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 种颜色永远无法“达到”。

      【讨论】:

      • 您的回答启发了我使用 255..254..253 步骤作为指导来编写自己的答案。但是,我不同意您对“更大”色彩空间的解释。在 Java 的(过于简化的)CMYK 中,添加 K 只是意味着减去等量的 C、M、Y。这只是意味着有很多不明确的色点,唯一色点的数量仍然等于2^24。
      • 嗨,马克,恭喜您在源代码中找到,但我并不完全同意您的评论。使用 CMYK 可能会有许多多余的颜色组合,但 CMYK 肯定有超过 256^3 的颜色组合。例如考虑深黄色的情况:r=1,g=1,b=0 这应该映射到 y=1 和 k=0 的 CMYK。但是我们有 y=1 和 k=1,2,3,..,255,它们甚至比 r=1,g=1,b=0 更暗。因此,离散 CMYK 可以表示 r=0.5,g=0.5,y=1 和 k=128。
      • 仅供参考,另一个有趣的注意事项是,理论上,RGB 和 CMYK 实际上是不同的,而不是完全重叠的颜色空间。查看维基百科上 Gamut 条目中的这句话:en.wikipedia.org/wiki/Gamut" .... "例如,虽然纯红色可以在 RGB 颜色空间中表示,但不能在 CMYK 颜色空间中表示;纯红色在 CMYK 颜色空间中超出了色域。” - 因此,当您查看此颜色空间时,事情会很快变得复杂且非线性。
      • 您对非模棱两可的分数颜色是正确的。我知道非重叠性。这就是为什么我在括号中称其为“过度简化”。最简单的线索是油漆青色更像是深天蓝色而不是加色青色。 “真正的”转换(打印机应该使用)也是非线性的,因为 RGB 在 sRGB 中,而 CMYK 显然不是。
      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-12
        • 1970-01-01
        • 2010-12-14
        相关资源
        最近更新 更多