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:

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:

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]);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With