I am currently working on my personal project. The idea is to import a picture and crop it into n-pieces of bufferedimage then draw them with random sequence to a java canvas. After that save the canvas to image file. Right now iam stuck at saving the canvas and i have searching for the solutions but none of them work. Here my save procedure.
Please help, thanks in advance
private void save() {
int r = jFileChooser1.showSaveDialog(this);
File file2 = null;
if(r == jFileChooser1.APPROVE_OPTION){
file2 = jFileChooser1.getSelectedFile();
Graphics g2d = canvas.getGraphics();
BufferedImage bi = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.paint(g2);
g2.dispose();
g2d.dispose();
try
{
ImageIO.write(bi, "jpg", file2);
}
catch (Exception ex) {
System.out.println("Error saving");
}
}
}
Update :
Now i get it, after using paintComponents now i can save the picture. Thanks #madProgrammer
public class CaptureImage extends javax.swing.JFrame {
MyPanel canvas;
BufferedImage[] processedImage;
public CaptureImage(BufferedImage[] proc) {
processedImage = proc;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private void createAndShowGUI() {
System.out.println("Created GUI on EDT? "
+ SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Output Picture");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
save();
System.exit(0);//cierra aplicacion
}
});
canvas = new MyPanel(processedImage);
f.add(canvas);
f.setSize(400, 400);
f.setVisible(true);
}
public void save() {
JFileChooser jFileChooser1 = new JFileChooser();
int r = jFileChooser1.showSaveDialog(this);
File file2 = null;
if (r == jFileChooser1.APPROVE_OPTION) {
file2 = jFileChooser1.getSelectedFile();
BufferedImage bi = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.print(g2);
try {
ImageIO.write(bi, "jpg", file2);
g2.dispose();
} catch (Exception ex) {
System.out.println("Error saving");
}
}
}
}
class MyPanel extends JPanel {
private Image[] processedImage;
public MyPanel(Image[] processedImage) {
this.processedImage = processedImage;
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
repaint();
}
});
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int loopj = 10;
int loopi = 10;
int l = 0;
int jPieces = 100;
int[] r = new int[jPieces];
int rand = 0;
for (int i = 0; i < r.length; i++) {
rand = (int) (Math.random() * (r.length));
if (Arrays.binarySearch(r, 0, r.length, rand) <= -1) {
r[i] = rand;
}
}
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < loopi; i++) {
for (int j = 0; j < loopj; j++) {
g2d.drawImage(processedImage[r[l]], i * 30, j * 30, this);
l++;
}
}
}
}
There's no need to use getGraphics and you certainly shouldn't be disposing of it.
Instead of using paint, which could include double buffering, you should try using printAll
BufferedImage bi = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.printAll(g2);
g2.dispose();
See Component#printAll for more details.
You should also be using the size of the canvas to determine the size of the image. The above example assumes that the canvas has already been sized appropriately...
Related
I have a problem using Graphics to put an image in a jPanel. I have the next code:
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
lienzo.paintComponents(imagenAbrir.getGraphics());
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Ocurriò un error al guardar la imàgen");
}
}
The code is part of a button, the user could select an imagen from any path, but it doesn't show anything in the panel. What could be the problem?
I think you have to change you method with BufferedImage object not a Graphics object
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
Then, if you want to draw image, create customized JPanel class on your own.
The paintCompoent method of JComponent will be invoked automatically, every time you call repaint method in your code.
final class ImagePane extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage myImage;
public ImagePane(final BufferedImage myImage) {
this.myImage = myImage;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(240, 220);
}
public void drawImage(BufferedImage img)
{
this.myImage = img;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (myImage != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - myImage.getWidth()) / 2;
int y = (getHeight() - myImage.getHeight()) / 2;
g2d.drawImage(myImage, x, y, this);
g2d.dispose();
}
}
}
Here is full source code.
public class JFileChooserTest {
static Runnable doRun = new Runnable()
{
final class ChooseAction implements ActionListener
{
final ImagePane drawPan;
ChooseAction(final ImagePane drawPan)
{
this.drawPan = drawPan;
}
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
}
final class ImagePane extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage myImage;
public ImagePane(final BufferedImage myImage) {
this.myImage = myImage;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(240, 220);
}
public void drawImage(BufferedImage img)
{
this.myImage = img;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (myImage != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - myImage.getWidth()) / 2;
int y = (getHeight() - myImage.getHeight()) / 2;
g2d.drawImage(myImage, x, y, this);
g2d.dispose();
}
}
}
#Override
public void run() {
final JFrame frame = new JFrame();
//frame.setSize(new Dimension(300,400));
JPanel lienzo = new JPanel();
lienzo.setLayout(new BorderLayout());
ImagePane drawPan = new ImagePane(null);
JButton drawMe = new JButton("draw me");
lienzo.add(drawMe, BorderLayout.NORTH);
lienzo.add(drawPan, BorderLayout.CENTER);
frame.add(lienzo);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
drawMe.addActionListener(new ChooseAction(drawPan));
}
};
public static void main(String[] args)
{
SwingUtilities.invokeLater(doRun);
}
}
I hope this will help you.
The code is part of a button, the user could select an imagen from any path, but it doesn't show anything in the panel. What could be the problem?
Basically, this is not how custom painting works in Swing. Never call paintComponent or paintComponents yourself, it's not your responsibility.
What you want to do is paint the image to the component via its Graphics context
Take a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works and how you're suppose to use it
Then take a look at How to use lables for a simple solution for displaying images
You can also have a look at How to set a background picture in JPanel. It demonstrates using a JLabel and custom component for displaying an image
So, Do you want add image on the panel in which some base image is displayed?
If so, there is some trick to achieve to do this.
I prepare two images on the internet ( I am afraid these are licensed images )
Then, now i have three buttons put on your class
JButton drawMe = new JButton("draw me");
JButton pickMe = new JButton("pick me");
JButton clearMe = new JButton("clear me");
I decided to let the DrawAction class reuse with three action commands that are a draw, pick and clear together.
drawMe.addActionListener(drawAct);
drawMe.setActionCommand("draw");
pickMe.addActionListener(drawAct);
pickMe.setActionCommand("pick");
clearMe.addActionListener(drawAct);
clearMe.setActionCommand("clear");
We'll see the ImagePane class again. If you want to add a image on a image, you should have a paintcomponent method inherited from JComponent whatever components you want to use.
The 'draw me' button is to set the base image after clearing all images in the image list in which array list of the bufferedimage class.
public void drawImage(BufferedImage img)
{
if (imageList.size() > 0) imageList.clear();
imageList.add(img);
repaint();
}
The 'pick me' button is the method that add a image to the image list.
public void addImage(BufferedImage imagenAbrir) {
imageList.add(imagenAbrir);
repaint();
}
The last one is clear button, flush and clear all image buffers in the image list.
public void clearImage() {
imageList.clear();
isClear = true;
repaint();
}
Here is my trick to clear image on the panel, it is accomplished by re-drawing canvas(jPanel at this time) with some specific color(gray).
The main method, paintComponent as following..
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(isClear)
{
Graphics2D g2d = (Graphics2D) g.create();
Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
g2d.setPaint(Color.GRAY);
g2d.fill(rectangle);
g2d.dispose();
isClear = false;
return;
}
if (imageList.size() > 0) {
BufferedImage img = null;
for(int i = 0; i < imageList.size(); i++)
{
img = imageList.get(i);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
Finally, you read the code below how to handle action commands along with java's component,
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("draw"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
}
}
}
else if(e.getActionCommand().equals("pick"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.addImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
}
}
}
else if(e.getActionCommand().equals("clear"))
{
drawPan.clearImage();
}
}
As you see the code, picking a file is required every time you click both the pick or draw me button.
Full source code
package com.tobee.ui.test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JFileChooserTest {
static Runnable doRun = new Runnable()
{
final class DrawAction implements ActionListener
{
final ImagePane drawPan;
DrawAction(final ImagePane drawPan)
{
this.drawPan = drawPan;
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
if(e.getActionCommand().equals("draw"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
else if(e.getActionCommand().equals("pick"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.addImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
else if(e.getActionCommand().equals("clear"))
{
drawPan.clearImage();
}
}
}
final class ImagePane extends JPanel {
private static final long serialVersionUID = 1L;
private boolean isClear;
private List<BufferedImage> imageList;
public ImagePane()
{
imageList = new ArrayList<BufferedImage>();
isClear = false;
}
public void clearImage() {
imageList.clear();
isClear = true;
repaint();
}
public void addImage(BufferedImage imagenAbrir) {
imageList.add(imagenAbrir);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(240, 220);
}
public void drawImage(BufferedImage img)
{
if (imageList.size() > 0) imageList.clear();
imageList.add(img);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(isClear)
{
Graphics2D g2d = (Graphics2D) g.create();
Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
g2d.setPaint(Color.GRAY);
g2d.fill(rectangle);
g2d.dispose();
isClear = false;
return;
}
if (imageList.size() > 0) {
BufferedImage img = null;
for(int i = 0; i < imageList.size(); i++)
{
img = imageList.get(i);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
#Override
public void run() {
final JFrame frame = new JFrame();
JPanel lienzo = new JPanel();
lienzo.setLayout(new BorderLayout());
JPanel optionPan = new JPanel();
ImagePane drawPan = new ImagePane();
JButton drawMe = new JButton("draw me");
JButton pickMe = new JButton("pick me");
JButton clearMe = new JButton("clear me");
DrawAction drawAct = new DrawAction(drawPan);
optionPan.add(drawMe);
optionPan.add(pickMe);
optionPan.add(clearMe);
lienzo.add(optionPan, BorderLayout.NORTH);
lienzo.add(drawPan, BorderLayout.CENTER);
frame.add(lienzo);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
drawMe.addActionListener(drawAct);
drawMe.setActionCommand("draw");
pickMe.addActionListener(drawAct);
pickMe.setActionCommand("pick");
clearMe.addActionListener(drawAct);
clearMe.setActionCommand("clear");
}
};
public static void main(String[] args)
{
SwingUtilities.invokeLater(doRun);
}
}
I want to create a animation game by java. But it runs slowly when having image in JPanel than don't have it.
public class Multi_Paint extends JFrame implements ActionListener {
JPanel pn1 = new JPanel();
JPanel pn2 = new JPanel();
static int x=100,y=100;
Timer timer;
Multi_Paint(){
setLayout(new BorderLayout());
pn1.setBackground(Color.GREEN);
pn2.setBackground(Color.red);
pn2.setPreferredSize(new Dimension(300, 300));
add(pn1,BorderLayout.CENTER);
add(pn2,BorderLayout.WEST);
setSize(1000, 1000);
setVisible(true);
pn1.add(new DrawPanel());
pn2.add(new DrawPanel());
timer = new Timer(1, this);
timer.start();
}
public void actionPerformed(ActionEvent e) {
moveBall();
repaint();
}
void moveBall(){
x=x+10;
y=y+10;
}
public static void main(String[] args) {
new Multi_Paint();
}
}
class DrawPanel extends JPanel{
DrawPanel(){
setBorder(BorderFactory.createLineBorder(Color.black));
}
public Dimension getPreferredSize() {
return new Dimension(500,500);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int x= Multi_Paint.x;
int y= Multi_Paint.y;
//If we decline this "try" Java will run faster.
try {
BufferedImage img = ImageIO.read(new File("D:\\pict1.jpg"));
double scale = 0.5 ;
double w = scale * img.getWidth(this);
double h = scale * img.getHeight(this);
g.drawImage(img, x, y, (int) w, (int) h, this);
} catch (IOException e) {
e.printStackTrace();
}
g.fillOval(x, y, 30, 30);
}
}
As it is right now, ImageIO.read internally creates an ImageInputStream, writes the data into a new BufferedImage instance and closes the stream every single frame, which are expensive IO operations. That's why it is running slowly.
You shouldn't have any logic in your paintComponent method, or else this will slow the process down. You should rather read your image file once in your constructor and only access it in your paint method. Since your image file doesn't change over the course of the program, this is sufficient.
Something like this should work:
class DrawPanel extends JPanel {
private final BufferedImage img;
private int w;
private int h;
DrawPanel() {
setBorder(BorderFactory.createLineBorder(Color.black));
this.img = createImage("D:\\pict1.jpg");
}
private BufferedImage createImage(String path) {
BufferedImage img = null;
try {
img = ImageIO.read(new File(path));
double scale = 0.5;
this.w = (int) (scale * img.getWidth(this));
this.h = (int) (scale * img.getHeight(this));
} catch (IOException e) {
System.err.println("Could not read file with path " + path);
e.printStackTrace();
}
return img;
}
public Dimension getPreferredSize() {
return new Dimension(500,500);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int x= Multi_Paint.x;
int y= Multi_Paint.y;
// img could be null
if(this.img != null) {
g.drawImage(img, x, y, w, h, this);
}
g.fillOval(x, y, 30, 30);
}
}
Original question:
This method is supposed to change the image being displayed on a JFrame gradually into another image. However, without some way to slow it down, it just seems to change from one image to the new image. In order to slow it down, I put in a Thread.sleep(1000) so the changes wouldn't happen instantly. However, with this line in there, my program freezes completely. No error message, no nothing. Can anyone please help me out? Suggest a better method to slow it down, or how this can be fixed.
For clarification: int k is the number of gradual steps in the change. k = 1 would be an instant change. Anything greater would be gradual changes. int l meanwhile controls the ratio of how much of each image is displayed.
public void morphImg(int width, int height, BufferedImage morphImage, int k) {
//creates new image from two images of same size
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//get color from original image
Color c = new Color(image.getRGB(i, j));
//get colors from morph image
Color c2 = new Color(morphImage.getRGB(i, j));
for (int l = 1; l <= k; l++) {
//gets colors at different stages
int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);
Color newColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, newColor.getRGB());
//display new image
try {
imageLabel.setIcon(new ImageIcon(image2));
Thread.sleep(1000);
}
catch (InterruptedException e){
System.out.println("Exception caught.");
}
}
}
}
//sets modified image as "original" for further manipulation
setImage(image2);
}
UPDATED CODE: Using a Timer also causes the program to freeze...Am I not using it right?
public void morphImg(int width, int height, BufferedImage morphImage, int k) {
//creates new image from two images of same size
final BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int l = 1; l <= k; l++) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//get color from original image
Color c = new Color(image.getRGB(i, j));
//get colors from morph image
Color c2 = new Color(morphImage.getRGB(i, j));
//gets colors at different stages
int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);
Color newColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, newColor.getRGB());
//display new image
imageLabel.setIcon(new ImageIcon(image2));
final Timer t = new Timer(500,null);
t.setInitialDelay(500);
t.start();
}
}
}
//sets modified image as "original" for further manipulation
setImage(image2);
}
Never use Thread.sleep() when code is executing on the Event Dispatch Thread.
Instead you should use a Swing Timer to schedule your animation.
See the sections from the Swing tutorial on:
Concurrency in Swing
How to Use Timers
Or if you don't want to use a Timer, then you can use a SwingWorker (as described in the tutorial on concurrency) and then just publish() the image after you change it. Then you can use a Thread.sleep() since the SwingWorker doesn't execute on the EDT.
Simple Timer example:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class TimerTime extends JPanel implements ActionListener
{
private JLabel timeLabel;
private int count = 0;
public TimerTime()
{
timeLabel = new JLabel( new Date().toString() );
add( timeLabel );
Timer timer = new Timer(1000, this);
timer.setInitialDelay(1);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e)
{
// Update the time
timeLabel.setText( new Date().toString() );
count++;
// Stop after 10 events have been generated
if (count == 10)
{
Timer timer = (Timer)e.getSource();
timer.stop();
System.out.println( "Timer stopped" );
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("TimerTime");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TimerTime() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
The loop over k should be the outermost loop. Right now you are calling Thread.sleep k*width*height times.
If the intention is to show progressive animation of the morph effect, below is the test code I did without using Timer or Thread.sleep(), using the latest morph code given by OP:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JFrame;
class MorphComponent extends Component {
/**
*
*/
private static final long serialVersionUID = 1L;
private BufferedImage bi;
private URL imageSrc1;
private URL imageSrc2;
public MorphComponent(URL imageSrc1, URL imageSrc2) {
this.imageSrc1 = imageSrc1;
this.imageSrc2 = imageSrc2;
try {
BufferedImage img1 = ImageIO.read(imageSrc1);
//BufferedImage img2 = ImageIO.read(imageSrc2);
int w = img1.getWidth(null);
int h = img1.getHeight(null);
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(img1, 0, 0, null);
} catch (IOException e) {
System.out.println("Image could not be read");
System.exit(1);
}
}
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(null), bi.getHeight(null));
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.white);
g2d.fillRect(0,0, getWidth(), getHeight());
try {
BufferedImage img1 = ImageIO.read(imageSrc1);
BufferedImage img2 = ImageIO.read(imageSrc2);
int w = img1.getWidth(null);
int h = img1.getHeight(null);
bi = morphImg(g, img1, img2, w, h, 10);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private long start = System.currentTimeMillis();
public BufferedImage morphImg(Graphics gp, BufferedImage originalImage, BufferedImage morphImage, int width, int height, int k) {
//creates new image from two images of same size
final BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int l = 1; l <= k; l++) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
long elapsed = System.currentTimeMillis() - start;
//get color from original image
Color c = new Color(originalImage.getRGB(i, j));
//get colors from morph image
Color c2 = new Color(morphImage.getRGB(i, j));
//gets colors at different stages
int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);
Color newColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, newColor.getRGB());
if( elapsed > 100 ) {
gp.drawImage(image2, 0, 0, null);
start = System.currentTimeMillis();
repaint();
}
}
}
}
return image2;
}
}
public class MorphImageApplet extends JApplet {
/**
*
*/
private static final long serialVersionUID = 1L;
static String imageFileName1 = "image_1.jpg";
static String imageFileName2 = "image_2.jpg";
private URL imageSrc1;
private URL imageSrc2;
public MorphImageApplet () {
}
public MorphImageApplet (URL imageSrc1, URL imageSrc2) {
this.imageSrc1 = imageSrc1;
this.imageSrc2 = imageSrc2;
}
public void init() {
try {
imageSrc1 = new URL(getCodeBase(), imageFileName1);
imageSrc2 = new URL(getCodeBase(), imageFileName2);
} catch (MalformedURLException e) {
}
buildUI();
}
public void buildUI() {
final MorphComponent st = new MorphComponent(imageSrc1, imageSrc2);
add("Center", st);
}
public static void main(String s[]) {
JFrame f = new JFrame("See Through Image");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
URL imageSrc1 = null;
URL imageSrc2 = null;
try {
imageSrc1 = ((new File(imageFileName1)).toURI()).toURL();
imageSrc2 = ((new File(imageFileName2)).toURI()).toURL();
} catch (MalformedURLException e) {
}
MorphImageApplet sta = new MorphImageApplet(imageSrc1, imageSrc2);
sta.buildUI();
f.add("Center", sta);
f.pack();
f.setVisible(true);
}
}
I am trying to create a simple draw program that saves a basic drawing upon button click. I copied the draw methods from my textbook, I am just toying around. This is the buffered image I have created:
private static BufferedImage bi = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
And this creates the paint panel:
public PaintPanel() {
addMouseMotionListener(
new MouseMotionAdapter() {
public void mouseDragged(MouseEvent event) {
if (pointCount < points.length) {
points[pointCount] = event.getPoint();
++pointCount;
repaint();
}
}
});
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < pointCount; i++)
g.fillOval(points[i].x, points[i].y, 4, 4);
}
On a button click:
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
PaintPanel.saveImage();
System.exit(0);
}
I call this method:
public static void saveImage() {
try {
ImageIO.write(bi, "png", new File("test.png"));
} catch (IOException ioe) {
System.out.println("Eek");
ioe.printStackTrace();
}
}
But the png file that I save is just black.
The BufferedImage and panel component have 2 distinct Graphics objects. Therefore it is necessary to explicitly update the Graphics object for the former:
Graphics graphics = bi.getGraphics();
for (int i = 0; i < pointCount; i++) {
graphics.fillOval(points[i].x, points[i].y, 4, 4);
}
Im creating a Java applet for my website where users can draw an image by clicking and dragging the mouse. I then want to convert this image to a black and white image, in the form of a two dimensional array with 1's and 0's. I have created the drawing part but I'm not sure how to go from the applet to the two dimensional array. Any suggestions?
The first thing you need to do is convert the screen to a BufferedImage, this will allow you access to the pixel data.
Something like...
BufferedImage buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = buffer.createGraphics();
printAll(g2d);
g2d.dispose();
Next, you need to convert that to a black and white image...
BufferedImage bwImage = new BufferedImage(
buffer .getWidth(),
buffer .getHeight(),
BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = bwImage.createGraphics();
g2d.drawImage(buffer , 0, 0, null);
g2d.dispose();
Now, you can access the raw data...
for (int y = 0; y < bwImage.getHeight(); y++) {
for (int x = 0; x < bwImage.getWidth(); x++) {
Color color = new Color(bwImage.getRGB(x, y));
// You should only be interested in colors of 0,0,0 RGB
}
}
UPDATED with Example
This is an example I adopted from a previous question
public class MyPaint {
public static void main(String[] args) {
new MyPaint();
}
public MyPaint() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 600);
frame.getContentPane().setBackground(Color.DARK_GRAY);
frame.setLocationRelativeTo(null);
frame.setLayout(new GridBagLayout());
final PaintSurfacePane surface = new PaintSurfacePane();
JPanel pnlButtons = new JPanel(new GridBagLayout());
pnlButtons.setOpaque(false);
JButton saveFromImage = new JButton("Save From Image");
JButton saveFromGraphics = new JButton("Save From Grpahics");
pnlButtons.add(saveFromImage);
pnlButtons.add(saveFromGraphics);
saveFromGraphics.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
BufferedImage buffer = new BufferedImage(surface.getWidth(), surface.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = buffer.createGraphics();
surface.printAll(g2d);
g2d.dispose();
renderBlackWhite(buffer);
}
});
saveFromImage.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
BufferedImage buffer = new BufferedImage(surface.getWidth(), surface.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = buffer.createGraphics();
g2d.drawImage(surface.getPaintSurface(), 0, 0, surface);
g2d.dispose();
renderBlackWhite(buffer);
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
frame.add(surface, gbc);
gbc.gridy++;
gbc.weighty = 0;
frame.add(pnlButtons, gbc);
frame.setVisible(true);
}
});
}
public static void renderBlackWhite(BufferedImage buffer) {
BufferedImage bwImage = new BufferedImage(
buffer.getWidth(),
buffer.getHeight(),
BufferedImage.TYPE_BYTE_BINARY);
Graphics2D g2d = bwImage.createGraphics();
g2d.drawImage(buffer, 0, 0, null);
g2d.dispose();
JFrame frame = new JFrame("Black and White");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JLabel(new ImageIcon(bwImage)));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class PaintSurfacePane extends JPanel {
private BufferedImage paintSurface;
public PaintSurfacePane() {
// This will produce a buffered image that will render faster...
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
paintSurface = gc.createCompatibleImage(400, 400, Transparency.OPAQUE);
Graphics2D g2d = paintSurface.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, 400, 400);
g2d.dispose();
MouseHandler handler = new MouseHandler();
addMouseListener(handler);
addMouseMotionListener(handler);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(paintSurface, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
#Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
public BufferedImage getPaintSurface() {
return paintSurface;
}
protected class MouseHandler extends MouseAdapter implements MouseMotionListener {
private Point startPoint;
#Override
public void mouseReleased(MouseEvent e) {
startPoint = null;
}
#Override
public void mouseDragged(MouseEvent e) {
Point endPoint = e.getPoint();
if (startPoint != null) {
Graphics2D g2d = paintSurface.createGraphics();
g2d.setColor(Color.RED);
g2d.draw(new Line2D.Float(startPoint, endPoint));
g2d.dispose();
repaint();
}
startPoint = endPoint;
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
}
}
Essentially it uses the "direct from buffer" approach and the "paint" approach to convert the graphics to black and white.