My other sites

Latest News

New Summer Look :)










Using the 2D API

 

Introducing the 2Dapi

(1) Graphics Processing

Drawing Example Using the 2Dapi

Adding Paints and Strokes

Adding Texture

General Paths

Compositing

Transformations

(2) Text Processing

(3) Image Handling

Image Processing

(4) Graphics Device Hookups

Colour Management

Quiz

Exercises

 


Introducing the 2Dapi

  - Huge improvement over the previous Graphics abilities

- Part of the Java media API, which contains :
Java3D, Advanced Imaging, Media Framework, Sound, Speech, Telephony

2Dapi is internal to jdk1.2 and contains classes for:
- (1) Graphics Processing
- (2) Text Processing
- (3) Image Handling
- (4) Graphics Device Hooks
- (5) Colour Management

 

 

(1) Graphics Processing

  New Subclass of Graphics -> Graphics2D

Drawing in Java involves 3 steps
- Specify the drawing attributes
o setColor(), setFont(), setPaintMode(), setXORMode()

- Identify the Shape sh to draw
o Line2D, Rectangle2D, RoundRectangle2D, Ellipse2D
o QuadCurve2D, CubicCurve2D, Arc2D, GeneralPath

- Draw it
o draw(sh) -> uses the current Stroke
o fill(sh) -> uses the current Paint

Transformations & Compositing available


Drawing Example Using the 2Dapi

 


import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.*;

public class Example2D extends Frame {
   public static void main(String[] argv) {
	   Example2D myExample = new Example2D();
   }	
   public Example2D() {
	setSize(300,180);
	addWindowListener(new WindowAdapter() {
	    public void windowClosing(WindowEvent we) { 
		dispose();System.exit(0);
	    }});
	setVisible(true);
   }
public void paint(Graphics g) {
	Graphics2D g2d = (Graphics2D)g;
	g2d.setColor(Color.red);
	Rectangle2D rect1 = new Rectangle2D.Double(32,42,100,100);
	Rectangle2D rect2 = new Rectangle2D.Double(164,42,100,100);
	g2d.fill(rect1);
	g2d.draw(rect2);	
   }
}


Adding Paints and Strokes


public
void paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; g2d.setColor(Color.red); Rectangle2D rect1 = new Rectangle2D.Double(32,42,100,100); Rectangle2D rect2 = new Rectangle2D.Double(164,42,100,100); Paint gp = g2d.getPaint(); g2d.setPaint(new GradientPaint
(32,42,Color.red,100,100,Color.white,true)); g2d.fill(rect1); g2d.setPaint(gp); g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 3f, new float[] {10f}, 0f)); g2d.draw(rect2);
}
* GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2, boolean cyclic)

* BasicStroke(float width, int cap, int join, float miterlimit, float[] dash, float dash_phase)


Adding Texture


 public void paint(Graphics g) {
 	Graphics2D g2d = (Graphics2D)g;
 	Rectangle2D rect1 = new Rectangle2D.Double(32,42,100,100);
 	Rectangle2D rect2 = new Rectangle2D.Double(164,42,100,100);
 	g2d.setPaint(loadTextureResource("trouble.gif"));
 	g2d.fill(rect1);
 	g2d.setStroke(new BasicStroke(10f, BasicStroke.CAP_ROUND, 
		BasicStroke.JOIN_MITER, 2f, new float[] {12f}, 0f));
 	g2d.draw(rect2);
 }

 public TexturePaint loadTextureResource(String absfilename) {
  MediaTracker tracker = new MediaTracker(this);
  Image imtexture = Toolkit.getDefaultToolkit().getImage(absfilename);
  tracker.addImage(imtexture,0);
  try {
    tracker.waitForID(0);
    int width = imtexture.getWidth(this);
    int height = imtexture.getHeight(this);
    System.out.println("width" + width + " height =" + height);
    BufferedImage buffImg = new BufferedImage(width, height, 
						 BufferedImage.TYPE_INT_ARGB);
    Graphics g = buffImg.getGraphics();
    g.drawImage(imtexture,0,0,this);
    return new TexturePaint(buffImg,new Rectangle2D.Double(0,0,width,height));
  }
  catch (Exception e) {
    System.out.println("Exception on Image-Texture Loading");
  }
  return null;
}


General Paths



  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;
    GeneralPath gp1 = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
    GeneralPath gp2 = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
    gp1.moveTo(20,30); gp1.lineTo(150,30);
gp1.lineTo(150,130);gp1.closePath(); gp2.moveTo(180,30); gp2.lineTo(290,30);
gp2.quadTo(200,75,180,130); gp2.curveTo(110,50,220,100,180,30); g2d.setPaint(loadTextureResource("Cork.jpg")); g2d.fill(gp1); g2d.fill(gp2); }


Compositing

 
public void paint(Graphics g) {
   Graphics2D g2d = (Graphics2D)g;
   Rectangle2D rect1 = new Rectangle2D.Double(32,42,200,130);
   Rectangle2D rect2 = new Rectangle2D.Double(164,42,100,100);
   g2d.setColor(Color.cyan);
   g2d.fill(rect1);
   g2d.setPaint(loadTextureResource("Cork.jpg"));
   g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.5f));
   g2d.fill(rect2);
}
 

Transformations

  Class AffineTransform can be used for :
- translating, rotating, scaling, fliping, shearing

Just know the static methods of the class
getRotateInstance(double theta)
getScaleInstance(double scaleX, double scaleY)
getShearInstance(double shiftX, double shiftY)
getTranslateInstance(double x, double y)

Which return an Instance of AffineTransform encapsulating the Geometry of the transformation
 
 public void paint(Graphics g) {
 	Graphics2D g2d = (Graphics2D)g;
 	Rectangle2D rect1 = new Rectangle2D.Double(132,42,100,100);
 	AffineTransform at = AffineTransform.<XXX>
 	g2d.setTransform(at);
 	g2d.setColor(Color.red);
 	g2d.fill(rect1);
 }


(2) Text Processing

 
import java.awt.*;

public class FontLister {

  public static void main(String[] argv) {
    Font fonts[] =   
       GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
    for (int i=0; i<fonts.length; i++) {
	  System.out.println(i + " font=" + fonts[i]);
    }
    Font myFont = fonts[2].deriveFont(Font.BOLD, 32);
  }
}
public void paint(Graphics g) {
  Graphics2D g2d = (Graphics2D)g;
  FontRenderContext frc = g2d.getFontRenderContext();
  Font font = new Font("Helvetica",Font.ITALIC | Font.BOLD, 72);
  TextLayout tl = new TextLayout("Excellent!",font,frc);
  Shape myShape = tl.getOutline(
                 AffineTransform.getTranslateInstance(50,100));
  Paint myPaint = loadTextureResource("Cork.jpg");
  g2d.setPaint(myPaint);
  g2d.fill(myShape);
}
 


(3) Image Handling

  BufferedImage
- For animation (double buffering)
- For optimising internal representation

Using BufferedImage
- instantiate i.e. new BufferedImage(width,height,type))
- use getGraphics to get a Graphics or createGraphics() to get a Graphics2D
- you could could ask the DeviceConfguration for the optimal type using createCombatibleImage()


Image Processing

  BufferedImageFilter and BufferedImageOp

- AffineTransformOp : for all Affine Transformations
- ColorConvertOp : for Colour mappings
- ConvoleOp : for weighted convolutions
- LookupOp : for non uniform modifications
- RescaleOp : for special scalings

JPEG encoding and decoding
- com.sun.image.codec.jpeg
- ask the JPEGCodec for a decoder or encoder
- read or write on the streams


(4) Graphics Device Hookups

  Class GraphicsDevice contains GraphicsConfiguration that encapsulates the configuration of the Output Device

You use GraphicsConfiguration to :
- get the current ColorModel
- get the available Fonts
- register a new Font
- optimise drawing operations


(5) Colour Management

Classes Color and ColorSpace

A map of device dependent colour spaces to device independent colour spaces is represented by class ICC_Profile
- ICC_ProfileGray
- ICC_ProfileRGB

Color Conversions between spaces
- RGB, GRAY, LINEAR_RGB, PYCC, CIEXYZ
- CIEXYZ is preferred (check www.color.org)

Quiz


1. When we want absolute coordinates we have to set the layout of a Container to null. Can you imagine what this implies for the implementation of Container? Is there a better way?

2. How would you proceed to create Oval borders? Oval buttons? Oval Windows?

3. Can you place AWT components inside JInternalWindows? And if yes how you would expect them to behave and why?

4. What will be drawn if the following code executes?

 public void paint(Graphics g) {
	Graphics2D g2d = (Graphics2D)g;
	GeneralPath gp1 = new GeneralPath();
	gp1.moveTo(100,200); gp1.curveTo(110,60,190,60,200,200);
	gp1.lineTo(180,200); gp1.curveTo(180,150,160,150,160,200);
	gp1.lineTo(140,200); gp1.curveTo(140,150,120,150,120,200);
	gp1.closePath();
	g2d.setColor(Color.blue); 
	g2d.fill(gp1);
	g2d.setColor(Color.white);
	Shape el1 = new 

Ellipse2D.Double(125,120,30,30);
	Shape el2 = new 

Ellipse2D.Double(145,120,30,30);
	g2d.fill(el1); g2d.fill(el2);
	g2d.setColor(Color.black);
	el1 = new Ellipse2D.Double(135,130,15,15);
	el2 = new Ellipse2D.Double(155,130,15,15);
	g2d.fill(el1);g2d.fill(el2);
}


Exercises


1. Get any example you have written that uses AWT and change it so that it
uses the respective SWING components. Add borders and ToolTips where appropriate. Change the UI style and notice the differences

2. Write the Scribble example but this time using Internal Frames decorated with JScrollPanes. Use the 2D api to draw the lines in random opacity, width, colour and stroke

3. Use the AffineTransform to animate a ball falling from the top of a panel to the bottom

4. Provide randomly different transformations including scaling, shearing and rotating

5. Use BufferedImage for the drawing to avoid flickering and Graphics’s drawImage() to instantly commit all the changes to the screen