【问题标题】:How to change the color of an icon based on user action?如何根据用户操作更改图标的颜色?
【发布时间】:2011-12-23 05:08:33
【问题描述】:

我正在编写一个应用程序,用户可以通过选择一种新颜色来更改屏幕上图像的颜色。我有一个简单的图像 - 只有 40x40 - 像这样:

我尝试了很多东西:像素替换、ColorModel、RGBFilter 等。我无法弄清楚这个图像的内容。在尝试的过程中,我了解了 BufferedImage,我可以将 .png 转换为该格式并显示在屏幕上。我可以使用像素替换将形状变成纯色斑点,但结果很糟糕。

根据我收集到的信息,我想使用 ColorModel 或 Filter,但我很难过。这是一个简单的应用程序,可以演示我的位置。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class ChangeImageColor {
  public static void main(String[] args) {
    final ChangeColor cc = new ChangeColor();
    java.awt.EventQueue.invokeLater( new Runnable() { @Override
      public void run() { cc.setVisible( true ); }}
    ); // invokeLater
  } // main
} // ChangeImageColor

  class ChangeColor extends JFrame {
    String  CHAR_HEAD    = "res/images/char/Head.png";
    JLabel  imageHead    = new JLabel( new ImageIcon( CHAR_HEAD ) );
    JButton buttonChoose = new JButton( "Choose Color" );

    public ChangeColor() {
      this.setSize( 200, 200 );
      this.setLayout( new BorderLayout() );

      buttonChoose.addActionListener( listenerButton );

      this.add( imageHead, BorderLayout.CENTER );
      this.add( buttonChoose, BorderLayout.SOUTH );
    } // constructor

    ActionListener listenerButton = new ActionListener() {
      @Override public void actionPerformed( ActionEvent event ) {
        Color newColor = JColorChooser.showDialog( null, "Choose Color", Color.RED );
        ImageIcon icon = new ImageIcon( CHAR_HEAD );

        System.out.println( "~" + newColor );

        // *****************
        // insert code to change color of Head.png to shades of chosen color
        // *****************

        imageHead.setIcon( icon );
      } // actionPerformed
    };

  } // class

(我从来没有使用过动态颜色和图像,所以我有点不知所措。在此先感谢您的帮助。)

编辑:这是选择较深颜色后我想要的“之前”和“之后”图像:

【问题讨论】:

  • 您是否限制了用户可以选择的颜色?您希望图像的哪些部分成为新颜色?
  • 我认为他希望灰度图像颜色作为所选颜色的某种亮度。
  • 是的,图像是灰度的,其中有 2 到 6 种灰度。我想调整所有这些阴影以反映所选颜色。
  • 嗯,我的回答对你有帮助吗,有什么问题吗?

标签: java image swing colors


【解决方案1】:

也许有一个更优雅、更高效的版本,但如果你有一个 BufferedImage,你可以尝试如下:

BufferedImage image;
for(int y = 0; y < image.getHeight(); y++)
    for(int x = 0; x < image.getWidth(); x++)
    {
        Color imageColor = new Color(image.getRGB(x, y));
        //mix imageColor and desired color 
        image.setRGB(x, y, imageColor.getRGB());
    }

也许这是真正的问题:混合两种颜色可以通过将它们相乘来完成......

编辑:

private Color multiply(Color color1, Color color2)
{
    float[] color1Components = color1.getRGBComponents(null);   
    float[] color2Components = color2.getRGBColorComponents(null);
    float[] newComponents = new float[3]; 

    for(int i = 0; i < 3; i++)
        newComponents[i] = color1Components[i] * color2Components[i];

    return new Color(newComponents[0], newComponents[1], newComponents[2],
        color1Components[3]);
}

【讨论】:

  • +1 setRGB();我放大了here
  • 我尝试了 setRGB,它改变了颜色,但结果都是单一颜色。正如你所建议的,我无法弄清楚如何将它们相乘。我需要考虑原始图像中的其他阴影。
  • RGB 颜色由三个分量组成:红色、绿色、蓝色,范围在 0 到 255(一个字节)之间。如果将字节转换为从 0.0 到 1.0 的浮点数,则可以将每个分量相乘。对于您的灰度图像,每个像素对于每个颜色分量都有相同的强度,这样它就充当了一个亮度因子(0 是黑色,1 是白色)。我在答案中添加了代码来解释这一点(未经测试),希望对您有所帮助...
  • 是的,这有帮助。我会试试看。我不知道那里有光。我已经看到了对浮点数、字节数、“预乘”和移位的引用——它只是让我头疼。阅读 getRGBColorComponents 上的文档让事情变得轻而易举。我会让你知道结果如何。
  • 这是有效的,但我在透明度方面遇到了问题。我在图像周围出现了一个大黑框。 .png 是 40x40,我认为它忽略了 Alpha,但我还没有弄清楚如何保留它。那里有任何指针吗?
【解决方案2】:

如果您提前知道想要的颜色,可以使用LookupOpLookupTable。示例可以在Using the Java 2D LookupOp Filter Class to Process ImagesImage processing with Java 2D 中找到。

如果没有,darker()getHSBColor() 可能会有所帮助,如 BufferedImage 上下文中的 here 所示。

【讨论】:

  • 我不知道客户会选择什么颜色 - 因此是 JColorChooser 对话框。我不知道这是否会改变你的建议。
  • 啊,你正在写一个编辑器。您可以按照example 中的建议实现一个滴管 工具,该工具在鼠标移动时显示RGB 值。三个源 RGB 分量是LookupTable 的索引;所选的 RGB 分量是这些索引处的新条目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2021-03-21
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多