Draw a rectangle over image in Java - java

I am trying to draw a rectangle over Image using java.awt classes. For that I used below sample code:
public class DrawRectangle {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setVisible(true);
}
});
}
}
class TestPane extends JPanel {
private BufferedImage myImage;
private Rectangle myOffice = new Rectangle(150, 50, 30, 20);
public TestPane() {
try {
File image = new File("C:\\Users\\NNaphade\\work\\ImageDetection\\Trial_Pascal_VOC\\test_image\\IMG_20180327_110210.jpg");
if(image.exists())
myImage = ImageIO.read(image);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
System.out.println("image exist!!!!!!");
return myImage == null ? new Dimension(200, 200) : new Dimension(
myImage.getWidth(), myImage.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (myImage != null) {
g2d.drawImage(myImage, 0, 0, 1000, 1000, this);
g2d.setColor(Color.RED);
g2d.translate(0, 0);
g2d.draw(myOffice);
}
g2d.dispose();
}
}
This works correct and output is displayed as expected. Here I am fixing the parameters for rectangle as:
private Rectangle myOffice = new Rectangle(150, 50, 30, 20);
However, in my application, I want to pass these parameters from another method. I want to pass these x1, y1, w and h to TestPane class given above. I tried changing the TestPane constructor by passing these 4 parameters, but I am not able to set them as instance variables. E.g. the following code doesn't work.
private void markWithBoundingBox(INDArray testData, int gridWidth, int gridHeight, double w, double h, DetectedObject obj) {
double[] xy1 = obj.getTopLeftXY();
int predictedClass = obj.getPredictedClass();
int x1 = (int) Math.round(w * xy1[0] / gridWidth);
int y1 = (int) Math.round(h * xy1[1] / gridHeight);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane(x1, y1, w, h));
frame.pack();
frame.setVisible(true);
}
});
}
class TestPane extends JPanel {
private BufferedImage myImage;
//private Rectangle myOffice = new Rectangle(50, 50, 3, 20);
public TestPane(int x, int y, double w, double h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
try {
File file = new File("C:\\Users\\NNaphade\\work\\ImageDetection\\Trial_Pascal_VOC\\test_image\\IMG_20180327_110210.jpg");
if(file.exists()) {
myImage = ImageIO.read(file);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return myImage == null ? new Dimension(100, 100) : new Dimension(
myImage.getWidth(), myImage.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (myImage != null) {
g2d.drawImage(myImage, 0, 0, 2000, 2000, this);
g2d.setColor(Color.RED);
g2d.translate(0, 0);
g2d.draw(new Rectangle(this.x, this.y, this.w, this.h));
}
g2d.dispose();
}
}
It seems to me that TestPane here is not a class but the component. because Java compiler doesn't let me declare the instance variables in the constructor and all the available methods there are of component. How can I get rid of this issue?

Related

Wrap image to Jframe

I'm trying to get my Jframe to match my image dimensions exactly, so that when i attempt to get the Rectangle2D co-ordinates of an area via drawing a rectangle, it's give me the true co-ordinates of where it would appear on the actual image.
The objective with this solution is to convert a PDF to a image, identify a particular area using the visual mapper and then use PDFBox (PDFTextStripperbyArea) to extract against this area.
The co-ordinates being given by the below code is not extracting the required area's.
This is the code:
public class PDFVisualMapper extends JFrame {
BufferedImage image = null;
public static void main(String[] args) throws IOException {
new PDFVisualMapper();
}
public PDFVisualMapper() throws IOException {
this.setSize(1700, 2200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new PaintSurface(), BorderLayout.CENTER);
this.setVisible(true);
}
private class PaintSurface extends JComponent {
ArrayList<Shape> shapes = new ArrayList<Shape>();
Point startDrag, endDrag;
public PaintSurface() throws IOException {
image = ImageIO.read(new File("C:\\Users\\Rusty\\Desktop\\temp\\Test_PDF-1.png"));
if ( image != null ) {
Dimension size = new Dimension(image.getWidth(null), image.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
startDrag = new Point(e.getX(), e.getY());
endDrag = startDrag;
repaint();
}
public void mouseReleased(MouseEvent e) {
Shape r = makeRectangle(startDrag.x, startDrag.y, e.getX(), e.getY());
shapes.add(r);
startDrag = null;
endDrag = null;
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
endDrag = new Point(e.getX(), e.getY());
repaint();
}
});
}
private void paintBackground(Graphics2D g2) {
g2.setPaint(Color.LIGHT_GRAY);
for (int i = 0; i < getSize().width; i += 10) {
Shape line = new Line2D.Float(i, 0, i, getSize().height);
g2.draw(line);
}
for (int i = 0; i < getSize().height; i += 10) {
Shape line = new Line2D.Float(0, i, getSize().width, i);
g2.draw(line);
}
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
paintBackground(g2);
Color[] colors = { Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.RED, Color.BLUE, Color.PINK };
int colorIndex = 0;
g2.drawImage(image, null, 0, 0);
g2.setStroke(new BasicStroke(2));
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.50f));
for (Shape s : shapes) {
g2.setPaint(Color.BLACK);
g2.draw(s);
g2.setPaint(colors[(colorIndex++) % 6]);
g2.fill(s);
}
if (startDrag != null && endDrag != null) {
g2.setPaint(Color.LIGHT_GRAY);
Shape r = makeRectangle(startDrag.x, startDrag.y, endDrag.x, endDrag.y);
g2.draw(r);
System.out.println(r.getBounds2D());
}
}
}
private Rectangle2D.Float makeRectangle(int x1, int y1, int x2, int y2) {
return new Rectangle2D.Float(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
}
}
Can anybody help?
This might be simpler: using a JLabel within the contentpane, using FlowLayout:
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class WarpImage {
public static void main(String[] args) throws IOException {
displayImage();
}
private static void displayImage() throws IOException{
URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
BufferedImage image = ImageIO.read(url);
ImageIcon icon= new ImageIcon(image);
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JLabel lbl= new JLabel();
lbl.setIcon(icon);
frame.add(lbl);
frame.pack();
//check size :
Rectangle bounds = lbl.getBounds();
System.out.println(bounds.getWidth() +"-"+ bounds.getHeight());
frame.setVisible(true);
}
}
I'm trying to get my Jframe to match my image dimensions exactly, so that when i attempt to get the Rectangle2D co-ordinates of an area via drawing a rectangle, it's give me the true co-ordinates of where it would appear on the actual image.
Then you paint the image yourself. Why? Because components like JLabel have their own internal layout mechanics which provide no way for you to determine the offset of the image within in, if the image is to large or to small for the component size.
Something like this, for example:
public class ImagePane extends JPanel {
private BufferedImage img;
public ImagePane(BufferedImage img) {
this.img = img;
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(0, 0) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2 = (Graphics2D) g.create();
g2.drawImage(img, 0, 0, this);
g2.dispose();
}
}
}
This places the image in the top left corner of the component, so if it's resized for some reason, the image will always be in the top left position. To be frank, it wouldn't be hard to generate an offset to allow the image to be centred, this could then be used by decedents of the component to calculate the offset required to adjust their own output as needed

Java run slowly when animatio many of images

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);
}
}

Rotating text in Java2D on Mac

Here is the problem I am currently facing: I want to draw a String on a JPanel using Java2D. The String has to be rotated of a user-defined angle.
Under that String, I also paint the background in a given color to facilitate reading (plenty of other things are drawn on my JPanel).
What I did, in the overridden paint method of my JPanel, is the following:
final Graphics2D g2 = (Graphics2D) g.create();
final int textWidth = g.getFontMetrics().stringWidth(textToDraw);
final int textHeight = g.getFontMetrics().getHeight();
g2.translate(pointToDraw.x, pointToDraw.y);
g2.rotate(angle);
g2.setColor(textBackground);
g2.fillRect(deltaX, -textHeight, textWidth, textHeight);
g2.setColor(drawColor);
g2.setFont(font);
g2.drawString(textToDraw, deltaX, deltaY);
g2.dispose();
This works very well on linux, but on Mac OS X (with Java 1.6), the text is not displayed properly: the text is correctly rotated but after each character, there is a line break.
How can I make it work on both platforms?
I don't think this is the solution you will want, but from everything I've been able to read, there doesn't seem to be a better solution...
The problem seems to be that the Mac is rotating each character, not just the String
Basically, I've cheated. This renders the text to a BufferedImage (you should create the image only when the properties change, unlike me, which I've done it within the paint method) and then rotates the image...
public class RotateText {
public static void main(String[] args) {
new RotateText();
}
public RotateText() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private String textToDraw = "Stack Overflow";
private double angle = 90;
private Color drawColor = Color.BLACK;
public TestPane() {
Timer timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angle += 2;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D g2 = (Graphics2D) g.create();
FontMetrics fm = g2.getFontMetrics();
int textWidth = fm.stringWidth(textToDraw);
int textHeight = fm.getHeight();
BufferedImage img = new BufferedImage(textWidth, textHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig = img.createGraphics();
ig.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
ig.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
ig.setColor(drawColor);
ig.drawString(textToDraw, 0, fm.getAscent());
ig.dispose();
int x = (getWidth() - textWidth) / 2;
int y = (getHeight() - textHeight) / 2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setTransform(AffineTransform.getRotateInstance(Math.toRadians(angle), getWidth() / 2, getHeight() / 2));
g2.drawImage(img, x, y, this);
g2.dispose();
}
}
}

Flipping shape (not image)

Solved:
Thanks #MadProgrammer
I replaced g2.rotate(Math.toRadians(180.0)); by g2.scale(1, -1); thanks^^
I wrote program to show Digital Clock with mirror (Vertical Flip)
This is my code
import java.awt.*;
import java.awt.font.GlyphVector;
import javax.swing.*;
import java.util.*;
public class DigitalClock extends JFrame implements Runnable {
/**
* #author HASSAN
*/
Thread runner; // declare global objects
Font clockFont;
Shape mirror;
public DigitalClock() {
super("Digital Clock - Hassan Sharaf 12MCMB33");
setSize(600, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false); // create window
setLocationRelativeTo(null);
clockFont = new Font("digifacewide", Font.BOLD, 100); // create font
Container contentArea = getContentPane();
ClockPanel timeDisplay = new ClockPanel();
contentArea.add(timeDisplay); // add components
setContentPane(contentArea);
start(); // start thread running
}
public class ClockPanel extends JPanel {
public void paintComponent(Graphics painter) {
// super.paintComponent(painter);
Graphics2D g2 = (Graphics2D) painter;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setFont(clockFont); // create clock components
g2.setColor(Color.black);
g2.drawString(timeNow(), 20, 140);
GlyphVector v = clockFont.createGlyphVector(getFontMetrics(clockFont).getFontRenderContext(), timeNow());
mirror = v.getOutline();
g2.translate(553, 160);
g2.rotate(Math.toRadians(180.0));
g2.fill(mirror);
g2.draw(mirror);
}
}
// get current time
public String timeNow() {
Calendar now = Calendar.getInstance();
int hrs = now.get(Calendar.HOUR_OF_DAY);
int min = now.get(Calendar.MINUTE);
int sec = now.get(Calendar.SECOND);
String time = zero(hrs) + ":" + zero(min) + ":" + zero(sec);
return time;
}
public String zero(int num) {
String number = (num < 10) ? ("0" + num) : ("" + num);
return number; // Add leading zero if needed
}
public void start() {
if (runner == null) {
runner = new Thread(this);
}
runner.start();
// method to start thread
}
public void run() {
while (runner == Thread.currentThread()) {
repaint();
// define thread task
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread failed");
}
}
}
// create main method
public static void main(String[] args) {
DigitalClock clock = new DigitalClock();
}
}
Problem: I used rotate() method, but actually I don't want rotate the clock I want flip it vertically
Question: How can I flip the shape (not image)?
You have lots-o-choices depending on what you want to achieve...
You can...
Create a PathIterator from the shape object, using a AffineTransform matching your rotational requirements. This will require you to create a new path, appending the PathIterator to it so you can paint it ... or
Create a new Path2D using the shape to be rotated as the base for the new path and passing the AffineTransform to it. This is pretty much the same as the first option, but requires less code...
Here's an example....
public class SpinningTriangle {
public static void main(String[] args) {
new SpinningTriangle();
}
public SpinningTriangle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SpinPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SpinPane extends JPanel {
private Triangle triangle;
private float angle = 0;
public SpinPane() {
triangle = new Triangle(50, 100);
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angle += 2;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(110, 110);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = triangle.getBounds();
// PathIterator pi = triangle.getPathIterator(AffineTransform.getRotateInstance(Math.toRadians(angle), bounds.width / 2, bounds.height / 2));
// Path2D path = new Path2D.Float();
// path.append(pi, true);
Path2D path = new Path2D.Float(triangle, AffineTransform.getRotateInstance(Math.toRadians(angle), bounds.width / 2, bounds.height / 2));
int x = (getWidth() - bounds.width) / 2;
int y = (getHeight() - bounds.height) / 2;
g2d.translate(x, y);
g2d.setColor(Color.RED);
g2d.fill(path);
g2d.setColor(Color.YELLOW);
g2d.draw(path);
g2d.dispose();
}
}
public class Triangle extends Path2D.Float {
public Triangle(int width, int height) {
moveTo(width / 2f, 0);
lineTo(width, height);
lineTo(0, height);
closePath();
}
}
}
UPDATED
If all you want to do is "mirror" the shape, you can scale the axis by -1...
public class SpinningTriangle {
public static void main(String[] args) {
new SpinningTriangle();
}
public SpinningTriangle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new FlipPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class FlipPane extends JPanel {
private Triangle triangle;
private boolean flip;
public FlipPane() {
triangle = new Triangle(50, 100);
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
flip = !flip;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(110, 110);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = triangle.getBounds();
double scale = flip ? -1 : 1;
Path2D path = new Path2D.Float(triangle, AffineTransform.getScaleInstance(scale, scale));
int x = (getWidth() - bounds.width) / 2;
int y = (getHeight() - bounds.height) / 2;
if (flip) {
y += bounds.height;
x += bounds.width;
}
g2d.translate(x, y);
g2d.setColor(Color.RED);
g2d.fill(path);
g2d.setColor(Color.YELLOW);
g2d.draw(path);
g2d.dispose();
}
}
public class Triangle extends Path2D.Float {
public Triangle(int width, int height) {
moveTo(width / 2f, 0);
lineTo(width, height);
lineTo(0, height);
closePath();
}
}
}

Convert java applet to black and white image

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.

Categories