Darkening an image in Swing

To darken an image, you can use the class LookupOp. This class works with one or more tables that will be applied to the color values of the pixels. To darken n RGB image, the RGB values have to be decreased (lower values means darker). The lookup table reflects these changes.

The following example shows the original image and an image that has been darkened by dividing the intensities by 2.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         short[] intensity = new short[256];
         for(int i=0; i<256; i++) {
            intensity[i] = (short) (i / 2);
         }
  
         ShortLookupTable slt = new ShortLookupTable(0, intensity);
         LookupOp op = new LookupOp(slt, null);
         destBi = op.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Brightening an image in Swing

To brighten an image, you can use the class LookupOp. This class works with one or more tables that will be applied to the color values of the pixels. To brighten an RGB image, the RGB values have to be increased (higher values means brighter). The lookup table reflects these changes.

The following example shows the original image, an image that has been brightened by adding 30 to every pixel color (every R,G and B, and all values that are higher than 255 are reset to 255) and an image where brightening is based on the rule that says that midrange colors are adjusted more than dark or bright colors.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
   private BufferedImage destBi2;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         destBi2 = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*3);
 
         short[] intensity1 = new short[256];
         for(int i=0; i<256; i++) {
            short newVal = (short) (i + 30);
            if (newVal > 255) newVal = 255;
            intensity1[i] = newVal;
         }
  
         byte[] intensity2 = new byte[256];
         for(int i=0; i<256; i++) {
            intensity2[i] = (byte) (Math.sqrt((float)i/255.0) * 255);
         }
 
         ShortLookupTable slt = new ShortLookupTable(0, intensity1);
         LookupOp op = new LookupOp(slt, null);
         destBi = op.filter(sourceBi, null);
 
         ByteLookupTable blt = new ByteLookupTable(0, intensity2);
         LookupOp op2 = new LookupOp(blt, null);
         destBi2 = op2.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
      g2d.drawImage(destBi2, 0, sourceBi.getHeight()*2, this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Zero out all pixels of a RGB band in Swing

Use the class LookupOp and pass it an array of arrays, each representing the change in band. In this example, the G(reen) and B(lue) band don’t change while the R(ed) value is made zero for all intensities.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         byte[][] intensity = new byte[3][256];
         for(int i=0; i<256; i++) {
            intensity[0][i] = 0;
            intensity[1][i] = (byte) i;
            intensity[2][i] = (byte) i;
         }
  
         ByteLookupTable blt = new ByteLookupTable(0, intensity);
         LookupOp op = new LookupOp(blt, null);
         destBi = op.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Inverting the red band of all pixels of a image in Swing

Use the class LookupOp and pass it an array of arrays, each representing the change in band.

In this example, the G(reen) and B(lue) band don’t change while the R(ed) pixels are made brighter.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         byte[][] intensity = new byte[3][256];
         int newRed;
         for(int i=0; i<256; i++) {
            newRed = (int) (i*1.5);  if (newRed > 255) newRed = 255;
            intensity[0][i] = (byte) newRed;
            intensity[1][i] = (byte) i;
            intensity[2][i] = (byte) i;
         }
  
         ByteLookupTable blt = new ByteLookupTable(0, intensity);
         LookupOp op = new LookupOp(blt, null);
         destBi = op.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing, check out this expensive but excellent book:

Fading in/out an image in Swing

Apply a ConvolveOp filter with the following kernel to your image:

	[ 0  0  0
        0  fadeFactor  0
        0  0  0 ]

To fade in, increase fadeFactor by some number (in our example .1). To fade out, decrease fadeFactor.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame implements Runnable {
   private BufferedImage sourceBi;
   private BufferedImage destBi;
   private float fadeFactor = 1f;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
 
      Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
      sourceBi = toBufferedImage(img);
      setSize(img.getWidth(null), 25+img.getHeight(null)*2);
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      g2d.drawImage(sourceBi, 0, 20, this);
      if (destBi != null) {
         g2d.drawImage(destBi, 0, 20+sourceBi.getHeight(), this);
      }
   }
 
   public void run() {
      while (true) {
         fadeIn(); 
         sleep(3000);
         fadeOut();
         sleep(3000);
      }
   }
 
   public void sleep(long millis) {
      try {
         Thread.sleep(millis);
      }
      catch(InterruptedException e) {
      }
   }
 
   public void fadeIn() {
      fadeFactor = 0;
      for (int i=0; i<10; i++) {
         fadeFactor += .1;
         performConvolve();
         repaint();
         sleep(100);
      }
   }
 
   public void fadeOut() {
      for (int i=0; i<10; i++) {
         fadeFactor -= .1;
         performConvolve();
         repaint();
         sleep(100);
      }
   }
 
   public void performConvolve() {
      destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                 BufferedImage.TYPE_INT_RGB);
  
      Kernel kernel = new Kernel(3, 3, new float[] 
                                         { 0, 0, 0,
                                           0, fadeFactor, 0,
                                           0, 0, 0 });
      ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
      cOp.filter(sourceBi, destBi);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
 
      Thread t = new Thread(main);
      t.start();
   }
}

Image used:


To learn more about image processing,
check out this excellent but expensive book:

Cropping an image in Swing

Use the class CropImageFilter.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.awt.*;
 
public class Main extends JFrame {
   private Image image;
   int startx, starty;
   int stopx, stopy;
   int currentx, currenty;
   
   public Main() throws Exception {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      image = new javax.swing.ImageIcon("http://www.esus.com/images/space.jpg").getImage();
 
      this.addMouseListener(new MouseAdapter() {
         public void mousePressed(MouseEvent me) {
            startx = me.getX();
            starty = me.getY();
            stopx = stopy = 0;
            repaint();
         }
 
         public void mouseReleased(MouseEvent me) {
            stopx = me.getX();
            stopy = me.getY();
            currentx = currenty = 0;
            repaint();
            constructFrame(getCroppedImage(image, startx, starty, 
                                           stopx-startx, stopy-starty));
         }
      });
 
      this.addMouseMotionListener(new MouseMotionAdapter() {
         public void mouseDragged(MouseEvent me) {
            currentx = me.getX();
            currenty = me.getY();
            repaint();
         }
      });
   } 
  
   public void constructFrame(final Image img) {
      JFrame frame = new JFrame() {
         public void paint(Graphics g) {
            g.drawImage(img, 0, 15, null);
         }
      };
      frame.setSize(img.getWidth(null), img.getHeight(null));
      frame.setVisible(true);
      frame.invalidate();
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      g2d.drawImage(image, 0, 0, this);
 
      if (startx != 0 && currentx != 0) {
         g2d.setColor(Color.white);
         BasicStroke bs = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                                            5, new float[] {10}, 0);
         g2d.setStroke(bs);
         g2d.drawRect(startx, starty, currentx-startx, currenty-starty);
      }
 
   }
 
   public Image getCroppedImage(Image img, int x, int y, int w, int h) {
      CropImageFilter cif = new CropImageFilter(x, y, w, h);
      FilteredImageSource fis = new FilteredImageSource(img.getSource(), cif);
      Image croppedImage = getToolkit().createImage(fis);
 
      MediaTracker tracker = new MediaTracker(this);
      tracker.addImage(croppedImage, 0);
      try {
         tracker.waitForID(0);
      } catch (Exception e) { 
         e.printStackTrace(); 
      } 
         
      return croppedImage;
   }
 
   public static void main(String []args) throws Exception {
      Main main = new Main();
      main.setSize(500, 400);
      main.setVisible(true);
   }
}

Inverting an image

To invert an image, you can use the class LookupOp. This class works with one or more tables that will be applied to the color values of the pixels. To invert an RGB image, every R, G, and B value are subtracted from 256. The lookup table reflects these changes.

The following example shows the original image and an image that has been inverted.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("meatballs.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         byte[] intensity = new byte[256];
         for(int i=0; i<256; i++) {
            intensity[i] = (byte) (256 - i);
         }
  
         ByteLookupTable blt = new ByteLookupTable(0, intensity);
         LookupOp op = new LookupOp(blt, null);
         destBi = op.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Shearing an image

Shearing is performing an operation on the image in which the parallel lines will remain parallel while opposite corners are pulled apart (one or two dimensions).

Main.java:

import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private Image image;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = Toolkit.getDefaultToolkit().getImage("c:\djkrush.jpg");
      waitForImage(image);
      image = shearImage(image, 1, 0);
      setSize(image.getWidth(null), image.getHeight(null));
   }
 
   public void paint(Graphics g) {
      g.drawImage(image, 0, 0, this);
   }
 
   public void waitForImage(Image image) {
      MediaTracker mt = new MediaTracker(this);
 
      int id = 0;
      mt.addImage(image, id);
 
      try {
         mt.waitForID(id);
      }
      catch(InterruptedException e) {
         System.out.println("Image loading interrupted : " + e);
      }
   }
 
   public Image shearImage(Image image, double shearx, double sheary) {
      BufferedImage bi = toBufferedImage(image);
 
      AffineTransformOp op = new AffineTransformOp(
                   AffineTransform.getShearInstance(shearx, sheary), null); 
 
      return op.filter(bi, null); 
   }
 
   public BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
   }
}

Image used:

Scaling an image

You can use apply an AffineTransform object when drawing the image, or you can create a BufferedImage and perform an scaling operation on it.

Apply AffineTransform when drawing image

Main.java:

import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private Image image;
   private double scalex = 1.0;
   private double scaley = 1.0;
   private JButton button1;
   private JButton button2;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = Toolkit.getDefaultToolkit().getImage("c:\djkrush.jpg");
      waitForImage(image);
 
      getContentPane().setLayout(new BorderLayout());
      
      button1 = new JButton("scale up by 5");
      button1.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            scalex += .1;
            scaley += .1;
            repaint();
         }
      });
 
      button2 = new JButton("scale down by 5");
      button2.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            scalex -= .1;
            scaley -= .1;
            repaint();
         }
      });
 
      JPanel panel = new JPanel(new GridLayout(1, 2));
      panel.add(button1);
      panel.add(button2);
      getContentPane().add(BorderLayout.SOUTH, panel);
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      AffineTransform at = new AffineTransform();
      at.scale(scalex, scaley);
      g2d.drawImage(image, at, this);
 
      button1.repaint();
      button2.repaint();
   }
 
   public void waitForImage(Image image) {
      MediaTracker mt = new MediaTracker(this);
 
      int id = 0;
      mt.addImage(image, id);
 
      try {
         mt.waitForID(id);
      }
      catch(InterruptedException e) {
         System.out.println("Image loading interrupted : " + e);
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Creating BufferedImage and scaling afterwards

Main.java:

import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private Image image;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = Toolkit.getDefaultToolkit().getImage("c:\djkrush.jpg");
      waitForImage(image);
      image = scaleImage(image, 2.0, 2.0);
   }
 
   public void paint(Graphics g) {
      g.drawImage(image, 0, 0, this);
   }
 
   public void waitForImage(Image image) {
      MediaTracker mt = new MediaTracker(this);
 
      int id = 0;
      mt.addImage(image, id);
 
      try {
         mt.waitForID(id);
      }
      catch(InterruptedException e) {
         System.out.println("Image loading interrupted : " + e);
      }
   }
 
   public Image scaleImage(Image image, double scalex, double scaley) {
      BufferedImage bi = toBufferedImage(image);
 
      AffineTransformOp op = new AffineTransformOp(
                   AffineTransform.getScaleInstance(scalex, scaley), null); 
 
      return op.filter(bi, null); 
   }
 
   public BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 

      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Image used:

Drawing a rotated image

Work directly on the class Graphics2D or use the class AffineTransform that allows you to create your own transformation matrixes.

Directly on Graphics2D

Main.java:

import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private Image image;
   private boolean firstTime = true;
   private int degrees = 0;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = Toolkit.getDefaultToolkit().getImage("c:\djkrush.jpg");
      waitForImage(image);
 
      getContentPane().setLayout(new BorderLayout());
      JButton button = new JButton("rotate by 10 degrees");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            degrees += 10;
            repaint();
         }
      });
 
      getContentPane().add(BorderLayout.SOUTH, button);
   }
 
   public void paint(Graphics g) {
      super.paint(g);
 
      Graphics2D g2d = (Graphics2D) g;
 
      double radians = degrees * (Math.PI / 180);
      g2d.translate(getSize().width/2, getSize().height/2);
      g2d.rotate(radians); 
      g2d.drawImage(image, 0, 0, this);
   }
 
   public void waitForImage(Image image) {
      MediaTracker mt = new MediaTracker(this);
 
      int id = 0;
      mt.addImage(image, id);
 
      try {
         mt.waitForID(id);
      }
      catch(InterruptedException e) {
         System.out.println("Image loading interrupted : " + e);
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Using AffineTransform

Main.java:

import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private Image image;
   private boolean firstTime = true;
   private int degrees = 0;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = Toolkit.getDefaultToolkit().getImage("c:\djkrush.jpg");
      waitForImage(image);
 
      getContentPane().setLayout(new BorderLayout());
      JButton button = new JButton("rotate by 10 degrees");
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            degrees += 10;
            repaint();
         }
      });
 
      getContentPane().add(BorderLayout.SOUTH, button);
   }
 
   public void paint(Graphics g) {
      super.paint(g);
 
      if (degrees == 0) {
         g.drawImage(image, getSize().width/2, getSize().height/2, this);
      }
      else {  
         Graphics2D g2d = (Graphics2D) g;
 
         double radians = degrees * (Math.PI / 180);
         AffineTransform at = new AffineTransform();
         at.translate(getSize().width/2, getSize().height/2);
         at.rotate(radians);
         g2d.drawImage(image, at, this);
      }
   }
 
   public void waitForImage(Image image) {
      MediaTracker mt = new MediaTracker(this);
 
      int id = 0;
      mt.addImage(image, id);
 
      try {
         mt.waitForID(id);
      }
      catch(InterruptedException e) {
         System.out.println("Image loading interrupted : " + e);
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

image used: