bb.gui
Class ScreenShot

java.lang.Object
  extended by bb.gui.ScreenShot

public final class ScreenShot
extends Object

Class which supports taking screen shots of the entire desktop, AWT Components, or Swing JComponents. This functionality is implemented in a series of take methods, each of which returns a BufferedImage. This class also offers convenience write methods for storing BufferedImages to files.

The images taken by this class should be the precise images seen on the screen. However, the images written to files may deviate from the originals. One obvious cause is limitations of the chosen file format (especially with lossy formats like jpeg). A subtle issue can occur, however, even when using lossless formats like png: if the file is subsequently opened by another application, that application may rescale the image, which can often cause visible artifacts.

To see this last problem on Windows XP, call take() which returns an image of the entire desktop and write it to a file, and then open the file with XP's default graphics file viewer ("Windows Picture And Fax Viewer"). This program shrinks the desktop image in order to fit it inside the program's window, and rescaling artifacts are readily seen, especially if the desktop image has any kind of text in it. If "Windows Picture And Fax Viewer" instead cropped the image or had a scroll pane, then this should not happen.

Acknowledgement: this class was inspired by the program ScreenImage. Differences from the above program:

  1. this class uses BufferedImage.TYPE_INT_ARGB instead of BufferedImage.TYPE_INT_RGB in order to preserve alpha
  2. this class's default image file format is PNG instead of JPEG
  3. this class's take methods simply take snapshots and never have the side effect of writing image files
  4. this class added a version of take which can get a snapshot of a region of a Component
  5. when taking a snapshot of a region of a Component or JComponent, the Rectangle that specifies the region always has coordinates relative to the origin of the item
See also: forum discussion #1 on screen shots forum discussion #2 on screen shots forum discussion #3 on screen shots.

Like typical Java GUI code, this class is not multithread safe: it expects to only be called by EventQueue's dispatch thread. This threading limitation is checked in every public method.

Author:
Brent Boyer

Nested Class Summary
static class ScreenShot.UnitTest
          See the Overview page of the project's javadocs for a general description of this unit test class.
 
Field Summary
static String formatNameDefault
          Default value for the graphics file format that will be written by this class.
private static int imageType
          Defines the image type for the BufferedImages that will create when taking snapshots.
 
Constructor Summary
private ScreenShot()
          This sole private constructor suppresses the default (public) constructor, ensuring non-instantiability outside of this class.
 
Method Summary
private static String getGraphicsFormat(File file)
          Returns the name of the graphics format stored in file.
static BufferedImage take()
          Takes a screen shot of the entire desktop.
static BufferedImage take(Component component)
          Takes a screen shot of that part of the desktop whose area is where component lies.
static BufferedImage take(Component component, Rectangle region)
          Takes a screen shot of that part of the desktop whose area is the region relative to where component lies.
static BufferedImage take(JComponent jcomponent)
          Takes a screen shot of just jcomponent (no other gui elements will be present in the result).
static BufferedImage take(JComponent jcomponent, Rectangle region)
          Takes a screen shot of just the specified region of jcomponent (no other gui elements will be present in the result).
static BufferedImage take(Rectangle region)
          Takes a screen shot of the specified region of the desktop.
static void write(BufferedImage image, File file)
          Calls write(image, getGraphicsFormat(file), file).
static void write(BufferedImage image, String filePath)
          Calls write(image, new File(filePath)).
static void write(BufferedImage image, String formatName, File file)
          Writes image to file in the format specified by formatName.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

imageType

private static final int imageType
Defines the image type for the BufferedImages that will create when taking snapshots. The current value is BufferedImage.TYPE_INT_ARGB, which was chosen because
  1. the 'A' in its name means that it preserves any alpha in the image (cannot use the "non-A" types)
  2. the "_INT" types are the fastest types (the "BYTE" types are slower)

See Also:
this forum posting, Constant Field Values

formatNameDefault

public static final String formatNameDefault
Default value for the graphics file format that will be written by this class. The current value is "png" because the PNG format is by far the best lossless format currently available. Furthermore, java cannot write to GIF anyways (only read).

See Also:
Portable Network Graphics (PNG) Specification (Second Edition), GIF or PNG, PNG Home Site, Constant Field Values
Constructor Detail

ScreenShot

private ScreenShot()
This sole private constructor suppresses the default (public) constructor, ensuring non-instantiability outside of this class.

Method Detail

take

public static BufferedImage take()
                          throws AWTException,
                                 SecurityException,
                                 IllegalStateException
Takes a screen shot of the entire desktop.

Any thread may call this method.

Returns:
a BufferedImage representing the entire screen
Throws:
IllegalStateException - if calling thread is not EventQueue's dispatch thread
AWTException - if the platform configuration does not allow low-level input control. This exception is always thrown when GraphicsEnvironment.isHeadless() returns true
SecurityException - if createRobot permission is not granted

take

public static BufferedImage take(Rectangle region)
                          throws IllegalArgumentException,
                                 IllegalStateException,
                                 AWTException,
                                 SecurityException
Takes a screen shot of the specified region of the desktop.

Any thread may call this method.

Parameters:
region - the Rectangle within the screen that will be captured
Returns:
a BufferedImage representing the specified region within the screen
Throws:
IllegalArgumentException - if region == null; region's width and height are not greater than zero
IllegalStateException - if calling thread is not EventQueue's dispatch thread
AWTException - if the platform configuration does not allow low-level input control. This exception is always thrown when GraphicsEnvironment.isHeadless() returns true
SecurityException - if createRobot permission is not granted

take

public static BufferedImage take(Component component)
                          throws IllegalArgumentException,
                                 IllegalStateException,
                                 AWTException,
                                 SecurityException
Takes a screen shot of that part of the desktop whose area is where component lies. Any other gui elements in this area, including ones which may lie on top of component, will be included, since the result always reflects the current desktop view.

Only EventQueue's dispatch thread may call this method.

Parameters:
component - AWT Component to take a screen shot of
Returns:
a BufferedImage representing component
Throws:
IllegalArgumentException - if component == null; component's width and height are not greater than zero
IllegalStateException - if calling thread is not EventQueue's dispatch thread
AWTException - if the platform configuration does not allow low-level input control. This exception is always thrown when GraphicsEnvironment.isHeadless() returns true
SecurityException - if createRobot permission is not granted

take

public static BufferedImage take(Component component,
                                 Rectangle region)
                          throws IllegalArgumentException,
                                 IllegalStateException,
                                 AWTException,
                                 SecurityException
Takes a screen shot of that part of the desktop whose area is the region relative to where component lies. Any other gui elements in this area, including ones which may lie on top of component, will be included, since the result always reflects the current desktop view.

Only EventQueue's dispatch thread may call this method.

Parameters:
component - AWT Component to take a screen shot of
region - the Rectangle relative to component that will be captured
Returns:
a BufferedImage representing component
Throws:
IllegalArgumentException - if component == null; component's width and height are not greater than zero; region == null
IllegalStateException - if calling thread is not EventQueue's dispatch thread
AWTException - if the platform configuration does not allow low-level input control. This exception is always thrown when GraphicsEnvironment.isHeadless() returns true
SecurityException - if createRobot permission is not granted

take

public static BufferedImage take(JComponent jcomponent)
                          throws IllegalArgumentException,
                                 IllegalStateException
Takes a screen shot of just jcomponent (no other gui elements will be present in the result).

Only EventQueue's dispatch thread may call this method.

Parameters:
jcomponent - Swing JComponent to take a screen shot of
Returns:
a BufferedImage representing jcomponent
Throws:
IllegalArgumentException - if jcomponent == null
IllegalStateException - if calling thread is not EventQueue's dispatch thread

take

public static BufferedImage take(JComponent jcomponent,
                                 Rectangle region)
                          throws IllegalArgumentException,
                                 IllegalStateException
Takes a screen shot of just the specified region of jcomponent (no other gui elements will be present in the result).

Only EventQueue's dispatch thread may call this method.

Parameters:
jcomponent - Swing JComponent to take a screen shot of
region - the Rectangle relative to jcomponent that will be captured
Returns:
a BufferedImage representing the region within jcomponent
Throws:
IllegalArgumentException - if jcomponent == null; region == null
IllegalStateException - if calling thread is not EventQueue's dispatch thread

write

public static void write(BufferedImage image,
                         String filePath)
                  throws IllegalArgumentException,
                         IllegalStateException,
                         IOException
Calls write(image, new File(filePath)).

Parameters:
image - the BufferedImage to be written
filePath - path of the File that will write image to
Throws:
IllegalArgumentException - if image == null; filePath is blank
IllegalStateException - if calling thread is not EventQueue's dispatch thread
IOException - if an I/O problem occurs

write

public static void write(BufferedImage image,
                         File file)
                  throws IllegalArgumentException,
                         IllegalStateException,
                         IOException
Calls write(image, getGraphicsFormat(file), file).

Parameters:
image - the BufferedImage to be written
file - the File that will write image to
Throws:
IllegalArgumentException - if image or file is null
IllegalStateException - if calling thread is not EventQueue's dispatch thread
IOException - if an I/O problem occurs

write

public static void write(BufferedImage image,
                         String formatName,
                         File file)
                  throws IllegalArgumentException,
                         IllegalStateException,
                         IOException
Writes image to file in the format specified by formatName.

Warning: a side effect of this method is that it will create any needed parent directories of file if they are not already existing.

Parameters:
image - the BufferedImage to be written
formatName - the graphics file format (e.g. "pnj", "jpeg", etc); must be in the same set of values supported by the formatName arg of ImageIO.write(RenderedImage, String, File)
file - the File that will write image to
Throws:
IllegalArgumentException - if image == null; type is blank; file == null
IllegalStateException - if calling thread is not EventQueue's dispatch thread
IOException - if an I/O problem occurs

getGraphicsFormat

private static String getGraphicsFormat(File file)
                                 throws IllegalArgumentException
Returns the name of the graphics format stored in file.

This is assumed to be file's extension, if it exists. Otherwise, if file has no extension, then formatNameDefault is returned.

Any thread may call this method.

Parameters:
file - the File whose graphics format needs to be determined
Throws:
IllegalArgumentException - if file == null