Computer Science 15-110, Spring 2010
Class Notes:  Graphics, Color, and Polygon Methods


  1. Display a Graphics Window (reminder)
  2. Graphics Methods
    1. drawLine
    2. setLineThickness (helper method)
    3. fillRect
    4. drawRect
    5. fillOval
    6. drawOval
    7. fillRoundRect
    8. drawRoundRect
    9. fillArc
    10. drawArc
    11. fillPolygon
    12. drawPolygon
    13. drawString
    14. drawCenteredString (helper method)
      (and getStringWidth, getStringHeight, and getStringAscent)
    15. setFont
    16. Online Graphics API
  3. Image Helper Methods
    1. Image Helper Methods
      1. drawImage
      2. drawCenteredImage
      3. getImageSize
      4. loadBufferedImage
      5. saveBufferedImage
    2. Image Helper Code
    3. Example:  Draw Images
    4. Example:  Edit Image Files
  4. Color Methods
    1. Construct RGB Color
    2. Construct RGBA Color
    3. equals
    4. brighter
    5. darker
    6. getRed, getGreen, getBlue, and getAlpha
    7. Online Color API
  5. Polygon Methods
    1. getBounds
    2. contains
    3. translate
    4. shapesIntersect (helper method)
    5. Online Polygon API

Graphics, Color, and Polygon Methods

  1. Display a Graphics Window (reminder)
    import java.awt.*;
    import javax.swing.*;
    
    class MyGraphics extends JComponent {
      public void paint(Graphics page) {
        // Place your paint code here!
      }
      //////////////////////////////////////////////
      ///           END OF YOUR CODE             ///
      ///  (you may ignore all the code below!!! ///
      //////////////////////////////////////////////
      public Dimension getPreferredSize() {
        int initialWidth = 500;
        int initialHeight = 400;
        return new Dimension(initialWidth, initialHeight);
      }
      public static void main(String[] args) {
        JComponent jc = newInstance();
        JFrame frame = new JFrame(jc.getClass().getName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel cp = new JPanel();
        cp.setLayout(new BorderLayout());
        cp.add(jc);
        frame.setContentPane(cp);
        frame.pack();
        frame.setVisible(true);
      }
      // Returns an instance of this class as a JComponent.  This is necessary so
      // students can rename this class without changing the "main" method's body.
      public static JComponent newInstance() {
        StackTraceElement[] trace = null;
        try { throw new RuntimeException(); }
        catch (Exception e) { trace = e.getStackTrace(); }
        try { return (JComponent)Class.forName(trace[0].getClassName()).newInstance(); }
        catch (Exception e) { return null; }
      }
    }
  2. Graphics Methods
     
    1. drawLine
        public void paint(Graphics page) {
          page.setColor(Color.gray);
          page.fillRect(50, 100, 150, 200);
          page.setColor(Color.black);
          page.drawLine(50, 100, 150, 200);  // suprised?
        }
    2. setLineThickness (helper method)
        public void paint(Graphics page) {
          for (int i=0; i<10; i++) {
            setLineThickness(page, i);
            int x = 100 + 20*i;
            page.drawLine(x, 50, x, 150);
          }
        }
        //////////////////////////////////////
        /// setLineThickness Helper method
        //////////////////////////////////////
      
        public static void setLineThickness(Graphics page, int thickness) {
          if (thickness < 0) thickness = 0;
          ((Graphics2D)page).setStroke(new BasicStroke(thickness));
        }

      Another Example:

        public void paint(Graphics page) {
          // See how the same line is drawn differently
          // with different line thicknesses
          page.setColor(Color.blue);
          setLineThickness(page, 20);
          page.drawLine(50, 50, 50, 250);
          page.setColor(Color.yellow);
          setLineThickness(page, 5);
          page.drawLine(50, 50, 50, 250);
          page.setColor(Color.black);
          setLineThickness(page, 1);
          page.drawLine(50, 50, 50, 250);
        }
    3. fillRect
        public void paint(Graphics page) {
          page.fillRect(50, 50, 100, 100);
        }
    4. drawRect
        public void paint(Graphics page) {
          page.drawRect(50, 50, 100, 100);
          page.setColor(Color.blue);
          setLineThickness(page, 5);
          page.drawRect(100, 100, 100, 100);
        }
    5. fillOval
        public void paint(Graphics page) {
          page.fillRect(50, 50, 50, 150);
          page.setColor(Color.green);
          page.fillOval(50, 50, 50, 150);
        }
    6. drawOval
        public void paint(Graphics page) {
          page.fillRect(50, 50, 50, 150);
          page.setColor(Color.green);
          page.drawOval(50, 50, 50, 150);
        }
    7. fillRoundRect
        public void paint(Graphics page) {
          int left = 50, top = 50, width = 50, height = 150;
          page.fillRect(left, top, width, height);
      
          int arcWidth = 30, arcHeight = 30;
          page.setColor(Color.yellow);
          page.fillRoundRect(left, top, width, height, arcWidth, arcHeight);
      
          left += 100;
          page.setColor(Color.blue);
          page.fillRoundRect(left, top, width, height, arcWidth, arcHeight);
        }
    8. drawRoundRect
        public void paint(Graphics page) {
          int left = 50, top = 50, width = 50, height = 150;
          page.fillRect(left, top, width, height);
          int arcWidth = 30, arcHeight = 30;
          page.setColor(Color.yellow);
          page.drawRoundRect(left, top, width, height, arcWidth, arcHeight);
          left += 100;
          page.setColor(Color.blue);
          page.drawRoundRect(left, top, width, height, arcWidth, arcHeight);
        }
    9. fillArc
        public void paint(Graphics page) {
          int left = 50, top = 100, width = 100, height = 150;
          page.fillRect(left, top, width, height);
          int startAngle = 45; // in degrees, where 45 always is the top-right corner!
          int extentAngle = 90;
          page.setColor(Color.yellow);
          page.fillArc(left, top, width, height, startAngle, extentAngle);
          startAngle = 180;
          extentAngle = 135;
          page.setColor(Color.red);
          page.fillArc(left, top, width, height, startAngle, extentAngle);
        }
    10. drawArc
        public void paint(Graphics page) {
          int left = 50, top = 100, width = 100, height = 150;
          page.fillRect(left, top, width, height);
          int startAngle = 45; // in degrees, where 45 always is the top-right corner!
          int extentAngle = 90;
          page.setColor(Color.yellow);
          page.drawArc(left, top, width, height, startAngle, extentAngle);
          startAngle = 180;
          extentAngle = 135;
          page.setColor(Color.red);
          page.drawArc(left, top, width, height, startAngle, extentAngle);
        }
    11. fillPolygon
        public void paint(Graphics page) {
          page.fillRect(100, 50, 200, 150);
          Polygon p = new Polygon();
          p.addPoint(100, 50);
          p.addPoint(200, 125);
          p.addPoint(300, 50);
          page.setColor(Color.green);
          page.fillPolygon(p);
        }
    12. drawPolygon
        public void paint(Graphics page) {
          page.fillRect(100, 50, 200, 150);
          Polygon p = new Polygon();
          p.addPoint(100, 50);
          p.addPoint(200, 125);
          p.addPoint(300, 50);
          page.setColor(Color.green);
          page.drawPolygon(p);
        }
    13. drawString
        public void paint(Graphics page) {
          page.drawString("Carpe Diem", 50, 50);
          page.setColor(Color.red);
          page.drawLine(50, 50, 100, 50); // surprised?
        }
    14. setFont
        public void paint(Graphics page) {
          page.setFont(new Font("Monospaced", Font.PLAIN, 16));
          page.drawString("Carpe Diem", 50, 50);
          page.setColor(Color.red);
          page.setFont(new Font("Serif", Font.BOLD, 32));
          page.drawString("Carpe Diem", 50, 100);
          page.setColor(Color.blue);
          page.setFont(new Font("SansSerif", Font.BOLD|Font.ITALIC, 64));
          page.drawString("Carpe Diem", 50, 175);
        }
    15. drawCenteredString (helper method)
      (and getStringWidth, getStringHeight, and getStringAscent)
        public void paint(Graphics page) {
          page.setColor(Color.blue);
          page.fillRect(50, 50, 400, 100);
          page.setFont(new Font("SansSerif", Font.BOLD, 64));
          page.setColor(Color.yellow);
          drawCenteredString(page, "Carpe Diem", 50, 50, 400, 100);
        }
        //////////////////////////////////////
        /// drawCenteredString Helper methods
        //////////////////////////////////////
        public static int getStringWidth(Graphics page, Font f, String s) {
          // Find the size of string s in the font of the Graphics context "page"
          FontMetrics fm   = page.getFontMetrics(f);
          java.awt.geom.Rectangle2D rect = fm.getStringBounds(s, page);
          return (int)Math.round(rect.getWidth());
        }
        public static int getStringHeight(Graphics page, Font f, String s) {
          // Find the size of string s in the font of the Graphics context "page"
          FontMetrics fm   = page.getFontMetrics(f);
          java.awt.geom.Rectangle2D rect = fm.getStringBounds(s, page);
          return (int)Math.round(rect.getHeight());
        }
        public static int getStringAscent(Graphics page, Font f, String s) {
          // Find the size of string s in the font of the Graphics context "page"
          FontMetrics fm   = page.getFontMetrics(f);
          return fm.getAscent();
        }
        public static void drawCenteredString(Graphics page, String s, int left, int top, int width, int height) {
          Font font = page.getFont();
          int textWidth  = getStringWidth(page,font,s);
          int textHeight = getStringHeight(page,font,s);
          int textAscent = getStringAscent(page,font,s);
          // Center text horizontally and vertically within provided rectangular bounds
          int textX = left + (width - textWidth)/2;
          int textY = top + (height - textHeight)/2 + textAscent;
          page.drawString(s, textX, textY);
        }
    16. Online Graphics API
      See http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Graphics.html
       
  3. Image Helper Methods
     
    1. Image Helper Methods
      1. drawImage
      2. drawCenteredImage
      3. getImageSize
      4. loadBufferedImage
      5. saveBufferedImage
         
    2. Image Helper Code
      imports:
      import java.awt.*;
      import java.awt.image.*;
      import javax.imageio.*;
      import java.io.*;
      import javax.swing.*;
      
      helper methods:
        //////////////////////////////////////
        /// Image Helper methods
        /////////////////////////////////////
      
        // Paint the given image rotated and scaled with a top-left at x,y
        public static void drawImage(Graphics page, Image image, int x, int y, double scale, double radians) {
          double imageWidth  = image.getWidth(null);
          double imageHeight = image.getHeight(null);
          Dimension newSize = getImageSize(image, scale, radians);
          java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform();
          transform.translate(x+newSize.getWidth()/2,y+newSize.getHeight()/2); // last (not first!)
          transform.rotate(radians);
          transform.scale(scale,scale);
          transform.translate(-imageWidth/2, -imageHeight/2);  // first
          ((Graphics2D)page).drawImage(image,transform,null);
        }
      
        // Same as drawImage, only here we position the image by its center
        public static void drawCenteredImage(Graphics page, Image image, int cx, int cy, double scale, double radians) {
          Dimension newSize = getImageSize(image, scale, radians);
          drawImage(page, image, cx - newSize.width/2, cy - newSize.height/2, scale, radians);
        }
      
        // get the size of this image after it has been scaled and rotated
        public static Dimension getImageSize(Image image, double scale, double radians) {
          double imageWidth  = image.getWidth(null);
          double imageHeight = image.getHeight(null);
          java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform();
          transform.rotate(radians);
          transform.scale(scale,scale);
          transform.translate(-imageWidth/2, -imageHeight/2);  // first
          double[] x = { 0, imageWidth, imageWidth ,     0       };
          double[] y = { 0,     0     , imageHeight, imageHeight };
          double minx=0, maxx=0, miny=0, maxy=0;
          java.awt.geom.Point2D.Double src = new java.awt.geom.Point2D.Double();
          java.awt.geom.Point2D.Double dst = new java.awt.geom.Point2D.Double();
          for (int i=0; i<4; i++) {
            src.setLocation(x[i],y[i]);
            transform.transform(src,dst);
            if (i == 0) {
              minx = maxx = dst.getX();
              miny = maxy = dst.getY();
            }
            else {
              minx = Math.min(dst.getX(),minx);
              miny = Math.min(dst.getY(),miny);
              maxx = Math.max(dst.getX(),maxx);
              maxy = Math.max(dst.getY(),maxy);
            }
          }
          return new Dimension((int)(maxx-minx), (int)(maxy-miny));
        }
      
      
        // Convert a jpg/png/etc file into an awt BufferedImage
        public static BufferedImage loadBufferedImage(String filename) {
          File file = new File(filename);
          if (!file.exists())
            throw new RuntimeException("File " + filename + " does not exist");
          try { return ImageIO.read(file); }
          catch (Exception e) { throw new RuntimeException(e); }
        }  
      
        // Verify the given the file format is one that is supported.
        public static void verifyFileFormatIsSupported(String format) {
          String[] legalFormats = ImageIO.getReaderFormatNames();
          for (String legalFormat : legalFormats)
            if (legalFormat.equals(format))
              return;
          throw new RuntimeException("Illegal format " + format + " not in " +
            java.util.Arrays.toString(legalFormats));
        }
      
        // Save the BufferedImage into the given file -- the image type is determined
        // by the extension of the file (.jpg, .png, etc)
        public static void saveBufferedImage(BufferedImage image, String filename) {
          int dotIndex = filename.lastIndexOf('.');
          if (dotIndex < 0) throw new RuntimeException("file must end in .jpg, .png, etc");
          String format = filename.substring(dotIndex+1);
          verifyFileFormatIsSupported(format);
          try { ImageIO.write(image, format, new File(filename)); }
          catch (Exception e) { throw new RuntimeException(e); }
         }
    3. Example:  Draw Images
          complete file (with imports and helper methods):  DrawImages.java
      
        public void paint(Graphics page) {
          // To run this, first save the image sampleImage.jpg to the current directory
      
          // get the dimensions of the draw area
          int width  = this.getWidth();
          int height = this.getHeight();
      
          // paint the background a pleasing olive green to complement our image
          page.setColor(new Color(120,120,50));
          page.fillRect(0,0,width,height);
      
          // center the full-sized, non-rotated image in the window
          double scale = 1.0;
          double rotation = 0.0;
          BufferedImage image = loadBufferedImage("sampleImage.jpg");
          drawCenteredImage(page, image, width/2, height/2, scale, rotation);
      
          // now draw a version of the image with its left-top at (0,0) and scaled to be smaller
          scale = 1.0/5.0;
          drawImage(page, image, 0, 0, scale, rotation);
      
          // and draw a 1/5th version in the top-right corner rotated by 45 degrees
          // This requires that we obtain the size of the rotated image so we
          // can compute its resulting left-top
          rotation = Math.toRadians(45);
          Dimension newSize = getImageSize(image, scale, rotation);
          int newLeft = width  - newSize.width;
          int newTop  = 0;
          drawImage(page, image, newLeft, newTop, scale, rotation);
        }
    4. Example:  Edit Image Files
          complete file (with imports and helper methods):  EditImages.java
      
        public static void main(String[] args) {
          // To run this, first save the image sampleImage.jpg to the current directory
          BufferedImage image = loadBufferedImage("sampleImage.jpg");
          Dimension dim = getImageSize(image, 1, 0);
          int imageWidth = dim.width;
          int imageHeight = dim.height;
          
          // Change all "nearly-black" pixels to blue!
          for (int x=0; x<imageWidth; x++)
            for (int y=0; y<imageHeight; y++) {
              int rgba  = image.getRGB(x,y);
              int alpha = (rgba >> 24) & 0xff;
              int red   = (rgba >> 16) & 0xff;
              int green = (rgba >>  8) & 0xff;
              int blue  = (rgba      ) & 0xff;
              if ((red < 30) && (green < 30) && (blue < 30)) {
                // we have a black pixel, switch to blue
                red = 0;
                green = 0;
                blue = 255;
                rgba = (alpha << 24) | (red << 16) | (green << 8) | (blue);
                image.setRGB(x,y,rgba);
              }
            }
          saveBufferedImage(image, "sampleImage1.jpg");
          
          // Get the graphics and paint a semi-transparent oval in the middle
          Graphics g = image.getGraphics();
          g.setColor(new Color(255, 0, 0, 128)); // semi-transparent red
          g.fillOval(0, imageHeight/2-20, imageWidth, 40);
          saveBufferedImage(image, "sampleImage3.jpg");
          
          // Make a new image from scratch
          int width = 400, height = 200;
          image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
          g = image.getGraphics();
          g.setColor(Color.yellow);
          g.fillRect(0,0,width,height);
          // add some vertical bars
          g.setColor(Color.blue);
          for (int x=20; x<width; x+=50)
            g.fillRect(x,0,10,height);
          // and a semi-transparent message
          g.setColor(new Color(255, 0, 0, 128)); // semi-transparent red again
          g.setFont(new Font("Arial",Font.BOLD,64));
          drawCenteredString(g,"Carpe Diem",0,0,width,height);
          saveBufferedImage(image, "sampleImage4.jpg");    
        }
  4. Color Methods
     
    1. Construct RGB Color
        public void paint(Graphics page) {
          // For a list of colors, see:  http://en.wikipedia.org/wiki/List_of_colors
          Color amethyst = new Color(153, 102, 204);
          page.setColor(amethyst);
          page.fillRect(10, 10, 50, 100);
          Color cinnabar = new Color(227, 66, 52);
          page.setColor(cinnabar);
          page.fillRect(30, 30, 50, 50);
        }
    2. Construct RGBA Color
        public void paint(Graphics page) {
          // For a list of colors, see:  http://en.wikipedia.org/wiki/List_of_colors
          Color amethyst = new Color(153, 102, 204);
          page.setColor(amethyst);
          page.fillRect(10, 10, 50, 100);
          Color semiTransparentCinnabar = new Color(227, 66, 52, 128);
          page.setColor(semiTransparentCinnabar);
          page.fillRect(30, 30, 50, 50);
        }
    3. equals
        public void paint(Graphics page) {
          Color amethyst = new Color(153, 102, 204);
          page.setColor(amethyst);
          page.fillRect(10, 10, 50, 100);
          Color anotherAmethyst = new Color(153, 102, 204);
          page.setColor(anotherAmethyst);
          page.fillRect(30, 30, 50, 50);
          System.out.println(amethyst == anotherAmethyst); // surprised?
          System.out.println(amethyst.equals(anotherAmethyst));
        }
    4. brighter
        public void paint(Graphics page) {
          Color amethyst = new Color(153, 102, 204);
          page.setColor(amethyst);
          page.fillRect(10, 10, 50, 100);
          Color brighterAmethyst = amethyst.brighter();
          page.setColor(brighterAmethyst);
          page.fillRect(30, 30, 50, 50);
        }
    5. darker
        public void paint(Graphics page) {
          Color amethyst = new Color(153, 102, 204);
          page.setColor(amethyst);
          page.fillRect(10, 10, 50, 100);
          Color darkerAmethyst = amethyst.darker();
          page.setColor(darkerAmethyst);
          page.fillRect(30, 30, 50, 50);
        }
    6. getRed, getGreen, getBlue, and getAlpha
        public void paint(Graphics page) {
          Color amethyst = new Color(153, 102, 204);
          page.setColor(amethyst);
          page.fillRect(10, 10, 50, 100);
          Color semiTransparentCinnabar = new Color(227, 66, 52, 128);
          page.setColor(semiTransparentCinnabar);
          page.fillRect(30, 30, 50, 50);
          System.out.println("RGBA values for semiTransparentCinnabar:");
          System.out.println("   red   = " + semiTransparentCinnabar.getRed());
          System.out.println("   green = " + semiTransparentCinnabar.getGreen());
          System.out.println("   blue  = " + semiTransparentCinnabar.getBlue());
          System.out.println("   alpha = " + semiTransparentCinnabar.getAlpha());
        }
    7. Online Color API
      See:  http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Color.html
       
  5. Polygon Methods
     
    1. getBounds
        public void paint(Graphics page) {
          page.fillRect(100, 50, 200, 150);
          Polygon p = new Polygon();
          p.addPoint(100, 50);
          p.addPoint(200, 125);
          p.addPoint(300, 50);
          page.setColor(Color.black);
          page.fillPolygon(p);
      
          Rectangle bounds = p.getBounds();
          System.out.println("Polygon's bounds: ");
          System.out.println("  left   = " + (int)bounds.getX());
          System.out.println("  top    = " + (int)bounds.getY());
          System.out.println("  width  = " + (int)bounds.getWidth());
          System.out.println("  height = " + (int)bounds.getHeight());
        }
    2. contains
        public void paint(Graphics page) {
          page.fillRect(100, 50, 200, 150);
          Polygon p = new Polygon();
          p.addPoint(100, 50);
          p.addPoint(200, 125);
          p.addPoint(300, 50);
          page.setColor(Color.black);
          page.fillPolygon(p);
          // This line starts inside the triangle, ends outside the triangle
          page.setColor(Color.yellow);
          page.drawLine(150, 75, 150, 100);
          System.out.println("Polygon contains...");
          System.out.println("  (150, 75)  = " + p.contains(150, 75));
          System.out.println("  (150, 100) = " + p.contains(150, 100));
          System.out.println("Polygon's bounds contains...");
          Rectangle bounds = p.getBounds();
          System.out.println("  (150, 75)  = " + bounds.contains(150, 75));
          System.out.println("  (150, 100) = " + bounds.contains(150, 100));
        }
    3. translate
        public void paint(Graphics page) {
          page.fillRect(100, 50, 200, 150);
          Polygon p = new Polygon();
          p.addPoint(100, 50);
          p.addPoint(125, 75);
          p.addPoint(100, 100);
          page.setColor(Color.blue);
          page.fillPolygon(p);
          p.translate(50, 50);
          page.setColor(Color.yellow);
          page.fillPolygon(p);
          p.translate(50, -75);
          page.setColor(Color.red);
          page.fillPolygon(p);
        }
    4. shapesIntersect (helper method)
        public void paint(Graphics page) {
          Polygon p1 = new Polygon();
          p1.addPoint(50, 50);
          p1.addPoint(100, 100);
          p1.addPoint(50, 150);
          page.setColor(Color.blue);
          page.fillPolygon(p1);
          Polygon p2 = new Polygon();
          p2.addPoint(75, 70);
          p2.addPoint(125, 120);
          p2.addPoint(175, 70);
          page.setColor(Color.red);
          page.fillPolygon(p2);
          Rectangle bounds1 = p1.getBounds();
          Rectangle bounds2 = p2.getBounds();
          System.out.println("intersection tests for...");
          System.out.println("  polygons:       " + shapesIntersect(p1, p2));
          System.out.println("  polygon bounds: " + shapesIntersect(bounds1, bounds2));
        }
        //////////////////////////////////////
        /// shapesIntersect Helper method
        //////////////////////////////////////
        public static boolean shapesIntersect(Shape s1, Shape s2) {
          java.awt.geom.Area area = new java.awt.geom.Area(s1);
          area.intersect(new java.awt.geom.Area(s2));
          return !area.isEmpty();
        }
    5. Online Polygon API
      See:  http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Polygon.html

carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem   -   carpe diem