Upload
candace-welch
View
214
Download
0
Embed Size (px)
Citation preview
CSE 219 Computer Science III
Image Manipulation
HW 1
• Has been posted on Blackboard
http://blackboard.stonybrook.edu/
• Making a Game of Life with limited options
We know how to draw an image
• What else do we need to do?– listen for & handle mouse clicks– resize (maybe)– get color values of individual pixels– change individual pixels
MouseEvents
• Generated by low-level mouse interactions– mouse clicking, mouse moving, mouse dragging
• Handled by 2 different listener interfaces– MouseListener: handles mouse clicks
•mousePressed, mouseReleased, mouseClicked, mouseEntered, mouseExited
– MouseMotionListener: handles mouse movement•mouseMoved, mouseDragged
MouseEvents generated by mouse clicks where?
• On our panel (not our buttons)– why not our buttons?
• Example, make an application that:– draws the map– when one clicks on the map, the x, y coordinates are
drawn in the bottom left corner– we’ll call it MapPixelDisplayer
public class MapPixelDisplayer extends JPanel implements MouseListener {
private Image image;private int id = 0;private String coords = "";
public MapPixelDisplayer(String file) {loadMap(file);this.addMouseListener(this);
}
private void loadMap(String file) {Toolkit tk = Toolkit.getDefaultToolkit();image = tk.getImage(file);MediaTracker tracker = new MediaTracker(this);tracker.addImage(image,id);try { tracker.waitForID(id); }catch (InterruptedException ie) {
// BOO! ERROR}
}
public void paintComponent(Graphics g) {super.paintComponent(g);g.drawImage(image, 0, 0,
getWidth(), getHeight(), null);
g.drawString(coords, 10, getHeight()-10);}
public void mouseClicked(MouseEvent me) {coords = me.getX() + "," + me.getY();this.repaint();
}
public void mousePressed(MouseEvent me) {}public void mouseReleased(MouseEvent me) {}public void mouseEntered(MouseEvent me) {}public void mouseExited(MouseEvent me) {}
}
Remember the second catch with images
• So far, we have drawn the image automatically to fit panel
• How did we size the panel?– we didn’t the panel’s LayoutManager did
• How can we get the size of the panel?– getWidth & getHeight methods– WARNING: you’ll only get this information after the
layout managers have sized everything• Why?
– so when can we get this info?• as soon as the panel’s paintComponent method is called
for the first time
Scaling an image
• Do only the first time paintComponent is called
• Use getScaledInstance from the Image class– scale it to your desired width & height
• fit the panel– scaling factors in Image class (ex: Image.SCALE_DEFAULT)
– scaling also done asynchronously• use MediaTracker class
public class ImageScalingExample extends JPanel {…private boolean panelSized = false;…private void scaleImage(int w, int h) {
image = image.getScaledInstance(w,h,Image.SCALE_DEFAULT);
MediaTracker tracker = new MediaTracker(this);tracker.addImage(image, id);try {tracker.waitForID(id);}catch (InterruptedException ie) { // ERROR }
}
public void paintComponent(Graphics g) {super.paintComponent(g);if (!panelSized) {
scaleImage(getWidth(), getHeight());panelSized = true;
}g.drawImage(image, 0, 0, image.getWidth(null),
image.getHeight(null), null);}
For images so far
• We can load
• We can render
• We can scale
• Now we want to edit them
• Note, for Risk game, simple Images won’t get it done, you’ll have to use the BufferedImage class– provides direct access to pixel data
java.awt.image.BufferedImage
• An image class that provides access to image data
• Has 3 important components:– ColorModel – stores info about format of image– Raster – stores image data– Graphics – allows us to “draw” data into object (fill raster)
Loading a BufferedImage from an Image
BufferedImage bImage = new BufferedImage(
image.getWidth(null), image.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics bImageG = bImage.getGraphics();
bImageG.drawImage(image, null, null);
• Now, you may draw your BufferedImage inside paintComponent using the drawImage method
NOTE: this is not drawing anything to the screen. So what is it doing?
Raster
• Image pixel data is stored in a single-dimensional array– width * height indices
• This array is called the Raster
• Each array cell stores pixel color
• Access each pixel via an array index
• Pixel in top row, left column is index 0
• Pixel at (x, y) of image is index (y * width) + x
Accessing Image Pixel Info• Get pixel data from Raster object
– use getRaster from BufferedImage class– use getDataElements from Raster class to access
data for a specific pixel
• Get image format data from ColorModel object – needed to translate pixel data into a Color– use getRGB method and Color constructor to convert
data into a Color– use getRed, getGreen, & getBlue methods from Color class
Changing the pixels of a BufferedImage
• use DataBuffer’s setElem method
• For getting & setting pixels, some necessary converting between Colors and ints
DumbMapPixelEraser
• Let’s make a program that will do the following:– draw our map inside a panel– When a user clicks a mouse on the map, 2 things will
happen:• the pixel color of the map at that location will be written in
the lower left of the map
• the pixel at that location of the map will be turned white
public class DumbMapPixelEraser extends JPanel implements MouseListener {
…private BufferedImage bImage;private String oldPixelColor = "";…public void loadBImage() {
bImage = new BufferedImage(image.getWidth(null),image.getHeight(null),BufferedImage.TYPE_INT_RGB);
Graphics bImageG = bImage.getGraphics();bImageG.drawImage(image, 0,0,null, null);
}…
public void erasePixel(int x, int y) {// GET THE OLD COLOR TO DISPLAYRaster raster = bImage.getRaster();Object data = raster.getDataElements(x, y,
null);ColorModel model = bImage.getColorModel();int rgb = model.getRGB(data);Color color = new Color(rgb);oldPixelColor = color.toString();
// CHANGE COLOR OF PIXEL TO WHITEDataBuffer db = raster.getDataBuffer();Color white = Color.WHITE;int whiteInt = white.getRGB();int index = (y * raster.getWidth()) + x;db.setElem(index, whiteInt);
}
public void paintComponent(Graphics g) {super.paintComponent(g);if (!panelSized) {
scaleImage(getWidth(), getHeight());loadBImage();panelSized = true;
}g.drawImage(bImage, 0, 0, image.getWidth(null),
image.getHeight(null), null);g.drawString("Old Pixel Color: " + oldPixelColor,
10, getHeight()-10);}
public void mouseClicked(MouseEvent me) {erasePixel(me.getX(), me.getY());repaint();
}public void mousePressed(MouseEvent me) {}public void mouseReleased(MouseEvent me) {}public void mouseEntered(MouseEvent me) {}public void mouseExited(MouseEvent me) {}
}
BetterMapPixelEraser
• Let’s change our program to do the following:– draw our map inside a panel– when a user drags a mouse on the map, 2 things will
happen:• the pixel color of the map at that location will be written in
the lower left of the map
• the pixel at that location of the map will be turned white
• Still not so great (brush diameter of 1 pixel)
public class BetterMapPixelEraser extends JPanel
implements MouseMotionListener {
…
public BetterMapPixelEraser(String file) {
loadMap(file);
this.addMouseMotionListener(this);
}
…
public void mouseDragged(MouseEvent me) {
erasePixel(me.getX(), me.getY());
repaint();
}
public void mouseMoved(MouseEvent me) {}
Risk Image Manipulation
• How are we going to combine these tools?
• Implementing Risk involves: – render map with army quantities– change map to assign ownership of territories– determine territory selection via a mouse click