创造更亮的颜色?(Java)

6
我试图使用java.awt.Color提供的默认颜色创建更亮的颜色,但是当我用这两种颜色绘制时,它们看起来是相同的?
Color blue = Color.BLUE;
Color brighterBlue = blue.brighter();

test.setColor(blue);
test.fillCircle(size);

test.setColor(brighterBlue);
test.drawCircle(size);

4
你的蓝色可能已经是最亮的蓝色了吗? - Lugubrious
1
除了您的代码会重叠之外,R = 0,G = 0,B = 255的颜色不太可能比它现在更亮。 - MadProgrammer
@lugubrious&MadProgrammer:好的,我回去检查了一下,这个方法可以创建一个更暗的颜色,所以我猜它是最亮的?非常感谢您的评论<3附:重叠是因为我想要一个带边框的圆形,但我不知道有更好的方法>_< - CJDKL
@CJDKL 这里的问题在于,“最亮”的概念并不是一个非常明确的术语。Color.brighter() 所执行的数学运算实际上是增加了颜色在 HSV 空间中的 ,这与它离白色有多近没有太大关系,它只是意味着它是最“蓝”的蓝色。 (HSV 的值轴几乎是极其愚蠢的。)HSL 更好一些,但仍然存在一个问题,即相同饱和度和亮度的蓝色看起来比黄色更暗。 - millimoose
2个回答

10

有很多方法可以解决这个问题。

最明显的方法是向现有的颜色值添加一个分数,例如...

int red = 128;
float fraction = 0.25f; // brighten by 25%

red = red + (red * float);

相反,你可以对颜色应用负载因子。我们知道颜色元素的最大值为255,因此,你不必试图增加颜色因子本身,而是可以将颜色元素按整个颜色范围的因子增加,例如

int red = 128;
float fraction = 0.25f; // brighten by 25%

red = red + (255 * fraction); // 191.75

基本上,这将通过255倍增加颜色元素......有点俏皮。现在我们还需要考虑到颜色永远不应大于255的事实。

这将允许您在变亮时强制颜色接近白色,在变暗时接近黑色......

输入图像描述

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BrighterColor {

    public static void main(String[] args) {
        new BrighterColor();
    }

    public BrighterColor() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            Rectangle rec = new Rectangle(0, 0, getWidth(), getHeight() / 2);
            g2d.setColor(Color.BLUE);
            g2d.fill(rec);
            g2d.translate(0, getHeight() / 2);
            g2d.setColor(brighten(Color.BLUE, 0.25));
            g2d.fill(rec);
            g2d.dispose();
        }
    }

    /**
     * Make a color brighten.
     *
     * @param color Color to make brighten.
     * @param fraction Darkness fraction.
     * @return Lighter color.
     */
    public static Color brighten(Color color, double fraction) {

        int red = (int) Math.round(Math.min(255, color.getRed() + 255 * fraction));
        int green = (int) Math.round(Math.min(255, color.getGreen() + 255 * fraction));
        int blue = (int) Math.round(Math.min(255, color.getBlue() + 255 * fraction));

        int alpha = color.getAlpha();

        return new Color(red, green, blue, alpha);

    }

}

这种方法会使饱和度有些偏差,根据HSL模型。从hsl(220, 75%, 27%)(即#113377以避免剪裁)开始,将128添加到每个分量中以使其变亮50%,最终得到hsl(220, 86%, 77%)。但它确实正确地调整了亮度并保持了色调不变。 - millimoose
结果发现,如果任何一种颜色剪辑了,这也会使色调偏斜。例如,将 hsl(210, 33%,40%)#446688 变亮,最终会得到 hsl(205, 100%,88%)。(此时饱和度完全混乱,但在高亮度下不太明显。) - millimoose
我并不否认这不是数学上完美的。我花了很多时间寻找能够产生所需效果的算法。对我而言,如果我从0开始向1移动,我就可以“看到”颜色向白色转变。我同意通常修改HSL可能是更完美的解决方案,但是我看到使用此方法的算法在我的测试范围内没有产生完全相同的结果,但这更多关乎于我当时的需求... - MadProgrammer
1
我并不是想否定你的解决方案 - 它很容易理解,差异也不是那么大,而且可能满足OP的需求。我只是指出它与在非常常见的HSL颜色空间中工作所能实现的有所偏离,该颜色空间旨在1:1映射到RGB。(虽然在我的眼中略微更具感知优势,但如果你要这样做,你会使用CIELAB。) - millimoose
你的观点是正确且受欢迎的 ;) - 我一直对寻找更好的理解和实现方式感兴趣。当我第一次尝试这些算法时,除了这种方法,我找不到任何可以使黑色变亮的东西。如果我正在处理一个基于颜色的应用程序,我肯定会更喜欢在这种情况下使用HLS而不是RGB。 - MadProgrammer

6
引用文档

该方法对此颜色的每个RGB分量应用任意比例因子,以创建此颜色的更亮版本。

因此,假设Color.blue是颜色rgb(0,0,255),则brighter方法将尝试:

  1. 0乘以比例因子,结果再次为0;和
  2. 255乘以比例因子,由于封顶而导致再次出现255

请注意,色调饱和度值(其中“值”与“亮度”相同)颜色坐标系模型与色调饱和度亮度模型不同,后者行为有些直观。 (有关HSL和HSV的详细信息,请参见维基百科上的HSL和HSV。)不幸的是,Java没有内置的HSL计算,但您应该能够轻松地通过搜索找到它们。


2
你可以查看HSL Color来了解一种实现方法。 - camickr
但是..比例因子具体是多少? - Redoman
@jj_ 就本问题而言,这并不重要。无论缩放因子是多少——只要大于 1 即可,否则该方法会使颜色变暗,而不是变亮——它都不会改变值为 0255 的 RGB 组件中的任何一个组件。 - millimoose
1
@jj_ 说句实话,Grepcode 表示它是 0.7 的倒数 = 7 / 101.43 : http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/awt/Color.java?av=f - millimoose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接