Reputation:
I'm attempting to develop an image editor in Java. Part of my Java image implementation of the image editor is to load an image and draw some shapes in addition to performing rotation, scaling, etc.
I'm using JLabel to load images but is there a way to draw and apply transformation on an image using JLabel? All of the examples I've found online used JPanel.
Upvotes: 2
Views: 12558
Reputation: 5625
You really need to look at Java2D turorial. You should draw images on Graphics2D
and also rotate and scale images on Graphics2D
.
Don't use JLabel
, because
J-* Components are heavy (although JLabel
is light-weighted). You can add an icon to a JLabel, but generally, they are used in stable cases, which won't be changed
frequently and arbitrarily. Painting on a J-* component brings
too many changes on it.
If you add a great number of components, it will also reduce performance.
(Each component would paint itself in a separate Graphics
object which belongs to
it and its container will paint them all and the layout also matters.)
Another drawback is it is sometimes very difficult even impossible to
do some manipulations on a component or on a couple of components together. For example, what if you want to add two pictures and group them? You need 2 JLabel
s, 1 JPanel
(maybe). Then what if you want to draw a line across these two images and group them again?
Below are the basic steps:
paint
or paintComponent
method of a component;Graphics
instance to Graphics2D
;Graphics2D
;Graphics2D
;Graphics2D
A large variety of classes are used, such as Graphics2D
, AffineTransform
, RenderingHints
, BufferedImage
, Shape
, etc. and even more methods. I can't describe everything here. Just read the Java2D tutorial. It gives you an overview of the APIs and tells you how to do these things.
Upvotes: 6
Reputation: 29
Here is Simple Image Editor
/*Arpana*/
CPanel displayPanel;
JButton sharpenButton, blurringButton, edButton, resetButton;
public ConvolveApp()
super();
Container container = getContentPane();
displayPanel = new CPanel();
container.add(displayPanel);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
panel
.setBorder(new TitledBorder(
"Click a Button to Perform the Associated Operation and Reset..."));
sharpenButton = new JButton("Sharpen");
sharpenButton.addActionListener(new ButtonListener());
blurringButton = new JButton("Blur");
blurringButton.addActionListener(new ButtonListener());
edButton = new JButton("Edge Detect");
edButton.addActionListener(new ButtonListener());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ButtonListener());
panel.add(sharpenButton);
panel.add(blurringButton);
panel.add(edButton);
panel.add(resetButton);
container.add(BorderLayout.SOUTH, panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
setVisible(true);
public static void main(String arg[]) {
new ConvolveApp();
class ButtonListener implements ActionListener
public void actionPerformed(ActionEvent e)
JButton button = (JButton) e.getSource();
if (button.equals(sharpenButton))
displayPanel.sharpen();
displayPanel.repaint();
else if (button.equals(blurringButton))
displayPanel.blur();
displayPanel.repaint();
else if (button.equals(edButton))
displayPanel.edgeDetect();
displayPanel.repaint();
else if (button.equals(resetButton))
displayPanel.reset();
displayPanel.repaint();
class CPanel extends JLabel
Image displayImage;
BufferedImage biSrc;
BufferedImage biDest;
BufferedImage bi;
Graphics2D big;
CPanel()
setBackground(Color.black);
loadImage();
setSize(displayImage.getWidth(this), displayImage.getWidth(this));
createBufferedImages();
bi = biSrc;
public void loadImage()
displayImage = Toolkit.getDefaultToolkit().getImage("Arpana.jpg");
MediaTracker mt = new MediaTracker(this);
mt.addImage(displayImage, 1);
try
mt.waitForAll();
if (displayImage.getWidth(this) == -1)
System.out.println("No jpg file");
System.exit(0);
public void createBufferedImages()
biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
big = biSrc.createGraphics();
big.drawImage(displayImage, 0, 0, this);
biDest = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
public void sharpen()
float data[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
public void blur()
float data[] = { 0.0625f, 0.125f, 0.0625f, 0.125f, 0.25f, 0.125f,
0.0625f, 0.125f, 0.0625f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
public void edgeDetect()
float data[] = { 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
public void reset()
big.setColor(Color.black);
big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
big.drawImage(displayImage, 0, 0, this);
bi = biSrc;
public void update(Graphics g)
g.clearRect(0, 0, getWidth(), getHeight());
paintComponent(g);
Upvotes: 1
Reputation: 29
/* Arpana*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class ConvolveApp extends JFrame {
CPanel displayPanel;
JButton sharpenButton, blurringButton, edButton, resetButton;
public ConvolveApp() {
super();
Container container = getContentPane();
displayPanel = new CPanel();
container.add(displayPanel);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
panel
.setBorder(new TitledBorder(
"Click a Button to Perform the Associated Operation and Reset..."));
sharpenButton = new JButton("Sharpen");
sharpenButton.addActionListener(new ButtonListener());
blurringButton = new JButton("Blur");
blurringButton.addActionListener(new ButtonListener());
edButton = new JButton("Edge Detect");
edButton.addActionListener(new ButtonListener());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ButtonListener());
panel.add(sharpenButton);
panel.add(blurringButton);
panel.add(edButton);
panel.add(resetButton);
container.add(BorderLayout.SOUTH, panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
setVisible(true);
}
public static void main(String arg[]) {
new ConvolveApp();
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
if (button.equals(sharpenButton)) {
displayPanel.sharpen();
displayPanel.repaint();
} else if (button.equals(blurringButton)) {
displayPanel.blur();
displayPanel.repaint();
} else if (button.equals(edButton)) {
displayPanel.edgeDetect();
displayPanel.repaint();
} else if (button.equals(resetButton)) {
displayPanel.reset();
displayPanel.repaint();
}
}
}
}
class CPanel extends JLabel {
Image displayImage;
BufferedImage biSrc;
BufferedImage biDest; // Destination image is mandetory.
BufferedImage bi; // Only an additional reference.
Graphics2D big;
CPanel() {
setBackground(Color.black);
loadImage();
setSize(displayImage.getWidth(this), displayImage.getWidth(this));
createBufferedImages();
bi = biSrc;
}
public void loadImage() {
displayImage = Toolkit.getDefaultToolkit().getImage("Arpana.jpg");
MediaTracker mt = new MediaTracker(this);
mt.addImage(displayImage, 1);
try {
mt.waitForAll();
} catch (Exception e) {
System.out.println("Exception while loading.");
}
if (displayImage.getWidth(this) == -1) {
System.out.println("No jpg file");
System.exit(0);
}
}
public void createBufferedImages() {
biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
big = biSrc.createGraphics();
big.drawImage(displayImage, 0, 0, this);
biDest = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
}
public void sharpen() {
float data[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void blur() {
float data[] = { 0.0625f, 0.125f, 0.0625f, 0.125f, 0.25f, 0.125f,
0.0625f, 0.125f, 0.0625f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void edgeDetect() {
float data[] = { 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void reset() {
big.setColor(Color.black);
big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
big.drawImage(displayImage, 0, 0, this);
bi = biSrc;
}
public void update(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
paintComponent(g);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(bi, 0, 0, this);
}
}
Upvotes: 0
Reputation: 36423
I'm using JLabel to load images but is there away to draw and apply transformation on an image using JLabel?
Not sure exactly what you mean.
But you can simply get the icon of the JLabel
(which is the image being displayed) do what needs to be done on the icon which we converted to BufferedImage
and than reapply the icon via setIcon(..)
.
Here is a short example hope it helps:
JLabel
with icon/BufferedImage
before rotating -45 degrees:
JLabel
after icon was got, rotated and re applied via setIcon(...)
:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Test {
private static JLabel imageLabel;
private static JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
imageLabel = new JLabel(new ImageIcon(createImage()));//set image of JLabel
panel.add(imageLabel);
frame.add(panel);
frame.pack();
frame.setVisible(true);
startImageChangeTimer();//creates a timer which will rotate image after 5 seconds
}
private void startImageChangeTimer() {
Timer timer = new Timer(5000, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
//get JLabel Icon and convert to BufferedImage
BufferedImage img = getBufferedImageOfIcon(imageLabel.getIcon(), imageLabel.getWidth(), imageLabel.getHeight());
//rotate the image
img = createTransformedImage(img, -45);
//change the labels image
imageLabel.setIcon(new ImageIcon(img));
frame.pack();//resize frame accrodingly
}
});
timer.setRepeats(false);
timer.start();
}
});
}
public static BufferedImage createImage() {
BufferedImage img = new BufferedImage(100, 50, BufferedImage.TRANSLUCENT);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("Calibri", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
String text = "Hello world";
int textWidth = fm.stringWidth(text);
g2d.drawString(text, (img.getWidth() / 2) - textWidth / 2, img.getHeight() / 2);
g2d.dispose();
return img;
}
public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int originalWidth = image.getWidth();
int originalHeight = image.getHeight();
int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
Graphics2D g2d = rotatedBI.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return rotatedBI;
}
}
Update:
I do tend to agree with @shuangwhywhy. Draw image to JPanel
via paintComponent(Graphics g)
thus you can simply resize the image and set it to the JPanel
image (via getters and setters)and than call repaint()
to show the changes.
Upvotes: 3
Reputation: 3234
I have only heard of people using JLabels to accomplish this. I recommend displaying the BufferedImage
as the background of the JLabel. When the user applies an edit to the image, edit the image (If you don't already have a library for manipulating images, I strongly recommend imgscalr) and reapply it as the background of the JLabel (if it doesn't automatically update).
Upvotes: 0