Colorize a picture in java - java

I would like, for a java project, to change the color of a hair modelisation (to change hair color) with shadows and reflects...
In fact, I wondered if there's a class which can change the color of a picture with a RGB code. If this can help you, here's the picture I need to colorize :

I assume that the question targeted NOT at blindly replacing certain pixels with a certain (fixed) color, but at really "dyeing" the image. Once I wrote a sample class showing how this could be done:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.imageio.*;
class DyeImage
{
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
new DyeImage();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
public DyeImage() throws Exception
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage image = ImageIO.read(new File("DRVpH.png"));
JPanel panel = new JPanel(new GridLayout(1,0));
panel.add(new JLabel(new ImageIcon(image)));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(255,0,0,128)))));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(255,0,0,32)))));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(0,128,0,32)))));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(0,0,255,32)))));
f.getContentPane().add(panel);
f.pack();
f.setVisible(true);
}
private static BufferedImage dye(BufferedImage image, Color color)
{
int w = image.getWidth();
int h = image.getHeight();
BufferedImage dyed = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
Graphics2D g = dyed.createGraphics();
g.drawImage(image, 0,0, null);
g.setComposite(AlphaComposite.SrcAtop);
g.setColor(color);
g.fillRect(0,0,w,h);
g.dispose();
return dyed;
}
}
The result with the given image and different dyeing colors will look like this:

Related

Image is not drawing on top left of panel

When i load image ,it do not load at upper left (if the image is large to be fit on window size).This is because i diminish its size as shown in code. Although i am giving its coordinate value 0,0 it is not drawing at that position.
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class photo extends JFrame
{
Dimension screenwidth=getToolkit().getScreenSize();
int mx=(int)screenwidth.getWidth();
int my=(int)screenwidth.getHeight();
BufferedImage picture1;
JLabel label3;
int neww;
int newh;
public photo() {
JFrame f = new JFrame("Image Editor v1.0");
f.setLayout(null);
try{
File file=new File("e:\\8.jpg");
picture1=ImageIO.read(file);
}catch(Exception e)
{
}
JPanel panel2 = new JPanel();
panel2.setLayout(null);
panel2.setBounds(101,20,mx-100,my-20);
f.add(panel2);
label3 = new JLabel("");
label3.setBounds(110,30,mx-110,my-30);
panel2.add(label3);
f.setExtendedState(Frame.MAXIMIZED_BOTH);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage bi = null;
if(picture1.getWidth()>mx-110 ||picture1.getHeight()>my-30 )
{
neww= (int) Math.round(picture1.getWidth() * 0.25);
newh = (int) Math.round(picture1.getHeight() *0.25);
}
else
{
neww=picture1.getWidth();
newh=picture1.getHeight();
}
bi = new BufferedImage(neww,newh,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(picture1,0,0,neww,newh,0,0,picture1.getWidth(),picture1.getHeight(), null);
label3.setIcon(new ImageIcon(bi));
}
public static void main(String[] args)
{
new photo();
}
}
You could add g2d.translate(0, 0); between g2d.addRenderingHints and g2d.drawImage and try it.
EDIT
So if you want the image to be at 101 px and 20 px, you should label3.setBounds(0,0,neww,newh); after label3.setIcon(new ImageIcon(bi)); instead of the current. I think this shall work as I have just tested.

Custom Swing Component Model, Component, UI delegate

I am very new to java in general and especially using Swing. I have created a custom swing component that zooms in and out on a picture using a slider. However I am now required to make it so that my code represents three classes
• Model
• The UI delegate
• An implementation of the component to bundle the model and UI delegate
together
I am very lost and cannot seem to get the code to function properly when I begin splitting it up into different classes. I have the interface working when implemented in a single class. Any help on how best to retool this code so that it fits into the previously mentioned model would be greatly appreciated. Here is my code.
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import java.io.File;
import java.net.URL;
import javax.imageio.ImageIO;
public class CustomComponent extends JComponent implements ChangeListener {
JPanel gui;
JLabel imageCanvas;
Dimension size;
double scale = 1.0;
private BufferedImage image;
public CustomComponent() {
size = new Dimension(10, 10);
setBackground(Color.black);
try {
image = ImageIO.read(new File("car.jpg"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void setImage(Image image) {
imageCanvas.setIcon(new ImageIcon(image));
}
public void initComponents() {
if (gui == null) {
gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(5, 5, 5, 5));
imageCanvas = new JLabel();
JPanel imageCenter = new JPanel(new GridBagLayout());
imageCenter.add(imageCanvas);
JScrollPane imageScroll = new JScrollPane(imageCenter);
imageScroll.setPreferredSize(new Dimension(300, 100));
gui.add(imageScroll, BorderLayout.CENTER);
}
}
public Container getGui() {
initComponents();
return gui;
}
public void stateChanged(ChangeEvent e) {
int value = ((JSlider) e.getSource()).getValue();
scale = value / 100.0;
paintImage();
}
protected void paintImage() {
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
BufferedImage bi = new BufferedImage(
(int)(imageWidth*scale),
(int)(imageHeight*scale),
image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform at = AffineTransform.getTranslateInstance(0, 0);
at.scale(scale, scale);
g2.drawRenderedImage(image, at);
setImage(bi);
}
public Dimension getPreferredSize() {
int w = (int) (scale * size.width);
int h = (int) (scale * size.height);
return new Dimension(w, h);
}
private JSlider getControl() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 1, 500, 50);
slider.setMajorTickSpacing(50);
slider.setMinorTickSpacing(25);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(this);
return slider;
}
public static void main(String[] args) {
CustomComponent app = new CustomComponent();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(app.getGui());
app.setImage(app.image);
// frame.getContentPane().add(new JScrollPane(app));
frame.getContentPane().add(app.getControl(), "Last");
frame.setSize(700, 500);
frame.setLocation(200, 200);
frame.setVisible(true);
}
}

Putting a transparent text field over an image

I'm trying to write a program that will allow me to put text over an image, and save the edited image. Right now I'm getting an error that says:
Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
When I run the code it shows the text box, and a white background without my image. Any help with this would be appreciated. Right now i'm just focused on getting the text field over the image. Thank you in advance!
Here's the code:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
import java.util.TreeSet;
public class Try1 extends JFrame {
public Try1() {
initializeUI();
}
BufferedImage img;
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
public void LoadImage() {
try {
img = ImageIO.read(new File("savedimage.jpg"));
}
catch (IOException e){}
}
private void initializeUI() {
JPanel panel = new JPanel(null);
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField textField = new JTextField(20);
textField.setBounds(50, 50, 100, 20);
panel.add(textField);
setContentPane(panel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Try1().setVisible(true);
}
});
JFrame f = new JFrame("Load Image Sample");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(new Try1());
f.pack();
f.setVisible(true);
}
}
A better approach in general can be seen in LabelRenderTest.
You only need to use HTML formatting in the label if multi-line text is required. Use plain text for a single line message.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class LabelRenderTest {
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
String title = "<html><body style='width: 200px; padding: 5px;'>"
+ "<h1>Do U C Me?</h1>"
+ "Here is a long string that will wrap. "
+ "The effect we want is a multi-line label.";
JFrame f = new JFrame("Label Render Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage image = new BufferedImage(
400,
300,
BufferedImage.TYPE_INT_RGB);
Graphics2D imageGraphics = image.createGraphics();
GradientPaint gp = new GradientPaint(
20f,
20f,
Color.red,
380f,
280f,
Color.orange);
imageGraphics.setPaint(gp);
imageGraphics.fillRect(0, 0, 400, 300);
JLabel textLabel = new JLabel(title);
textLabel.setSize(textLabel.getPreferredSize());
Dimension d = textLabel.getPreferredSize();
BufferedImage bi = new BufferedImage(
d.width,
d.height,
BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.createGraphics();
g.setColor(new Color(255, 255, 255, 128));
g.fillRoundRect(
0,
0,
bi.getWidth(f),
bi.getHeight(f),
15,
10);
g.setColor(Color.black);
textLabel.paint(g);
Graphics g2 = image.getGraphics();
g2.drawImage(bi, 20, 20, f);
ImageIcon ii = new ImageIcon(image);
JLabel imageLabel = new JLabel(ii);
f.getContentPane().add(imageLabel);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
Following JFrame is useless. Because Try1 is itself a JFrame.
JFrame f = new JFrame("Load Image Sample");
basically just use Try1 instead of other Jframe.
f = new Try1();
f.pack();
f.setVisible(true);
But more importantly, you should not override paint, overide paintComponent instead. See Difference between paint() and paintcomponent()?.
This is your problem
JFrame f = new JFrame("Load Image Sample");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
This is not a window. It is a JFrame, so it is unwise to put a WindowAdapter on it
Your class is extending a JFrame, so take out the JFrame, and just do your
new Try1();
f.pack();
f.setVisible(true);

how to save panel as image in swing?

Hi i want to convert panel which contains components like label and buttons to image file.
I have done the following code. The image was saved. but the content of the panel not visible or saved. Can anyone tell me how to save the panel with its components.
Code:
package PanelToImage;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
public class sample extends JPanel {
public JPanel firstpanel;
public JPanel secondpanel;
JLabel label1, label2;
JButton button1, button2;
public sample() {
firstpanel = new JPanel();
firstpanel.setSize(400,300);
firstpanel.setBackground(Color.RED);
secondpanel = new JPanel();
secondpanel.setBackground(Color.GREEN);
secondpanel.setSize(400,300);
label1 = new JLabel("label1");
label2 = new JLabel("label2");
button1 = new JButton("button1");
button2 = new JButton("button2");
firstpanel.add(label1);
firstpanel.add(button1);
secondpanel.add(label2);
secondpanel.add(button2);
saveImage(firstpanel);
add(firstpanel);
// add(secondpanel);
}
public static void main(String args[]) {
JFrame frame = new JFrame();
sample sam = new sample();
frame.setContentPane(sam);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
}
private void saveImage(JPanel panel) {
BufferedImage img = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_RGB);
panel.paint(img.getGraphics());
try {
ImageIO.write(img, "png", new File("E://Screen.png"));
System.out.println("panel saved as image");
} catch (Exception e) {
System.out.println("panel not saved" + e.getMessage());
}
}
}
Tthis code works for me (in the JFrame):
Container c = getContentPane();
BufferedImage im = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
c.paint(im.getGraphics());
ImageIO.write(im, "PNG", new File("shot.png"));
Maybe you have used custom panels. If true, try to add super.paint(g) at the beginning of the paint methods of your panels.
EDIT: You have to call saveImage after display the frame:
public static void main(String args[]) {
...
frame.setSize(400, 300);
sam.saveImage(sam.firstpanel);
}
EDIT 2: This is the saved image (is little because the layout, but is the proof that it should work):
I called the saveImage as last call in the main, and used a file in the user dir (new File("Screen.png")) as nIcE cOw said.
Here try this example program, instead of using getGraphics() seems like you have to use createGraphics() for the BufferedImage you are about to make.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
public class SnapshotExample
{
private JPanel contentPane;
private void displayGUI()
{
JFrame frame = new JFrame("Snapshot Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBackground(Color.WHITE);
JLabel label = new JLabel("This JLabel will display"
+ " itself on the SNAPSHOT", JLabel.CENTER);
contentPane.add(label);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
makePanelImage(contentPane);
}
private void makePanelImage(Component panel)
{
Dimension size = panel.getSize();
BufferedImage image = new BufferedImage(
size.width, size.height
, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
panel.paint(g2);
try
{
ImageIO.write(image, "png", new File("snapshot.png"));
System.out.println("Panel saved as Image.");
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SnapshotExample().displayGUI();
}
});
}
}

Set Color as int value for use in setRGB(int x, int y, int rgb) method? -- Java

Any other errors aside, I need a way of converting my Color grayScale into an int. When I plug in the Color, I get an error. setRGB method takes an x, a y, and an rgb int as parameters. How do I change my Color into an int?
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
public class Picture{
Container content;
BufferedImage image, image2;
public Picture(String filename) {
File f = new File(filename);
//assume file is the image file
try {
image = ImageIO.read(f);
}
catch (IOException e) {
System.out.println("Invalid image file: " + filename);
System.exit(0);
}
}
public void show() {
final int width = image.getWidth();
final int height = image.getHeight();
JFrame frame = new JFrame("Edit Picture");
//set frame title, set it visible, etc
content = frame.getContentPane();
content.setPreferredSize(new Dimension(width, height));
frame.pack();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add a menubar on the frame with a single option: saving the image
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenuItem saveAction = new JMenuItem("Save");
fileMenu.add(saveAction);
JMenuItem grayScale = new JMenuItem("Grayscale");
fileMenu.add(grayScale);
grayScale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
grayscale(width, height);
}
});
//add the image to the frame
ImageIcon icon = new ImageIcon(image);
frame.setContentPane(new JLabel(icon));
//paint the frame
frame.setVisible(true);
frame.repaint();
}
public void grayscale(int width, int height) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
Color color = new Color(image.getRGB(i, j));
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
int rGray = red*(1/3);
int gGray = green*(2/3);
int bGray = blue*(1/10);
Color grayScale = new Color(rGray, gGray, bGray);
image.setRGB(i,j, grayScale);
}
}
show();
}
public static void main(String[] args) {
Picture p = new Picture(args[0]);
p.show();
}
}
As per comment by trashgod.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
public class Picture{
Container content;
BufferedImage image;
BufferedImage image2;
public Picture(BufferedImage image) {
this.image = image;
grayscale();
}
public void show() {
JFrame frame = new JFrame("Edit Picture");
//set frame title, set it visible, etc
content = frame.getContentPane();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add the image to the frame
ImageIcon icon = new ImageIcon(image2);
frame.setContentPane(new JLabel(icon));
frame.pack();
//paint the frame
frame.setVisible(true);
}
public void grayscale() {
// create a grayscale image the same size
image2 = new BufferedImage(
image.getWidth(),
image.getHeight(),
BufferedImage.TYPE_BYTE_GRAY);
// convert the original colored image to grayscale
ColorConvertOp op = new ColorConvertOp(
image.getColorModel().getColorSpace(),
image2.getColorModel().getColorSpace(),null);
op.filter(image,image2);
show();
}
public static void main(String[] args) {
int size = 120;
int pad = 10;
BufferedImage bi = new BufferedImage(
size,
size,
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0,0,size,size);
g.setColor(Color.YELLOW);
g.fillOval(pad,pad,size-(2*pad),size-(2*pad));
g.dispose();
Picture p = new Picture(bi);
p.show();
}
}
image.setRGB(i, j, grayScale.getRGB());
Take a look at what values (1/3), (2/3), and (1/10) actually have, then note that you are multiplying your red, green, and blue values by those numbers.
The color is an Object. An rgb is an int. Use colorName.getRGB() to get the integer RGB value of that color.

Categories

Resources