/** * ImageManipulator.java * * Class for pixel manipulating images -- creating images * from pixel data with a memory image source and grabbing * pixel's from an existing image with a pixel grabber. * * @ Authors: * * @ Wayne Witzel * @ University of Utah, Cosmic Ray Physics * @ * @ Copyright 1999, All Rights Reserved */ import java.awt.image.*; import java.awt.*; public class ImageManipulator { MemoryImageSource source; MediaTracker tracker; Component owner; ColorModel colorModel; int[] pixels; Image image; int bgColor; int width; int height; boolean doWrapping = false; // wrap when considering pixels out of bounds // create a blank memory image of the given size public ImageManipulator(Component owner, int width, int height, int bgColor) { this.bgColor = bgColor; this.owner = owner; tracker = new MediaTracker(owner); clear(width, height); colorModel = new DirectColorModel(32, 255, 255, 255, 255); } // create a ImageManipulator initialize to the picture of the given image public ImageManipulator(Component owner, Image image, int bgColor) { this.bgColor = bgColor; this.owner = owner; tracker = new MediaTracker(owner); loadImage(image); } // set if you want out of bounds pixels to wrap around or be ignored // (default is not to wrap). public void setWrapping(boolean doWrapping) { this.doWrapping = doWrapping; } public boolean isWrapping() { return doWrapping; } // clear and resize public void clear(int width, int height) { if (pixels == null || (pixels.length < width * height)) pixels = new int[width * height]; if (this.width != width || this.height != height) { this.width = width; this.height = height; if (colorModel != null) source = new MemoryImageSource(width, height, colorModel, pixels, 0, width); else source = new MemoryImageSource(width, height, pixels, 0, width); source.setAnimated(true); if (image != null) { tracker.removeImage(image); image.flush(); } image = owner.createImage(source); } for (int i = 0; i < pixels.length; i++) pixels[i] = bgColor; } // clear the entire image with the background color (may be transparent) public void clear() { for (int i = 0; i < pixels.length; i++) pixels[i] = bgColor; } public void clear(Rectangle bounds) { clear(bounds.x, bounds.y, bounds.width, bounds.height); } // clear a rectangular region with the background color (may be transparent) public void clear(int left, int top, int width, int height) { for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) setPixel(left + x, top + y, bgColor); } private Point translation = new Point(0, 0); public void translate(int x, int y) // move the origin { translation.x += x; translation.y += y; } public void setTranslation(int x, int y) { translation.x = x; translation.y = y; } public Point getTranslation() { return translation; } public void setPixel(int x, int y, int value) { try { pixels[getIndex(x, y)] = value; } catch (IndexOutOfBoundsException e) { /* ignore if out of range */ } } public void setPixel(int index, int value) // see getIndex { pixels[index] = value; } public int getPixel(int x, int y) { try { return pixels[getIndex(x, y)]; } catch (IndexOutOfBoundsException e) { return 0; } } public int getPixel(int index) // see getIndex { return pixels[index]; } public int[] getPixels() { return pixels; } public int getIndex(int x, int y) throws IndexOutOfBoundsException { x += translation.x; y += translation.y; if (doWrapping) { x %= width; y %= height; return (y >= 0 ? y : y + height)*width + (x >= 0 ? x : x + width); } else if (x >= 0 && x < width && y >= 0 && y < height) return y*width + x; else throw new IndexOutOfBoundsException(); } public Image getImage() { source.newPixels(); tracker.addImage(image, 0); try{tracker.waitForID(0);} catch(InterruptedException e) {} return image; } public int getWidth() { return width; } public int getHeight() { return height; } public void loadImage(Image imgSource) { int width = imgSource.getWidth(owner); int height = imgSource.getHeight(owner); if (pixels == null || (pixels.length < width * height)) pixels = new int[width * height]; if (this.width != width || this.height != height) { this.width = width; this.height = height; source = null; } PixelGrabber grabber = new PixelGrabber(imgSource, 0, 0, width, height, pixels, 0, width); try { grabber.grabPixels(); } catch (InterruptedException e) { } colorModel = grabber.getColorModel(); if (source == null) { if (image != null) image.flush(); source = new MemoryImageSource(width, height, colorModel, pixels, 0, width); source.setAnimated(true); image = owner.createImage(source); } } // invert the image vertically public void invertVertical() { int tmp; for (int y = 0; y < height/2; y++) { for (int x = 0; x < width; x++) { tmp = getPixel(x, y); setPixel(x, y, getPixel(x, height - y - 1)); setPixel(x, height - y - 1, tmp); } } } // invert the image horizontal public void invertHorizontal() { int tmp; for (int x = 0; x < width/2; x++) { for (int y = 0; y < height; y++) { tmp = getPixel(x, y); setPixel(x, y, getPixel(width - x - 1, y)); setPixel(width - x - 1, y, tmp); } } } public void makeBackgroundTransparent() { for (int i = 0; i < pixels.length; i++) if (pixels[i] == bgColor) pixels[i] = 0; } // flush images resources -- this should be done if many // ImageManipulator's are created public void flush() { image.flush(); } }