import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.swing.*; import javax.imageio.*; import java.net.*; import java.io.*; /** * Represents an image that can be manipulated without a thorough understanding * of the built-in image classes. Performance (in terms of memory and speed) is sacrificed in order to provide * simplified access to pixel data. Allows direct read/write access to individual pixels * and a factory method for creating EasyBufferedImages from files. The image always * appears as either a gray-scale image, an RGB image or an RGBA image. The data is * never packed or interleaved (at least with respect to the get/set pixel methods). *
* Please note that grayscale processing of a color image always maintains the color information of the image while * altering the intensity channel. To perform operations on a purely gray-scale image, convert any color * images to grayscale prior to processing. *
* Since the EasyBufferedImage class is a sub-class of Image and BufferedImage, it * is fully integrated into the standard Swing libraries for viewing and manipulation. * To create an EasyBufferedImage you must use the factory method shown below: *
* where the filename is a String representing an image file in either GIF, PNG, or JPEG
* formats. The following code fragment is an example of how to invert a gray-scale image:
* EasyBufferedImage image = EasyBufferedImage.createImage(filename);
* @see Image
* @see BufferedImage
*
* @author Kenny Hunt, University of Wisconsin - Lacrosse
* @author Jeff Ondich, Carleton College -- fixed the confusion between RED and GRAY, and added show(String,int,int).
*/
public class EasyBufferedImage extends BufferedImage implements Serializable
{
private static final long serialVersionUID = 456L;
public static final int GRAY = 4, RED = 0, GREEN = 1, BLUE = 2, ALPHA = 3;
public static final int JPEG = 0, GIF = 1, PNG = 2;
private static final String[] TYPES = {"JPEG", "GIF", "PNG"};
private static int windowCount = 0;
/**
* Returns a String array listing the file formats supported by this class.
* @param none
* @return an array of strings listing the supported file formats.
*/
public String[] getSupportedFormats() {
return TYPES;
}
public static EasyBufferedImage createImage(BufferedImage image) {
return toBufferedImage(image);
}
/**
* Returns an EasyBufferedImage object by reading the image file
* specified by the filename. The format of the file may be any
* one of GIF, PNG, or JPEG. This is a factory method to create
* EasyBufferedImages. There is no direct constructor access.
*
* int[] pixels = image.getPixels1D(EasyBufferedImage.GRAY);
* for(int i=0; i < pixels.length; i++) {
* pixels[i] = 255-pixels[i];
* }
* image.setPixels(pixels);
*
* @param filename the name of the file to load. * @return the EasyBufferedImage stored in the file. * @throws FileNotFoundException * @see Image * @see BufferedImage */ public static EasyBufferedImage createImage(String filename) throws FileNotFoundException { File file = new File(filename); if(!file.exists()) throw new FileNotFoundException(filename); return toBufferedImage(Toolkit.getDefaultToolkit().createImage(filename)); } public static EasyBufferedImage createImage(File file) throws IOException, FileNotFoundException { if(!file.exists()) throw new FileNotFoundException(file.getName()); return toBufferedImage(ImageIO.read(file)); } /** * Returns an EasyBufferedImage object by reading the image * specified by the url. The format of the file may be any * one of GIF, PNG, or JPEG. This is a factory method to create * EasyBufferedImages. There is no direct constructor access. *
* @param url is the URL of an image file to load. * @return the EasyBufferedImage stored in the file. * @see Image * @see BufferedImage */ public static EasyBufferedImage createImage(URL url) { return toBufferedImage(Toolkit.getDefaultToolkit().createImage(url)); } /** * Returns an EasyBufferedImage object represented by the specified pixels. * The dimensions of the pixel array must be [height][width][bands] where bands may * be either 1 (gray-scale) or 3 (red-green-blue). * This is a factory method to create EasyBufferedImages. There is no direct constructor access. *
* @param pixels is an array of [height][width][bands] pixels that represents the image. * @return An EasyBufferedImage representation of the pixels. * @throws IllegalArgumentException if pixels is null * @see Image * @see BufferedImage */ public static EasyBufferedImage createImage(int[][][] pixels) { if(pixels == null) throw new IllegalArgumentException("null pixels array"); // create the BufferedImage (doesn't include transparency!) EasyBufferedImage result = new EasyBufferedImage(pixels[0].length, pixels.length, BufferedImage.TYPE_INT_RGB); result.setPixels(pixels); return result; } /** * Returns an EasyBufferedImage object represented by the specified pixels. * The dimensions of the pixel array must be [height][width] and is assumed * to be gray-scale. * This is a factory method to create EasyBufferedImages. There is no direct constructor access. *
* @param pixels is an array of [height][width] pixels that represents the image. * @return An EasyBufferedImage representation of the pixels. * @throws IllegalArgumentException if pixels is null * @see Image * @see BufferedImage */ public static EasyBufferedImage createImage(int[][] pixels) { if(pixels == null) throw new IllegalArgumentException("null pixels array"); // create the BufferedImage (doesn't include transparency!) EasyBufferedImage result = new EasyBufferedImage(pixels[0].length, pixels.length, BufferedImage.TYPE_INT_RGB); result.setPixels(pixels, RED); result.setPixels(pixels, GREEN); result.setPixels(pixels, BLUE); return result; } /** * Returns an EasyBufferedImage object represented by the specified pixels. * The dimensions of the pixel array must be [height * width] and layed out in * row-major format. The image is assumed to be gray-scale. * This is a factory method to create EasyBufferedImages. There is no direct constructor access. *
* @param pixels is an array of [height * width] pixels that represents the image. * @param height is the height (in pixels) of the image. * @param width is the width (in pixels) of the image. * @return An EasyBufferedImage representation of the pixels. * @throws IllegalArgumentException if pixels is null or the length is not width * height. * @see Image * @see BufferedImage */ public static EasyBufferedImage createImage(int[] pixels, int width, int height) { if(pixels == null) { throw new IllegalArgumentException("null pixels array"); } else if((width * height) != pixels.length) { throw new IllegalArgumentException("pixels dimensions doesn't match width/height parameters"); } if(pixels == null) throw new IllegalArgumentException("null pixels array"); // create the BufferedImage (doesn't include transparency!) EasyBufferedImage result = new EasyBufferedImage(width, height, BufferedImage.TYPE_INT_RGB); result.setPixels(pixels, RED); result.setPixels(pixels, GREEN); result.setPixels(pixels, BLUE); return result; } private EasyBufferedImage(int w, int h, int type) { super(w, h, type); } /** * Returns the value of v clamped to the range 0-255. * This is a convenience method for working with image pixel values. *
* @param v is the value of a pixel to be clamped. * @return the value v clamped to the range 0-255. */ public static int clamp(double v) { if(v < 0) return 0; else if(v > 255) return 255; else return (int)v; } /** * Returns an EasyBufferedImage object that is a gray-scale copy * of the calling image. *
* @param None * @return an EasyBufferedImage that is a gray-scale copy of the caller. */ public EasyBufferedImage copyToGrayScale() { EasyBufferedImage result = new EasyBufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_BYTE_GRAY); WritableRaster input = getRaster(); WritableRaster output = result.getRaster(); for(int row=0; row < input.getHeight(); row++) { for(int col=0; col < input.getWidth(); col++) { int red = input.getSample(col, row, 0); int green = input.getSample(col, row, 1); int blue = input.getSample(col, row, 2); output.setSample(col, row, 0, clamp((red+green+blue)/3.0)); } } return result; } private static EasyBufferedImage toBufferedImage(Image image) { // make sure that the Image is loaded (images can be loaded asynchronously) image = new ImageIcon(image).getImage(); // create the BufferedImage (doesn't include transparency!) EasyBufferedImage result = new EasyBufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB); // Draw the input onto the BufferedImage and return Graphics g = result.createGraphics(); g.drawImage(image, 0, 0, null); g.dispose(); return result; } /** * Returns a 3D array of pixel values. The dimensions of the array correspond * to the [height][width][bands] of the EasyBufferedImage. The number of bands * will be 1 for a gray-scale or binary image, 3 for a color image without * transparency, and 4 for a color image with transparency. The bands are (in * order) RED (or GRAY), GREEN, BLUE, ALPHA. Pixel values are in the range 0-255. *
* @param None
* @return an array of pixels accessed.
*/
public int[][][] getPixels3D() {
int width = getWidth();
int height = getHeight();
int bands = getSampleModel().getNumBands();
int[][][] pixels = new int[height][width][bands];
WritableRaster raster = getRaster();
for(int i=0; i
* where the AlphaValue is a percentage value in the range [0..100] and serves as a brightness control. Values in the range
* [0..1) will darken the image while values above 1 will brighten the input image. This application also saves the processed
* file in GIF format to a file named "Sample.gif".
* java EasyBufferedImage ImageFileName AlphaValue
* @param args is an array of two strings. The first is the filename of the file to process and the second is a perctage value to brighten/darken an image.
* @throws IOException.
*/
public static void main(String[] args) throws IOException {
EasyBufferedImage image = EasyBufferedImage.createImage(args[0]);
double alpha = Double.parseDouble(args[1]);
EasyBufferedImage copy = image.copy();
image.show("Original Image");
int[][] data = image.getPixels2D(EasyBufferedImage.RED);
for(int i=0; i
public static void main(String[] args) throws IOException
{
EasyBufferedImage image = EasyBufferedImage.createImage(args[0]);
double alpha = Double.parseDouble(args[1]);
EasyBufferedImage copy = image.copy();
int[][] data = image.getPixels2D(EasyBufferedImage.RED);
for(int i=0; i < image.getHeight(); i++)
{
for(int j=0; j < image.getWidth(); j++)
{
data[i][j] = clamp(data[i][j] * alpha);
}
}
image.setPixels(data, EasyBufferedImage.RED);
data = image.getPixels2D(EasyBufferedImage.GREEN);
for(int i=0; i < image.getHeight(); i++)
{
for(int j=0; j < image.getWidth(); j++)
{
data[i][j] = clamp(data[i][j] * alpha);
}
}
image.setPixels(data, EasyBufferedImage.GREEN);
data = image.getPixels2D(EasyBufferedImage.BLUE);
for(int i=0; i < image.getHeight(); i++){
for(int j=0; j < image.getWidth(); j++){
data[i][j] = clamp(data[i][j] * alpha);
}
}
image.setPixels(data, EasyBufferedImage.BLUE);
image.show(args[0]);
data = copy.getPixels2D(EasyBufferedImage.GRAY);
for(int i=0; i < copy.getHeight(); i++){
for(int j=0; j < copy.getWidth(); j++){
data[i][j] = clamp(data[i][j] * alpha);
}
}
copy.setPixels(data, EasyBufferedImage.GRAY);
copy.show("GRAY SCALE PROCESSING");
image.save("Sample.gif", EasyBufferedImage.GIF);
}