Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the color of an icon based on user action?

I am writing an application where the user can change the color of the image on screen by choosing a new color. I have a simple image - only 40x40 - like this: Character Head

I have tried many things: pixel replacement, ColorModel, RGBFilter, etc. I can't figure this image stuff out. In the process of trying, I have learned about BufferedImage and I can get the .png's into that format and displayed on screen. I can turn the shape into a solid blob of color using pixel replacement, but the results are horrible.

From what I've gleaned, I want to use a ColorModel or Filter, but I am stumped. Here is a simple app that demonstrates where I am.

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

(I've never worked with dynamic colors and images, so I'm way over my head. Thanks in advance for your help.)

Edit: Here is a "before" and "after" image of what I would like after a darker color is chosen:

enter image description here enter image description here

like image 366
Jon Avatar asked Dec 09 '25 18:12

Jon


2 Answers

Perhaps there is a more elegant and efficient version but if you have a BufferedImage you could try something like:

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());
    }

Maybe this is the real problem: Mixing the two colors can be done by multiplying them...

Edit:

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]);
}
like image 65
foowtf Avatar answered Dec 12 '25 08:12

foowtf


If you know the colors you want in advance, you can use a LookupOp with a LookupTable. Examples may be found in Using the Java 2D LookupOp Filter Class to Process Images and Image processing with Java 2D.

If not, darker() or getHSBColor() may helpful, as shown here in the context of BufferedImage.

like image 35
trashgod Avatar answered Dec 12 '25 07:12

trashgod



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!