echopointng.image.ImageKit Maven / Gradle / Ivy
Show all versions of ibis-echo2 Show documentation
package echopointng.image;
/*
* This file is part of the Echo Point Project. This project is a collection
* of Components that have extended the Echo Web Application Framework.
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*/
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.awt.image.RGBImageFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import nextapp.echo2.app.AwtImageReference;
import nextapp.echo2.app.Color;
import nextapp.echo2.app.Extent;
import nextapp.echo2.app.ImageReference;
import nextapp.echo2.app.ResourceImageReference;
import echopointng.util.ColorKit;
import echopointng.util.collections.ConcurrentReaderHashMap;
/**
* A utility to class to help with ImageReference manipulation
*
* @author Brad Baker
*/
public class ImageKit {
/** You can use this object as an valid ImageObserver */
public static final java.awt.Component imageObserver = new java.awt.Component() {
};
/** You can use this object as an valid MediaTracker */
public static final java.awt.MediaTracker imageMediaTracker = new java.awt.MediaTracker(imageObserver);
/* our media tracker ids */
private static int mediaTrackerIDs = 0;
/* our image cache */
private static Map imageCache = new ConcurrentReaderHashMap();
private static Map coloredImageCache = new ConcurrentReaderHashMap();
/** not instantiable */
private ImageKit() {
}
/**
* Creates an ImageReference that is width * height in dimensions and has
* the specified background color.
*/
public static ImageReference createImageRef(Color background, int width, int height) {
java.awt.Color clrBackground = ColorKit.makeAwtColor(background,java.awt.Color.white);
//
// create our Image
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setColor(clrBackground);
g.fillRect(0, 0, width, height);
return new AwtImageReference(image);
}
/**
* Returns an transparent ImageReference that is width * height in dimensions
*/
public static ImageReference getTransparentImageRef(int width, int height) {
return new ResourceImageReference("/echopointng/ui/resource/images/transparent1x1.gif", new Extent(width), new Extent(height));
}
/**
* Returns an ImageReference that is width * height in dimensions with the specified
* background color. The returned ImageReference is cached for fast
* retrieval but it uses SoftReferences so it will degrade in low
* memory conditions.
*/
public static ImageReference getColoredImageRef(Color backgroundColor, int width, int height) {
String name = "" + backgroundColor.getRgb() + "w:" + width + "h:" + height;
SoftReference softRef = (SoftReference) coloredImageCache.get(name);
AwtImageReference awtImageRef = (AwtImageReference) (softRef == null ? null : softRef.get());
if (awtImageRef == null) {
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(ColorKit.makeAwtColor(backgroundColor,java.awt.Color.lightGray));
g.fillRect(0,0,width,height);
g.dispose();
awtImageRef = new AwtImageReference(image);
coloredImageCache.put(name,new SoftReference(awtImageRef));
}
return awtImageRef;
}
/**
* This method will return copy a source Image and return
* a new BufferedImage.
*
* This differs from makeBufferedImage() in that it gauruntees
* to make a new copy of the image data whereas makeBufferedImage()
* will return the same object if its already a BufferedImage.
*
* @param srcImage the source Image
* @return - a completely new BufferedImage
*/
public static BufferedImage copyImage(Image srcImage) {
if (srcImage == null)
throw new IllegalArgumentException("The srcImage must be non null");
if (! waitForImage(srcImage))
throw new IllegalStateException("The srcImage could not be loaded");
int width = srcImage.getWidth(imageObserver);
int height = srcImage.getHeight(imageObserver);
boolean hasAlpha = hasAlphaChannel(srcImage);
// Create a buffered image with a format that's compatible with the screen
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = getColorModel(srcImage).getTransparency();
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(width, height, transparency);
} catch (Exception e) {
// The system does not have a screen
}
if (bimage == null) {
int type = (hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
bimage = new BufferedImage(width,height,type);
}
Graphics2D g = bimage.createGraphics();
g.drawImage(srcImage, 0,0,width,height,imageObserver);
g.dispose();
return bimage;
}
/**
* Private function to load a cached image from disk or the memory cache
* for a given String or URL. Soft references are used.
*/
private static Image _loadImageFromCache(Object imageLocation, int width, int height) {
SoftReference imageRef = (SoftReference) imageCache.get(imageLocation);
Image image = (Image) ((imageRef == null) ? null : imageRef.get());
if (image == null) {
if (imageLocation instanceof URL) {
if (width >= 0 && height >= 0)
image = loadImage((URL) imageLocation, width, height);
else
image = loadImage((URL) imageLocation);
}
if (imageLocation instanceof String) {
if (width >= 0 && height >= 0)
image = loadImage((String) imageLocation, width, height);
else
image = loadImage((String) imageLocation);
}
imageRef = new SoftReference(image);
imageCache.put(imageLocation,imageRef);
}
return image;
}
/**
* Loads an image file from disk and returns an java.awt.Image. The
* image is guaranteed to be fully loaded when this method returns and
* is not contained in any internal cache.
*
* @param imageFileName - the image file to be loaded
* @return Image - the loaded AWT image
*/
public static Image loadImage(String imageFileName) {
Image image = Toolkit.getDefaultToolkit().createImage(imageFileName);
if (!waitForImage(image))
return null;
return image;
}
/**
* Loads an image file from disk and returns an java.awt.Image, which
* is then cached. The image is guaranteed to be fully loaded when
* this method returns. Soft references are used so that the image
* cache can be reclaimed in low memory conditions.
*
* @param imageFileName - the image file to be loaded
* @return Image - the loaded AWT image
*/
public static Image loadCachedImage(String imageFileName) {
return _loadImageFromCache(imageFileName,-1,-1);
}
/**
* Loads an image file from disk and returns an java.awt.Image. The
* image is guaranteed to be fully loaded when this method returns and
* is not contained in any internal cache. The image will be
* scaled to the specified width and height.
*
* @param imageFileName - the image file to be loaded
* @param width - the width of the new image
* @param height - the height of the new image
* @return Image - the loaded AWT image
*/
public static Image loadImage(String imageFileName, int width, int height) {
Image image = Toolkit.getDefaultToolkit().createImage(imageFileName);
if (!waitForImage(image))
return null;
return makeBufferedImage(image, width, height);
}
/**
* Loads an image file from disk and returns an java.awt.Image, which
* is then cached. The image is guaranteed to be fully loaded when this
* method returns. Soft references are used so that the image cache can
* be reclaimed in low memory conditions.
*
* The image will be scaled to the specified width and height.
*
* @param imageFileName - the image file to be loaded
* @param width - the width of the new image
* @param height - the height of the new image
* @return Image - the loaded AWT image
*/
public static Image loadCachedImage(String imageFileName, int width, int height) {
return _loadImageFromCache(imageFileName,width,height);
}
/**
* Loads an image file from disk and returns an java.awt.Image. The
* image is guaranteed to be fully loaded when this method returns and
* is not contained in any internal cache.
*
* @param imageUrl - the image URL to be loaded
* @return Image - the loaded AWT image
*/
public static Image loadImage(URL imageUrl) {
Image image = Toolkit.getDefaultToolkit().createImage(imageUrl);
if (!waitForImage(image))
return null;
return image;
}
/**
* Loads an image file from disk and returns an java.awt.Image, which
* is then cached. The image is guaranteed to be fully loaded when
* this method returns. Soft references are used so that the image
* cache can be reclaimed in low memory conditions.
*
* @param imageUrl - the image URL to be loaded
* @return Image - the loaded AWT image
*/
public static Image loadCachedImage(URL imageUrl) {
return _loadImageFromCache(imageUrl,-1,-1);
}
/**
* Loads an image file from disk and returns an java.awt.Image. The
* image is guaranteed to be fully loaded when this method returns and
* is not contained in any internal cache. The image will be
* scaled to the specified width and height.
*
* @param imageUrl - the image URL to be loaded
* @param width - the width of the new image
* @param height - the height of the new image
* @return Image - the loaded AWT image
*/
public static Image loadImage(URL imageUrl, int width, int height) {
Image image = Toolkit.getDefaultToolkit().createImage(imageUrl);
if (!waitForImage(image))
return null;
return makeBufferedImage(image, width, height);
}
/**
* Loads an image file from disk and returns an java.awt.Image, which
* is then cached. The image is guaranteed to be fully loaded when
* this method returns. Soft references are used so that the image
* cache can be reclaimed in low memory conditions.
*
* The image will be scaled to the specified width and height.
*
* @param imageUrl - the image URL to be loaded
* @param width - the width of the new image
* @param height - the height of the new image
* @return Image - the loaded AWT image
*/
public static Image loadCachedImage(URL imageUrl, int width, int height) {
return _loadImageFromCache(imageUrl,width,height);
}
/**
* Loads an image file from a named Java resource and returns an
* java.awt.Image. The image is guaranteed to be fully loaded
* when this method returns and is not contained in any
* internal cache.
*
* @param imageResourceName - the image resource to be loaded
* @return Image - the loaded AWT image
*/
public static Image loadResourceImage(String imageResourceName) {
URL url = ImageKit.class.getResource(imageResourceName);
return loadImage(url);
}
/**
* Loads an image file from a named Java resource and returns an
* java.awt.Image which is then cached. The image is guaranteed to
* be fully loaded when this method returns. Soft references are used
* so that the image cache can be reclaimed in low memory conditions.
*
* @param imageResourceName - the image resource to be loaded
* @return Image - the loaded AWT image
*/
public static Image loadCachedResourceImage(String imageResourceName) {
URL url = ImageKit.class.getResource(imageResourceName);
return loadCachedImage(url);
}
/**
* Loads an image file from a named Java resource and returns an
* java.awt.Image. The image is guaranteed to be fully loaded
* when this method returns and is not contained in any
* internal cache. The image will be scaled to the specified
* width and height.
*
* @param imageResourceName - the image resource to be loaded
* @param width - the width of the new image
* @param height - the height of the new image
* @return Image - the loaded AWT image
*/
public static Image loadResourceImage(String imageResourceName, int width, int height) {
URL url = ImageKit.class.getResource(imageResourceName);
return loadImage(url,width,height);
}
/**
* Loads an image file from a named Java resource and returns an
* java.awt.Image which is then cached. The image is guaranteed to
* be fully loaded when this method returns The image will be scaled
* to the specified width and height.
*
* @param imageResourceName - the image resource to be loaded
* @param width - the width of the new image
* @param height - the height of the new image
* @return Image - the loaded AWT image
*/
public static Image loadCachedResourceImage(String imageResourceName, int width, int height) {
URL url = ImageKit.class.getResource(imageResourceName);
return loadCachedImage(url,width,height);
}
/**
* Returns a BufferedImage, that is same as the original
* java.awt.Image. Its smart about passing in BufferedImage objects
* and will simply return them unchanged.
*
* The image type will be BufferedImage.TYPE_INT_ARGB if it has
* an alpha channel other wise it will be BufferedImage.TYPE_INT_RGB
*
* @param srcImage Image - the image to be converted
* @return a BufferedImage
*/
public static BufferedImage makeBufferedImage(Image srcImage) {
if (!waitForImage(srcImage))
return null;
int iw = srcImage.getWidth(imageObserver);
int ih = srcImage.getHeight(imageObserver);
int type = hasAlphaChannel(srcImage) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
return makeBufferedImage(srcImage, iw, ih, type);
}
/**
* Returns a BufferedImage, that is same as the original
* java.awt.Image. Its smart about passing in BufferedImage objects
* and will simply return them unchanged.
*
* The image type will be BufferedImage.TYPE_INT_ARGB if it has
* an alpha channel other wise it will be BufferedImage.TYPE_INT_RGB
* type will be BufferedImage.TYPE_INT_ARGB.
*
* The image will be scaled to the width/height dimensions.
*
* @param srcImage - the image to be converted
* @param width - the width of the new image
* @param height - the height of the new image
* @return a BufferedImage
*/
public static BufferedImage makeBufferedImage(Image srcImage, int width, int height) {
if (!waitForImage(srcImage))
return null;
int type = hasAlphaChannel(srcImage) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
return makeBufferedImage(srcImage, width, height, type);
}
/**
* Returns a BufferedImage, that is same as the original
* java.awt.Image, scaled to width and height. Its smart about
* passing in BufferedImage objects and will simply return
* them unchanged.
*
* @param srcImage - the image to be converted
* @param width - the width of the new image
* @param height - the height of the new image
* @param imageType - can be on of BufferedImage types such as BufferedImage.TYPE_INT_ARGB
* @return a BufferedImage
*/
public static BufferedImage makeBufferedImage(Image srcImage, int width, int height, int imageType) {
if (! (srcImage instanceof BufferedImage)) {
if (!waitForImage(srcImage))
return null;
}
int iw = srcImage.getWidth(imageObserver);
int ih = srcImage.getHeight(imageObserver);
if (srcImage instanceof BufferedImage && iw == width && ih == height)
return (BufferedImage) srcImage;
BufferedImage bi = new BufferedImage(width, height, imageType);
Graphics2D g = bi.createGraphics();
g.drawImage(srcImage, 0, 0, width, height, imageObserver);
g.dispose();
return bi;
}
/**
* This method will return the ColorModel of an Image.
*
* @param srcImage the source Image
* @return - the ColorModel of the image
*/
public static ColorModel getColorModel(Image srcImage) {
// If buffered image, the color model is readily available
if (srcImage instanceof BufferedImage) {
BufferedImage bimage = (BufferedImage)srcImage;
return bimage.getColorModel();
}
// Use a pixel grabber to retrieve the image's color model;
// grabbing a single pixel is usually sufficient
PixelGrabber pg = new PixelGrabber(srcImage, 0, 0, 1, 1, false);
try {
pg.grabPixels();
} catch (InterruptedException e) {
}
ColorModel cm = pg.getColorModel();
return cm;
}
/**
* This method returns true if the provided Image has an alpha channel
*
* @param srcImage - the image to check for an alpha channel
* @return true if the provided Image has an alpha channel
*/
public static boolean hasAlphaChannel(Image srcImage) {
ColorModel cm = getColorModel(srcImage);
if (cm != null)
return cm.hasAlpha();
return
false;
}
/**
* Private filter class to examine each pixel and make some color another Color
* This leaves the alpha value intact.
*/
private static class ColorSwapImageFilter extends RGBImageFilter {
private int srcRGB = 0;
private int destRGB = 0;
private ColorSwapImageFilter(java.awt.Color srcColor, java.awt.Color destColor) {
srcRGB =((srcColor.getRed() & 0xFF) << 16) |
((srcColor.getGreen() & 0xFF) << 8) |
((srcColor.getBlue() & 0xFF) << 0);
destRGB =((destColor.getRed() & 0xFF) << 16) |
((destColor.getGreen() & 0xFF) << 8) |
((destColor.getBlue() & 0xFF) << 0);
canFilterIndexColorModel = true;
}
public final int filterRGB(int x, int y, int rgb) {
int currentColor = (rgb & 0x00FFFFFF);
if (currentColor == srcRGB) {
return ((rgb & 0xFF000000) | destRGB);
} else {
return rgb;
}
}
}
/**
* This will change all occurences of srcColor to destColor
* in the image. Any alpha valuews in the image will be
* left intact.
*
* This method works inline on the provided image. It does NOT make a copy of
* the source image.
*
* @param srcImage - the image to be transformed
* @param srcColor - the source color
* @param destColor - the dest color
* @return - a same image with the source and dest colors swapped.
*/
public static Image swapImageColors(Image srcImage, Color srcColor, Color destColor) {
if (srcColor == null)
throw new IllegalArgumentException("The srcColor must be non null");
if (destColor == null)
throw new IllegalArgumentException("The destColor must be non null");
java.awt.Color srcClr = ColorKit.makeAwtColor(srcColor,null);
java.awt.Color destClr = ColorKit.makeAwtColor(destColor,null);
ImageProducer ip = new FilteredImageSource(srcImage.getSource(), new ColorSwapImageFilter(srcClr,destClr));
Image returnImage = Toolkit.getDefaultToolkit().createImage(ip);
waitForImage(returnImage);
return returnImage;
}
/** private filter class to examine each pixel and make some color transparent */
private static class TransparencyImageFilter extends RGBImageFilter {
private int markerRGB = 0;
private int alphaRGB = 0;
private TransparencyImageFilter(java.awt.Color markerColor, int alpha) {
java.awt.Color alphaColor = new java.awt.Color(markerColor.getRed(),markerColor.getGreen(),markerColor.getBlue(),alpha);
alphaRGB = ((alpha & 0xFF) << 24) |
((markerColor.getRed() & 0xFF) << 16) |
((markerColor.getGreen() & 0xFF) << 8) |
((markerColor.getBlue() & 0xFF) << 0);
alphaRGB = alphaColor.getRGB();
markerRGB = markerColor.getRGB() | 0xFF000000;
canFilterIndexColorModel = true;
}
public final int filterRGB(int x, int y, int rgb) {
int currentColor = (rgb | 0xFF000000);
if (currentColor == markerRGB) {
return alphaRGB;
} else {
return rgb;
}
}
}
/**
* This will change the image so that any occurence of the specified color is fully transparent, ie
* has an alpha value of 0.
*
* This method works inline on the provided image. It does NOT make a copy of
* the source image.
*
* @param srcImage - the image to be transformed
* @param markerColor - the color to be made transparent
* @return - a new image with the specified color as fully transparent
*/
public static Image makeImageColorTransparent(Image srcImage, Color markerColor) {
return makeImageColorTransparent(srcImage,markerColor,0);
}
/**
* This will change the image so that any occurence of the specified color is changed to
* have an alpha value of 'alpha';
*
* This method works inline on the provided image. It does NOT make a copy of
* the source image.
*
* @param srcImage - the image to be transformed
* @param markerColor - the color to be made transparent
* @param alpha - an alpha value between 0 and 255
* @return - a same image with the specified color as having the alpha value
*/
public static Image makeImageColorTransparent(Image srcImage, Color markerColor, int alpha) {
if (alpha < 0 && alpha > 255)
throw new IllegalArgumentException("The alpha value must be between 0 and 255");
java.awt.Color awtTransClr = ColorKit.makeAwtColor(markerColor,null);
ImageProducer ip = new FilteredImageSource(srcImage.getSource(), new TransparencyImageFilter(awtTransClr,alpha));
Image returnImage = Toolkit.getDefaultToolkit().createImage(ip);
waitForImage(returnImage);
return returnImage;
}
public static BufferedImage makeImageGreyScale(Image srcImage) {
BufferedImage bufImage;
if (srcImage instanceof BufferedImage) {
bufImage = (BufferedImage) srcImage;
} else {
bufImage = makeBufferedImage(srcImage);
}
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp op = new ColorConvertOp(cs, null);
return op.filter(bufImage, null); }
/**
* Waits for an Image to be loaded by using a MediaTracker internally.
* @param srcImage - the source Image
* @return false if the image cannot be loaded or true if it is down.
*/
public static boolean waitForImage(Image srcImage) {
if (srcImage == null)
return false;
synchronized (imageObserver) {
mediaTrackerIDs++;
}
imageMediaTracker.addImage(srcImage, mediaTrackerIDs);
try {
imageMediaTracker.waitForID(mediaTrackerIDs);
} catch (Exception e) {
return false;
}
if (imageMediaTracker.isErrorID(mediaTrackerIDs))
return false;
return true;
}
/**
* Writes an AttributedString to an object output stream and saves
* all Serializable obejcts contained within it.
*
* @param out
* @param as
* @throws IOException
*/
public static void writeSerializedAttributedString(ObjectOutputStream out, AttributedString as) throws IOException {
if (as == null) {
// write a null marker
out.writeObject(null);
return;
}
AttributedCharacterIterator cit = as.getIterator();
StringBuffer buf = new StringBuffer();
for (char c = cit.first(); c != AttributedCharacterIterator.DONE; c = cit.next()) {
buf.append(c);
}
out.writeObject("nonnull");
out.writeObject(buf.toString());
cit = as.getIterator();
Set keys = cit.getAllAttributeKeys();
int keyCount = 0;
for (Iterator iter = keys.iterator(); iter.hasNext();) {
Object key = iter.next();
if (key instanceof Serializable) {
AttributedCharacterIterator.Attribute attr = (AttributedCharacterIterator.Attribute) key;
Object value = cit.getAttribute(attr);
if (value instanceof Serializable) {
keyCount++;
}
}
}
out.writeInt(keyCount);
for (Iterator iter = keys.iterator(); iter.hasNext();) {
Object key = iter.next();
if (key instanceof Serializable) {
AttributedCharacterIterator.Attribute attr = (AttributedCharacterIterator.Attribute) key;
Object value = cit.getAttribute(attr);
if (value instanceof Serializable) {
out.writeObject(attr);
out.writeObject(value);
}
}
}
}
/**
* Writes an Image out to a serialisation stream.
*
* Most of the code was taken from the Echo AwtImageReference, so kudos to
* NextApp.
*
* @param out the object output stream
* @param srcImage - the source Image
* @throws IOException if need be
*/
public static void writeSerializedImage(ObjectOutputStream out, Image srcImage) throws IOException {
if (srcImage == null) {
// has no image data
out.writeBoolean(false);
} else {
// has image data
out.writeBoolean(true);
int width = srcImage.getWidth(ImageKit.imageObserver);
int height = srcImage.getHeight(ImageKit.imageObserver);
out.writeInt(width);
out.writeInt(height);
int[] pixels = new int[width * height];
try {
PixelGrabber pg = new PixelGrabber(srcImage, 0, 0, width, height, pixels, 0, width);
pg.grabPixels();
if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
throw new IOException("Unable to serialize java.awt.image: PixelGrabber aborted.");
}
} catch (InterruptedException ex) {
throw new IOException("Unable to serialize java.awt.Image: PixelGrabber interrupted.");
}
out.writeObject(pixels);
}
}
/**
* Reads in a serialized AttributeString and restores all Serializable
* objects contained within it.
*
* @param in
* @return AttributedString - the new AttributedString
* @throws IOException
* @throws ClassNotFoundException
*/
public static AttributedString readSerializedAttributedString(ObjectInputStream in) throws IOException, ClassNotFoundException {
Object marker = in.readObject();
if (marker == null)
return null;
String s = (String) in.readObject();
AttributedString as = new AttributedString(s);
int keyCount = in.readInt();
for (int i = 0; i < keyCount; i++) {
AttributedCharacterIterator.Attribute attr = (AttributedCharacterIterator.Attribute) in.readObject();
Object value = in.readObject();
as.addAttribute(attr, value);
}
return as;
}
/**
* Reads an image in from a serilisation stream. It must have been written with the
* writeSerializedImage
method.
*
* Most of the code was taken from the Echo AwtImageReference, so kudos to
* NextApp.
*
* @param in
* @return Image
* @throws IOException
* @throws ClassNotFoundException
*/
public static Image readSerializedImage(ObjectInputStream in) throws IOException, ClassNotFoundException {
boolean hasImageData = in.readBoolean();
if (hasImageData) {
int width = in.readInt();
int height = in.readInt();
int[] pixels = (int[]) in.readObject();
if (pixels != null) {
ColorModel colorModel = ColorModel.getRGBdefault();
return Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(width, height, colorModel, pixels, 0, width));
}
}
return null;
}
/**
* This method mirrows the source image through the vertical
* plane, eg. the left become the right.
*
* This will work inline on the image if its a BufferedImage
* and will create a copy if its not.
*
* @param srcImage the source Image
* @return the image mirrowed
*/
public static Image mirrowImage(Image srcImage) {
BufferedImage bufferedImage = makeBufferedImage(srcImage);
AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-bufferedImage.getWidth(imageObserver), 0);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null);
return bufferedImage;
}
/**
* This method flips the source image through the horizontal
* plane, eg. the top become the bottom.
*
* This will work inline on the image if its a BufferedImage
* and will create a copy if its not.
*
* @param srcImage the source Image
* @return the image flipped
*/
public static Image flipImage(Image srcImage) {
BufferedImage bufferedImage = makeBufferedImage(srcImage);
// Flip the image horizontally
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -bufferedImage.getHeight(imageObserver));
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null);
return bufferedImage;
}
/**
* This method roteates the source image through the horizontal
* and vertical plane. This is the equivalent of rotating it
* through 180 degrees.
*
* This will work inline on the image if its a BufferedImage
* and will create a copy if its not.
*
* @param srcImage the source Image
* @return the image rotated 180 degrees.
*/
public static Image rotateImage(Image srcImage) {
BufferedImage bufferedImage = makeBufferedImage(srcImage);
// Flip the image vertically and horizontally;
// equivalent to rotating the image 180 degrees
AffineTransform tx = AffineTransform.getScaleInstance(-1, -1);
tx.translate(-bufferedImage.getWidth(imageObserver), -bufferedImage.getHeight(imageObserver));
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null);
return bufferedImage;
}
/**
* Called to enlarge an image by splicing it vertically (along the X axis)
* at x and filling the new section with a 1 pixel sample at x
*
* This method will only enlarge the image. If the new width is less than
* or equal to the current width, then the srcImage is returned.
*
*
* @param srcImage - the source Image
* @param x - the position to splice at
* @param newW - the new width of the image
* @return an image that is enlarged to the new width via splicing
*/
public static Image enlargeImageSpliceVert(Image srcImage, int x, int newW) {
int imgW = srcImage.getWidth(imageObserver);
int imgH = srcImage.getHeight(imageObserver);
if (newW <= imgW)
return srcImage;
if (x <= 0 || x >= imgW)
x = imgW / 2;
return _spliceImageInternal(srcImage,x,0,newW,imgH,imgW,imgH,true);
}
/**
* Called to enlarge an image by splicing it horizontally (along the Y axis)
* at y and filling the new section with a 1 pixel sample at y
*
* This method will only enlarge the image. If the new height is less than
* or equal to the current height, then the srcImage is returned.
*
* @param srcImage - the source Image
* @param y - the position to splice at
* @param newH - the new height of the image
* @return an image that is enlarged to the new height via splicing
*/
public static Image enlargeImageSpliceHoriz(Image srcImage, int y, int newH) {
int imgW = srcImage.getWidth(imageObserver);
int imgH = srcImage.getHeight(imageObserver);
if (newH <= imgH)
return srcImage;
if (y <= 0 || y >= imgH)
y = imgH / 2;
return _spliceImageInternal(srcImage,0,y,imgW,newH,imgW,imgH,false);
}
/*
* Called internally to splice an image vertically or horizontally. This
* will stretch to the newX, newY sizes if they are different to the
* source image, which is usually not what you want.
*/
private static Image _spliceImageInternal(Image srcImage, int x, int y, int newW, int newH, int imgW, int imgH, boolean verticallyFirst) {
x = (x <= 0) ? imgW/2 : x;
y = (y <= 0) ? imgH/2 : y;
int widthDiff = newW - imgW;
int heightDiff = newH - imgH;
int sx1 = 0; int sy1 = 0;
int sx2 = 0; int sy2 = 0;
int dx1 = 0; int dy1 = 0;
int dx2 = 0; int dy2 = 0;
BufferedImage bufImg = new BufferedImage(newW,newH,BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bufImg.createGraphics();
if (verticallyFirst) {
// --------------------------
// VERTICAL SPLICE
// --------------------------
//
// draw the repeated part!
sx1 = x; sy1 = 0;
sx2 = x+1; sy2 = imgH;
dx1 = x; dy1 = 0;
dx2 = x+1; dy2 = newH;
for (int i = 0; i < widthDiff; i++) {
g.drawImage(srcImage, dx1,dy1,dx2,dy2, sx1,sy1,sx2,sy2, imageObserver);
dx1 += 1;
dx2 += 1;
}
//
// draw the left hand side
sx1 = 0; sy1 = 0;
sx2 = x; sy2 = imgH;
dx1 = 0; dy1 = 0;
dx2 = x; dy2 = newH;
g.drawImage(srcImage, dx1,dy1,dx2,dy2, sx1,sy1,sx2,sy2, imageObserver);
//
// draw the right hand side
sx1 = x; sy1 = 0;
sx2 = imgW; sy2 = imgH;
dx1 = newW-(imgW-x); dy1 = 0;
dx2 = newW; dy2 = newH;
g.drawImage(srcImage, dx1,dy1,dx2,dy2, sx1,sy1,sx2,sy2, imageObserver);
} else {
// --------------------------
// HORIZONTAL SPLICE
// --------------------------
//
// draw the repeated part!
sx1 = 0; sy1 = y;
sx2 = imgW; sy2 = y+1;
dx1 = 0; dy1 = y;
dx2 = newW; dy2 = y+1;
for (int i = 0; i < heightDiff; i++) {
g.drawImage(srcImage, dx1,dy1,dx2,dy2, sx1,sy1,sx2,sy2, imageObserver);
dy1 += 1;
dy2 += 1;
}
//
// draw the left hand side
sx1 = 0; sy1 = 0;
sx2 = imgW; sy2 = y;
dx1 = 0; dy1 = 0;
dx2 = newW; dy2 = y;
g.drawImage(srcImage, dx1,dy1,dx2,dy2, sx1,sy1,sx2,sy2, imageObserver);
//
// draw the right hand side
sx1 = 0; sy1 = y;
sx2 = imgW; sy2 = imgH;
dx1 = 0; dy1 = newH-(imgH-y);
dx2 = newW; dy2 = newH;
g.drawImage(srcImage, dx1,dy1,dx2,dy2, sx1,sy1,sx2,sy2, imageObserver);
}
g.dispose();
return bufImg;
}
}