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?
Asked
Active
Viewed 723 times
0
-
1I think you are better off having the image as an image all along. Here is a [close equivalent](http://stackoverflow.com/questions/12683533/drawing-a-rectangle-that-wont-disappear-in-next-paint/12683632#12683632) of what you are trying to do, using a `BufferedImage` as the painting surface. If you like that approach I can put it here as an answer. OTOH - see also [`ComponentImageCapture`](http://stackoverflow.com/a/5853992/418556) which does more literally what you are trying to do. – Andrew Thompson Oct 16 '12 at 04:12
1 Answers
0
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.

MadProgrammer
- 343,457
- 22
- 230
- 366
-
Did you mean to declare the second BufferedImage as image instead of bwImage? Because later you use the variable name image to reference that image. Also, I tried this code, however when I display this new image to the screen I get a completely black screen, instead of black where I drew something and white everywhere else. To do this I used the command "g.drawImage(image,0,0,null);" where g is my Graphics object. Is this correct? – Nate Oct 18 '12 at 19:05
-
Firstly, I've updated the code to correct the reference errors, my mistake, sorry. Secondly, it depends, I'm assuming you've drawn directly to the applet's graphics context (overriding one of the `paint` methods). If you've used a backing buffer then you should be ale to skip the first step and use that directly. If you've used `getGraphics` then you're in trouble – MadProgrammer Oct 18 '12 at 20:04
-
I'v both overridden the paint method and called getGraphics throughout my code. What is the problem with using getGraphics? An additional comment, I have analyzed the pixel values when I use the above code and not a single value is a 1. – Nate Oct 18 '12 at 21:05
-
GetGraphics is a snap shot of the graphics context from the last paint cycle, it will be overridden during the next paint cycle. My example works on the premise that all painting is done via the paint methods and injected via the getGraphics method – MadProgrammer Oct 18 '12 at 21:11
-
No offence, but you're not providing use with enough context, do you gave some sample code? – MadProgrammer Oct 18 '12 at 21:13