Convert a Graphics2D to an Image or BufferedImage - java

I have a little problem here.
I have an applet, where user can "draw" inside it. To do that, I use the java.awt.Graphics2D.
But, how can I do to save the user draw image as a JPEG image, or at least, convert it to a BufferedImage or something? I don't know how to do that.
Thanks.

Have them draw directly in a BufferedImage by way of it's Graphics2D object which you can get via getGraphics(). Then use ImageIO.write(...) to output the image to whatever file type you desire (and that's supported). The ImageIO API should help you with this: ImageIO API.
The other issue you'll have is where are they supposed to save the image once it has been drawn? On their own computer? If so and this is an applet program, then the applet will need to be "signed" in order for it to have the permission to write to disk. If you're unsure on this, check out Google, this article, or you may wish to write a new question for this issue alone.
Edit 1: code example
For example:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
#SuppressWarnings("serial")
public class DrawAndSaveImage extends JPanel {
private static final int BI_WIDTH = 600;
private static final int BI_HEIGHT = BI_WIDTH;
private static final Color LABEL_DRAW_COLOR = new Color(180, 180, 255);
private static final Stroke LABEL_DRAW_STROKE = new BasicStroke(1);
private static final Stroke BIMAGE_DRAW_STROKE = new BasicStroke(4);
private static final int COLOR_DIV = 5;
private BufferedImage bImage = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_RGB);
private List<Point> pointList = new ArrayList<Point>();
private JLabel imageLabel;
private List<Color> colorList = new ArrayList<Color>();
private Random random = new Random();
public DrawAndSaveImage() {
Graphics2D g2d = bImage.createGraphics();
g2d.setBackground(Color.white);
g2d.clearRect(0, 0, BI_WIDTH, BI_HEIGHT);
g2d.dispose();
for (int r = 0; r < COLOR_DIV; r++) {
for (int g = 0; g < COLOR_DIV; g++) {
for (int b = 0; b < COLOR_DIV; b++) {
Color c = new Color((r * 255) / COLOR_DIV,
(g * 255) / COLOR_DIV, (b * 255) / COLOR_DIV);
colorList.add(c);
}
}
}
imageLabel = new JLabel(new ImageIcon(bImage)) {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintInLabel(g);
}
};
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
imageLabel.addMouseListener(myMouseAdapter);
imageLabel.addMouseMotionListener(myMouseAdapter);
imageLabel.setBorder(BorderFactory.createEtchedBorder());
JButton saveImageBtn = new JButton("Save Image");
saveImageBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
saveImageActionPerformed();
}
});
JButton clearImageBtn = new JButton("Clear Image");
clearImageBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Graphics2D g2 = bImage.createGraphics();
g2.setBackground(Color.white);
g2.clearRect(0, 0, BI_WIDTH, BI_HEIGHT);
g2.dispose();
imageLabel.repaint();
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(saveImageBtn);
btnPanel.add(clearImageBtn);
setLayout(new BorderLayout());
add(imageLabel, BorderLayout.CENTER);
add(btnPanel, BorderLayout.SOUTH);
}
private void saveImageActionPerformed() {
JFileChooser filechooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"JPG Images", "jpg");
filechooser.setFileFilter(filter);
int result = filechooser.showSaveDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
File saveFile = filechooser.getSelectedFile();
try {
ImageIO.write(bImage, "jpg", saveFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void paintInLabel(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(LABEL_DRAW_COLOR);
g2d.setStroke(LABEL_DRAW_STROKE);
if (pointList.size() < 2) {
return;
}
for (int i = 1; i < pointList.size(); i++) {
int x1 = pointList.get(i - 1).x;
int y1 = pointList.get(i - 1).y;
int x2 = pointList.get(i).x;
int y2 = pointList.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
pointList.add(e.getPoint());
imageLabel.repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
Graphics2D g2d = bImage.createGraphics();
g2d.setColor(colorList.get(random.nextInt(colorList.size())));
g2d.setStroke(BIMAGE_DRAW_STROKE);
if (pointList.size() >= 2) {
for (int i = 1; i < pointList.size(); i++) {
int x1 = pointList.get(i - 1).x;
int y1 = pointList.get(i - 1).y;
int x2 = pointList.get(i).x;
int y2 = pointList.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
g2d.dispose();
pointList.clear();
imageLabel.repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
pointList.add(e.getPoint());
imageLabel.repaint();
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("DrawAndSaveImage");
frame.getContentPane().add(new DrawAndSaveImage());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}

I do it that way, and works very well:
BufferedImage awtImage = new BufferedImage(drawPanel.getWidth(), drawPanel.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = awtImage.getGraphics();
drawPanel.printAll(g);
try
{
String caminhoImagem = System.getProperty("user.home") + "\\temps\\assinatura.jpg";
FileOutputStream fos = new FileOutputStream(caminhoImagem);
JPEGImageEncoderImpl j = new JPEGImageEncoderImpl(fos);
j.encode(awtImage);
fos.close();
} catch(e) {..... }
That's all :)
Thanks everyone :)

Use the drawImage method provided by Graphics2D and write it using ImageIO
BufferedImage img;
g2dObject.drawImage(img, null, 0, 0);
ImageIO.write(img, "JPEG", new File("foo.jpg"));

Use the "drawOnImage" example from Custom Painting Approaches. Then to create the image of the panel you can use the Screen Image class.

If you'd like to draw JComponent's image onto BufferedImage (JApplet extends JComponent):
JComponent whatToDraw = ...;
BufferedImage img = new BufferedImage(whatToDraw.getWidth(),
whatToDraw.getHeight(), BufferedImage.TYPE_INT_RGB);
whatToDraw.printAll(img.getGraphics());
And to write its data to JPEG file:
ImageIO.write(img, "jpg", new File("something.jpg"));

Related

Why does my buffered image not display in my JPanel?

I am trying to edit the pixels of a new buffered image but when I use the constructor for a new BufferedImage it does not display, when I load an image and set the pixels it does. Why does it not display?
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = 1000;
int h = 1000;
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
//ImageIO.read(new File("/Users/george/Documents/Ali.png"));
int color = Color.BLACK.getRGB();
for(int x = 0; x < w; x++) {
for(int y = 0; y < h; y++) {
image.setRGB(x, y, color);
}
}
g.drawImage(image, 0, 0, null);
}
Again, don't edit the BufferedImage from within paintComponent -- do it elsewhere. For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class ImageEdit extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int COLOR = Color.BLACK.getRGB();
private BufferedImage image = null;
public ImageEdit() {
image = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_RGB);
for(int x = 0; x < PREF_H; x++) {
for(int y = 0; y < PREF_W; y++) {
image.setRGB(x, y, COLOR);
}
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, this);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
ImageEdit mainPanel = new ImageEdit();
JFrame frame = new JFrame("ImageEdit");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Select, Copy and Paste Images

What I want my app to do:
1 - Select an area of Image and get the coordinates. This code below should do this:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
public class ScreenCaptureRectangle {
Rectangle captureRect;
ScreenCaptureRectangle(final BufferedImage screen) {
final BufferedImage screenCopy = new BufferedImage(
screen.getWidth(),
screen.getHeight(),
screen.getType());
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int)(screen.getWidth()/3),
(int)(screen.getHeight()/3)));
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
final JLabel selectionLabel = new JLabel(
"Drag a rectangle in the screen shot!");
panel.add(selectionLabel, BorderLayout.SOUTH);
repaint(screen, screenCopy);
screenLabel.repaint();
screenLabel.addMouseMotionListener(new MouseMotionAdapter() {
Point start = new Point();
#Override
public void mouseMoved(MouseEvent me) {
start = me.getPoint();
repaint(screen, screenCopy);
selectionLabel.setText("Start Point: " + start);
screenLabel.repaint();
}
#Override
public void mouseDragged(MouseEvent me) {
Point end = me.getPoint();
captureRect = new Rectangle(start,
new Dimension(end.x-start.x, end.y-start.y));
repaint(screen, screenCopy);
screenLabel.repaint();
selectionLabel.setText("Rectangle: " + captureRect);
}
});
JOptionPane.showMessageDialog(null, panel);
System.out.println("Rectangle of interest: " + captureRect);
}
public void repaint(BufferedImage orig, BufferedImage copy) {
Graphics2D g = copy.createGraphics();
g.drawImage(orig,0,0, null);
if (captureRect!=null) {
g.setColor(Color.RED);
g.draw(captureRect);
g.setColor(new Color(255,255,255,150));
g.fill(captureRect);
}
g.dispose();
}
public static void main(String[] args) throws Exception {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ScreenCaptureRectangle(screen);
}
});
}
}
2 - get the coordinates and use it on getSubimage method.
double w = captureRect.getWidth();
double h = captureRect.getHeight();
double x = captureRect.getX();
double y = captureRect.getY();
int W = (int) w;
int H = (int) h;
int X = (int) x;
int Y = (int) y;
BufferedImage selectImg = screen.getSubimage(x, y, w, h);
3 - this code create a new image file and copy the imageselected.
BufferedImage img = new BufferedImage ( 5000, 5000, BufferedImage.TYPE_INT_RGB );
img.createGraphics().drawImage(selectImg, 0, 0, null);
File final_image = new File("C:/Final.jpg");
ImageIO.write(img, "jpeg", final_image);
The idea of app is:
- Select an area of the image.
- Copy that image and paste in other file. ( when I pressed any button )
- The program will continue run until I press another button.
- Every image that I copy the program will paste it beside the last one.
I think I am near to the solution. Can any one help me to "connect the parts" ?
Start by taking a look at:
How to Write a Mouse Listener
How to Use Buttons, Check Boxes, and Radio Buttons
How to Write an Action Listeners
Performing Custom Painting
Writing/Saving an Image
You need to take the concepts you have and rework them into a coherent workable solution. That is, provide functionality between the areas you need (selecting a region and saving the file) so that they work cleanly together...
The following example takes a screenshot, allows you to select an area, click save and the file will be saved. The example checks to see how many files are already in the current directory and increments the count by 1 so you are not overwriting the existing files...
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScreenImage {
public static void main(String[] args) {
new ScreenImage();
}
public ScreenImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final BufferedImage screen = robot.createScreenCapture(new Rectangle(screenSize));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane(screen));
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (AWTException exp) {
exp.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage master;
public TestPane(BufferedImage image) {
this.master = image;
setLayout(new BorderLayout());
final ImagePane imagePane = new ImagePane(image);
add(new JScrollPane(imagePane));
JButton btnSave = new JButton("Save");
add(btnSave, BorderLayout.SOUTH);
btnSave.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
BufferedImage img = imagePane.getSubImage();
master = append(master, img);
File save = new File("Capture.png");
ImageIO.write(master, "png", save);
imagePane.clearSelection();
JOptionPane.showMessageDialog(TestPane.this, save.getName() + " was saved", "Saved", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(TestPane.this, "Failed to save capture", "Error", JOptionPane.ERROR_MESSAGE);
}
}
public BufferedImage append(BufferedImage master, BufferedImage sub) {
// Create a new image which can hold both background and the
// new image...
BufferedImage newImage = new BufferedImage(
master.getWidth() + sub.getWidth(),
Math.max(master.getHeight(), sub.getHeight()),
BufferedImage.TYPE_INT_ARGB);
// Get new image's Graphics context
Graphics2D g2d = newImage.createGraphics();
// Draw the old background
g2d.drawImage(master, 0, 0, null);
// Position and paint the new sub image...
int y = (newImage.getHeight() - sub.getHeight()) / 2;
g2d.drawImage(sub, master.getWidth(), y, null);
g2d.dispose();
return newImage;
}
});
}
}
public class ImagePane extends JPanel {
private BufferedImage background;
private Rectangle selection;
public ImagePane(BufferedImage img) {
background = img;
MouseAdapter ma = new MouseAdapter() {
private Point clickPoint;
#Override
public void mousePressed(MouseEvent e) {
clickPoint = e.getPoint();
}
#Override
public void mouseDragged(MouseEvent e) {
Point dragPoint = e.getPoint();
int x = Math.min(clickPoint.x, dragPoint.x);
int y = Math.min(clickPoint.y, dragPoint.y);
int width = Math.abs(clickPoint.x - dragPoint.x);
int height = Math.abs(clickPoint.y - dragPoint.y);
selection = new Rectangle(x, y, width, height);
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public void clearSelection() {
selection = null;
repaint();
}
public BufferedImage getSubImage() {
BufferedImage img = null;
if (selection != null) {
img = background.getSubimage(selection.x, selection.y, selection.width, selection.height);
}
return img;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
if (selection != null) {
Color stroke = UIManager.getColor("List.selectionBackground");
Color fill = new Color(stroke.getRed(), stroke.getGreen(), stroke.getBlue(), 128);
g2d.setColor(fill);
g2d.fill(selection);
g2d.setColor(stroke);
g2d.draw(selection);
}
g2d.dispose();
}
}
}
So apart from rendering the selection the hardest part would be generating the resulting image...
Basically, this done by creating a new BufferedImage and painting the old image and the new, sub, image together.
public BufferedImage append(BufferedImage master, BufferedImage sub) {
// Create a new image which can hold both background and the
// new image...
BufferedImage newImage = new BufferedImage(
master.getWidth() + sub.getWidth(),
Math.max(master.getHeight(), sub.getHeight()),
BufferedImage.TYPE_INT_ARGB);
// Get new image's Graphics context
Graphics2D g2d = newImage.createGraphics();
// Draw the old background
g2d.drawImage(master, 0, 0, null);
// Position and paint the new sub image...
int y = (newImage.getHeight() - sub.getHeight()) / 2;
g2d.drawImage(sub, master.getWidth(), y, null);
g2d.dispose();
return newImage;
}
The example replaces the previous (master) image with the one created here, so it will constantly be appending new images to the end of it...
You need more listeners for button pressed and released.. some lines in the mouseMoved also better placed in mousePressed.
You would want to update your captureRect when you release the mouse (in mouseReleased method).
Then you just write it to the file. You may adjust other things according to your needs.
And for clarity maybe it's better to add a save button into your UI.
public class ScreenCaptureRectangle {
Rectangle captureRect;
Point start = new Point();
SimpleDateFormat sdf;
ScreenCaptureRectangle(final BufferedImage screen) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
final BufferedImage screenCopy = new BufferedImage(
screen.getWidth(),
screen.getHeight(),
screen.getType());
final JLabel screenLabel = new JLabel(new ImageIcon(screenCopy));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int) (screen.getWidth() / 3),
(int) (screen.getHeight() / 3)));
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
JButton btnSave = new JButton("SAVE");
btnSave.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
double w = captureRect.getWidth();
double h = captureRect.getHeight();
double x = captureRect.getX();
double y = captureRect.getY();
int W = (int) w;
int H = (int) h;
int X = (int) x;
int Y = (int) y;
BufferedImage selectImg = screen.getSubimage(X, Y, W, H);
try {
String fName = generateFileName();
if (fName != null) {
File f = new File(fName);
if (f.createNewFile()) {
ImageIO.write(selectImg, "jpg", f);
}
}
} catch (IOException ex) {
Logger.getLogger(ScreenCaptureRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
panel.add(btnSave, BorderLayout.AFTER_LAST_LINE);
final JLabel selectionLabel = new JLabel(
"Drag a rectangle in the screen shot!");
panel.add(selectionLabel, BorderLayout.SOUTH);
repaint(screen, screenCopy);
screenLabel.repaint();
screenLabel.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me) {
Point end = me.getPoint();
captureRect = new Rectangle(start,
new Dimension(end.x - start.x, end.y - start.y));
repaint(screen, screenCopy);
screenLabel.repaint();
selectionLabel.setText("Rectangle: " + captureRect);
}
});
screenLabel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
start = me.getPoint();
repaint(screen, screenCopy);
selectionLabel.setText("Start Point: " + start);
screenLabel.repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
int endX = me.getX();
int endY = me.getY();
if (endX > start.x && endY > start.y) {
captureRect = new Rectangle(start.x, start.y, endX-start.x, endY-start.y);
System.out.println("Rectangle of interest: " + captureRect);
}
}
});
JOptionPane.showMessageDialog(null, panel);
}
private String generateFileName() {
return new StringBuilder("screencrop_").append(sdf.format(new Date())).append(".jpg").toString();
}
public void repaint(BufferedImage orig, BufferedImage copy) {
Graphics2D g = copy.createGraphics();
g.drawImage(orig, 0, 0, null);
if (captureRect != null) {
g.setColor(Color.RED);
g.draw(captureRect);
g.setColor(new Color(255, 255, 255, 150));
g.fill(captureRect);
}
g.dispose();
}
public static void main(String[] args) throws Exception {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ScreenCaptureRectangle(screen);
}
});
}
}

Area generation not liking straight lines

I'm using the area generation and drawing code from Smoothing a jagged path to create collision areas for tile sprites in a JRPG game I'm making in java - Its not a major full blown game, more just a proof-of-concept for me to learn from.
The area generation works fine except for straight lines:
http://puu.sh/7wJA2.png
http://puu.sh/7wJGF.png
These images are of the collision outline opened in photoshop (in the background) vs the area that the java code is generating based on the red color (in the foreground). As can be seen, the large red line in the first image won't be draw unless I have a red pixel under it every 2 pixels, as shown in the second image.
I have made no changes to the code (other than adding comments in an attempt to better understand it) except to remove
Graphics2D g = imageOutline.createGraphics();
//...
g.dispose();
from the areaOutline draw code, replacing it with reference to my own Graphics2D variable. I tested the code both with and without those two lines and I couldn't see any difference.
I'm a bit stuck on what could be causing the issue - its not a major game-breaking issue, as I can fix it a couple of ways, but it does mean I have to explain this issue to anyone when showing them how to use it with their own sprite textures.
I've created a SSCCE of the issue - This shows the areas generated have vertical lines generated fine, but that horizontal ones are not. It takes two images - both a square 30x30 pixels, but one has internal pixels every 2 second pixel in which causes a more accurate area to be generated.
When you press a key the program will switch between the two images (and their areas), allowing for direct comparison.
The following two images must be put in the root folder of the program.
You can start the program by running the "main" method.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.io.*;
import javax.imageio.*;
public class AreaOutlineCanvas extends JFrame implements KeyListener
{
private ImagePanel imagePanel;
/**
* Constructor for objects of class Skeleton
*/
public AreaOutlineCanvas()
{
// initialise instance variables
addKeyListener( this );
initUI();
}
public static void main( String[] args )
{
for( String s: args )
{
System.out.println( s );
}
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
AreaOutlineCanvas aOC = new AreaOutlineCanvas();
aOC.pack();
aOC.setVisible( true );
aOC.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
} );
}
private void initUI()
{
imagePanel = new ImagePanel();
setPreferredSize( new Dimension( 100, 100 ) );
setLocationRelativeTo( null );
add( imagePanel );
imagePanel.setDoubleBuffered( true );
pack();
}
#Override
public void keyTyped( KeyEvent e )
{
}
#Override
public void keyPressed( KeyEvent e )
{
//#TODO: switch statment checking the menu Skeleton is in (currentMenu)
if( imagePanel != null )
{
imagePanel.bDrawingFirstArea = !imagePanel.bDrawingFirstArea;
imagePanel.repaint();
}
}
#Override
public void keyReleased(KeyEvent e)
{
//System.out.println( "Key released: " + e.getKeyChar() + " (" + e.getKeyCode() + ")" );
}
public class ImagePanel extends JPanel
{
/** Path for the location of this charactors sprite sheet */
private String firstPath = "square1.png";
private String secondPath = "square2.png";
private BufferedImage firstImage;
private BufferedImage secondImage;
private Area firstImageArea;
private Area secondImageArea;
public boolean bDrawingFirstArea = true;
/**
* Constructor for objects of class Character
*/
public ImagePanel()
{
loadImages();
generateAreas();
}
private void loadImages()
{
try
{
firstImage = ImageIO.read( new File( firstPath ) );
secondImage = ImageIO.read( new File( secondPath ) );
}
catch( IOException e )
{
e.printStackTrace();
}
}
private void generateAreas()
{
Color c = new Color( 255, 0, 0 );
firstImageArea = getOutline( c, firstImage );
secondImageArea = getOutline( c, secondImage );
}
public Area getOutline(Color target, BufferedImage bi) {
// construct the GeneralPath
GeneralPath gp = new GeneralPath();
boolean cont = false;
int targetRGB = target.getRGB();
for (int xx=0; xx<bi.getWidth(); xx++) {
for (int yy=0; yy<bi.getHeight(); yy++) {
if (bi.getRGB(xx,yy)==targetRGB) {
if (cont) {
gp.lineTo(xx,yy);
gp.lineTo(xx,yy+1);
gp.lineTo(xx+1,yy+1);
gp.lineTo(xx+1,yy);
gp.lineTo(xx,yy);
} else {
gp.moveTo(xx,yy);
}
cont = true;
} else {
cont = false;
}
}
cont = false;
}
gp.closePath();
// construct the Area from the GP & return it
return new Area(gp);
}
#Override
public void paintComponent( Graphics g )
{
super.paintComponent( g );
drawImages(g);
}
private void drawImages( Graphics g )
{
Graphics2D g2d = (Graphics2D) g;
if( bDrawingFirstArea )
{
g2d.drawImage( firstImage, 50, 0, this );
g2d.draw( firstImageArea );
}
else
{
g2d.drawImage( secondImage, 50, 0, this );
g2d.draw( secondImageArea );
}
Toolkit.getDefaultToolkit().sync();
}
}
}
For convenience I've posted the code from Smoothing a jagged path question here
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
/* Gain the outline of an image for further processing. */
class ImageOutline {
private BufferedImage image;
private TwoToneImageFilter twoToneFilter;
private BufferedImage imageTwoTone;
private JLabel labelTwoTone;
private BufferedImage imageOutline;
private Area areaOutline = null;
private JLabel labelOutline;
private JLabel targetColor;
private JSlider tolerance;
private JProgressBar progress;
private SwingWorker sw;
public ImageOutline(BufferedImage image) {
this.image = image;
imageTwoTone = new BufferedImage(
image.getWidth(),
image.getHeight(),
BufferedImage.TYPE_INT_RGB);
}
public void drawOutline() {
if (areaOutline!=null) {
Graphics2D g = imageOutline.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0,0,imageOutline.getWidth(),imageOutline.getHeight());
g.setColor(Color.RED);
g.setClip(areaOutline);
g.fillRect(0,0,imageOutline.getWidth(),imageOutline.getHeight());
g.setColor(Color.BLACK);
g.setClip(null);
g.draw(areaOutline);
g.dispose();
}
}
public Area getOutline(Color target, BufferedImage bi) {
// construct the GeneralPath
GeneralPath gp = new GeneralPath();
boolean cont = false;
int targetRGB = target.getRGB();
for (int xx=0; xx<bi.getWidth(); xx++) {
for (int yy=0; yy<bi.getHeight(); yy++) {
if (bi.getRGB(xx,yy)==targetRGB) {
if (cont) {
gp.lineTo(xx,yy);
gp.lineTo(xx,yy+1);
gp.lineTo(xx+1,yy+1);
gp.lineTo(xx+1,yy);
gp.lineTo(xx,yy);
} else {
gp.moveTo(xx,yy);
}
cont = true;
} else {
cont = false;
}
}
cont = false;
}
gp.closePath();
// construct the Area from the GP & return it
return new Area(gp);
}
public JPanel getGui() {
JPanel images = new JPanel(new GridLayout(2,2,2,2));
JPanel gui = new JPanel(new BorderLayout(3,3));
JPanel originalImage = new JPanel(new BorderLayout(2,2));
final JLabel originalLabel = new JLabel(new ImageIcon(image));
targetColor = new JLabel("Target Color");
targetColor.setForeground(Color.RED);
targetColor.setBackground(Color.WHITE);
targetColor.setBorder(new LineBorder(Color.BLACK));
targetColor.setOpaque(true);
JPanel controls = new JPanel(new BorderLayout());
controls.add(targetColor, BorderLayout.WEST);
originalLabel.addMouseListener( new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent me) {
originalLabel.setCursor(
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
#Override
public void mouseExited(MouseEvent me) {
originalLabel.setCursor(Cursor.getDefaultCursor());
}
#Override
public void mouseClicked(MouseEvent me) {
int x = me.getX();
int y = me.getY();
Color c = new Color( image.getRGB(x,y) );
targetColor.setBackground( c );
updateImages();
}
});
originalImage.add(originalLabel);
tolerance = new JSlider(
JSlider.HORIZONTAL,
0,
255,
104
);
tolerance.addChangeListener( new ChangeListener() {
public void stateChanged(ChangeEvent ce) {
updateImages();
}
});
controls.add(tolerance, BorderLayout.CENTER);
gui.add(controls,BorderLayout.NORTH);
images.add(originalImage);
labelTwoTone = new JLabel(new ImageIcon(imageTwoTone));
images.add(labelTwoTone);
images.add(new JLabel("Smoothed Outline"));
imageOutline = new BufferedImage(
image.getWidth(),
image.getHeight(),
BufferedImage.TYPE_INT_RGB
);
labelOutline = new JLabel(new ImageIcon(imageOutline));
images.add(labelOutline);
updateImages();
progress = new JProgressBar();
gui.add(images, BorderLayout.CENTER);
gui.add(progress, BorderLayout.SOUTH);
return gui;
}
private void updateImages() {
if (sw!=null) {
sw.cancel(true);
}
sw = new SwingWorker() {
#Override
public String doInBackground() {
progress.setIndeterminate(true);
adjustTwoToneImage();
labelTwoTone.repaint();
areaOutline = getOutline(Color.BLACK, imageTwoTone);
drawOutline();
return "";
}
#Override
protected void done() {
labelOutline.repaint();
progress.setIndeterminate(false);
}
};
sw.execute();
}
public void adjustTwoToneImage() {
twoToneFilter = new TwoToneImageFilter(
targetColor.getBackground(),
tolerance.getValue());
Graphics2D g = imageTwoTone.createGraphics();
g.drawImage(image, twoToneFilter, 0, 0);
g.dispose();
}
public static void main(String[] args) throws Exception {
int size = 150;
final BufferedImage outline =
new BufferedImage(size,size,BufferedImage.TYPE_INT_RGB);
Graphics2D g = outline.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0,0,size,size);
g.setRenderingHint(
RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Polygon p = new Polygon();
p.addPoint(size/2, size/10);
p.addPoint(size-10, size-10);
p.addPoint(10, size-10);
Area a = new Area(p);
Rectangle r = new Rectangle(size/4, 8*size/10, size/2, 2*size/10);
a.subtract(new Area(r));
int radius = size/10;
Ellipse2D.Double c = new Ellipse2D.Double(
(size/2)-radius,
(size/2)-radius,
2*radius,
2*radius
);
a.subtract(new Area(c));
g.setColor(Color.BLACK);
g.fill(a);
ImageOutline io = new ImageOutline(outline);
JFrame f = new JFrame("Image Outline");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(io.getGui());
f.pack();
f.setResizable(false);
f.setLocationByPlatform(true);
f.setVisible(true);
}
}
class TwoToneImageFilter implements BufferedImageOp {
Color target;
int tolerance;
TwoToneImageFilter(Color target, int tolerance) {
this.target = target;
this.tolerance = tolerance;
}
private boolean isIncluded(Color pixel) {
int rT = target.getRed();
int gT = target.getGreen();
int bT = target.getBlue();
int rP = pixel.getRed();
int gP = pixel.getGreen();
int bP = pixel.getBlue();
return(
(rP-tolerance<=rT) && (rT<=rP+tolerance) &&
(gP-tolerance<=gT) && (gT<=gP+tolerance) &&
(bP-tolerance<=bT) && (bT<=bP+tolerance) );
}
public BufferedImage createCompatibleDestImage(
BufferedImage src,
ColorModel destCM) {
BufferedImage bi = new BufferedImage(
src.getWidth(),
src.getHeight(),
BufferedImage.TYPE_INT_RGB);
return bi;
}
public BufferedImage filter(
BufferedImage src,
BufferedImage dest) {
if (dest==null) {
dest = createCompatibleDestImage(src, null);
}
for (int x=0; x<src.getWidth(); x++) {
for (int y=0; y<src.getHeight(); y++) {
Color pixel = new Color(src.getRGB(x,y));
Color write = Color.BLACK;
if (isIncluded(pixel)) {
write = Color.WHITE;
}
dest.setRGB(x,y,write.getRGB());
}
}
return dest;
}
public Rectangle2D getBounds2D(BufferedImage src) {
return new Rectangle2D.Double(0, 0, src.getWidth(), src.getHeight());
}
public Point2D getPoint2D(
Point2D srcPt,
Point2D dstPt) {
// no co-ord translation
return srcPt;
}
public RenderingHints getRenderingHints() {
return null;
}
}

Call JDialog from JDialog

I'm trying to build an application, in which allows calling JDialog from JDialog. I've tried it, but at the time of the call dialog B of A, B dialog appears and then immediately disappears. Is there a solution to these problems?
My code :
I have a class A which extends javax.swing.JDialog. Then there is a label that has the action to call dialog from class PadAndZoom as below:
private void lblSuratRekomendasiMouseClicked(java.awt.event.MouseEvent evt) {
try {
PadAndZoom app = new PadAndZoom();
BufferedImage img = ImageIO.read(PadAndZoom.class.getResource("/tampilan/background5.jpg"));
app.tes(img);
} catch (IOException ex) {
Logger.getLogger(RincianBukuBesar.class.getName()).log(Level.SEVERE, null, ex);
}
}
then I have one more class to be invoked by the method lblSuratRekomendasiMouseClicked (java.awt.event.MouseEvent evt) of class A
package dispertasih;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class PadAndZoom implements ChangeListener {
BufferedImage image;
PanPanelX label;
public void stateChanged(ChangeEvent e) {
int value = ((JSlider) e.getSource()).getValue();
double scale = value / 200.0;
BufferedImage scaled = getScaledImage(scale);
label.setImage(scaled);
}
public BufferedImage getScaledImage(double scale) {
int w = (int)(scale*image.getWidth());
int h = (int)(scale*image.getHeight());
BufferedImage bi = new BufferedImage(w, h, image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
g2.drawRenderedImage(image, at);
g2.dispose();
return bi;
}
public PanPanelX getContent() {
// createAnImage();
label = new PanPanelX(image);
//label.setHorizontalAlignment(JLabel.CENTER);
return label;
}
public void createAnImage(BufferedImage imgbuf) {
int w = 500;
int h = 500;
int type = BufferedImage.TYPE_INT_RGB; // many options
image = imgbuf;
}
public JSlider getControl() {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 50, 200, 50);
slider.setMajorTickSpacing(50);
slider.setMinorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(this);
return slider;
}
public void tes(BufferedImage img) {
PadAndZoom app = new PadAndZoom();
JDialog f = new JDialog();
JButton b = new JButton();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) { }
app.createAnImage(img);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.getContentPane().add(new JScrollPane(app.getContent()));
//f.getContentPane().add(new JButton("tessss"));
f.getContentPane().add(app.getControl(), "Last");
f.setSize(400, 400);
f.setLocation(200,200);
f.setVisible(true);
}
}
class PanPanelX extends JPanel {
public int x, y;
public int width = 800, height = 800;
BufferedImage img;
public final static RenderingHints textRenderHints = new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
public final static RenderingHints imageRenderHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
public final static RenderingHints renderHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
static int startX, startY;
public void setImage(BufferedImage img) {
this.img = img;
revalidate();
repaint();
}
public PanPanelX(BufferedImage img) {
x = 20;
y = 20;
this.img = img;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent me) {
super.mousePressed(me);
startX = me.getX();
startY = me.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me) {
super.mouseDragged(me);
if (me.getX() < startX) {//moving image to right
x -= 2;
} else if (me.getX() > startX) {//moving image to left
x += 2;
}
if (me.getY() < startY) {//moving image up
y -= 2;
} else if (me.getY() > startY) {//moving image to down
y += 2;
}
repaint();
}
});
}
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
//turn on some nice effects
applyRenderHints(g2d);
g2d.drawImage(img, x, y, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public static void applyRenderHints(Graphics2D g2d) {
g2d.setRenderingHints(textRenderHints);
g2d.setRenderingHints(imageRenderHints);
g2d.setRenderingHints(renderHints);
}
}
thanks u ..

Component with transparent background to BufferedImage?

I have a component extends JPanel. It saves itself as bufferedimage on every call of paintComponent method. Component is not completely transparent, only its background. Problem is background is not transparent. I am using setOpaque(false);
Here is my relevant code;
private BufferedImage bufImage = null;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// if first time call
if (bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
bufImage = (BufferedImage)this.createImage(w, h);
}
g2.drawImage(bufImage, null, 0, 0);
// draw sth
g2.draw(sth);
}
--
I also tried
bufImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
instead of
bufImage = (BufferedImage)this.createImage(w, h);
When i do that; background transperancy works but i can only draw with white color. I have no idea what causes that.
Note:
I used that code to check if it is working;
File outputfile = new File("saved.png");
ImageIO.write(bufImage, "png", outputfile);
saved.png had transparent background but drawings were only white.
This is the component, only lets drawing rectangle with mouse;
class PaintPanel extends JPanel implements MouseListener, MouseMotionListener {
private BufferedImage _bufImage = null;
private boolean dragging = false;
private Point _start = null, _end = null;
public PaintPanel() {
setOpaque(false);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
if (_bufImage == null) {
int w = this.getWidth();
int h = this.getHeight();
_bufImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
//_bufImage = (BufferedImage)this.createImage(w, h);
}
g2.drawImage(_bufImage, null, 0, 0);
if (dragging) {
drawCurrentShape(g2);
}
}
private void drawCurrentShape(Graphics2D g2) {
int startx = (int) _start.getX();
int starty = (int) _start.getY();
int stopx = (int) _end.getX();
int stopy = (int) _end.getY();
int width = Math.abs(startx - stopx);
int height = Math.abs(starty - stopy);
int x = startx, y = starty;
if(x > stopx)
x = stopx;
if(y > stopy)
y = stopy;
Rectangle r = new Rectangle(x, y, width, height);
g2.draw(r);
}
public void mousePressed(MouseEvent e) {
dragging = true;
_start = e.getPoint();
_end = _start;
}
public void mouseDragged(MouseEvent e) {
_end = e.getPoint();
this.repaint();
}
public void mouseReleased(MouseEvent e) {
_end = e.getPoint();
if (dragging) {
dragging = false;
drawCurrentShape(_bufImage.createGraphics());
this.repaint();
}
}
public void mouseMoved (MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited (MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
}
try this:
bufImage = new BufferedImage(w,h,java.awt.image.BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufImage.createGraphics();
this.print(graphics);
graphics.dispose();
The key is to use print()
Edit: I tried the following and transparency works like a charm:
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test2 {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel p = new JPanel();
p.setPreferredSize(new Dimension(400, 400));
p.setOpaque(false);
JButton button = new JButton("Hello world");
p.add(button);
frame.add(p);
frame.pack();
frame.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
BufferedImage bufImage = new BufferedImage(p.getWidth(), p.getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufImage.createGraphics();
p.print(graphics);
graphics.dispose();
try {
ImageIO.write(bufImage, "png", new File("d:/tmp/tmp.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
createImage(w, h) will create a "blank" image with the specified width and height. That being said, what you'll need to do is invoke createGraphics on the BufferedImage instance and draw directly to the returned Graphics object.

Categories

Resources