diff options
Diffstat (limited to 'libjava/java/awt/image/IndexColorModel.java')
| -rw-r--r-- | libjava/java/awt/image/IndexColorModel.java | 239 |
1 files changed, 232 insertions, 7 deletions
diff --git a/libjava/java/awt/image/IndexColorModel.java b/libjava/java/awt/image/IndexColorModel.java index 9ceb0bf0944..6791589032e 100644 --- a/libjava/java/awt/image/IndexColorModel.java +++ b/libjava/java/awt/image/IndexColorModel.java @@ -38,7 +38,29 @@ exception statement from your version. */ package java.awt.image; +import java.awt.color.ColorSpace; +import java.math.BigInteger; + /** + * Color model similar to pseudo visual in X11. + * + * This color model maps linear pixel values to actual RGB and alpha colors. + * Thus, pixel values are indexes into the color map. Each color component is + * an 8-bit unsigned value. + * + * The IndexColorModel supports a map of valid pixels, allowing the + * representation of holes in the the color map. The valid map is represented + * as a BigInteger where each bit indicates the validity of the map entry with + * the same index. + * + * Colors can have alpha components for transparency support. If alpha + * component values aren't given, color values are opaque. The model also + * supports a reserved pixel value to represent completely transparent colors, + * no matter what the actual color component values are. + * + * IndexColorModel supports anywhere from 1 to 16 bit index values. The + * allowed transfer types are DataBuffer.TYPE_BYTE and DataBuffer.TYPE_USHORT. + * * @author C. Brian Jones (cbj@gnu.org) */ public class IndexColorModel extends ColorModel @@ -47,6 +69,7 @@ public class IndexColorModel extends ColorModel private boolean opaque; private int trans = -1; private int[] rgb; + private BigInteger validBits = BigInteger.ZERO; /** * Each array much contain <code>size</code> elements. For each @@ -127,6 +150,9 @@ public class IndexColorModel extends ColorModel | (blues[i] & 0xff)); } } + + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); } /** @@ -140,6 +166,7 @@ public class IndexColorModel extends ColorModel * @param cmap packed color components * @param start the offset of the first color component in <code>cmap</code> * @param hasAlpha <code>cmap</code> has alpha values + * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. */ public IndexColorModel (int bits, int size, byte[] cmap, int start, boolean hasAlpha) @@ -148,25 +175,155 @@ public class IndexColorModel extends ColorModel } /** - * Each array much contain <code>size</code> elements. For each - * array, the i-th color is described by reds[i], greens[i], - * blues[i], alphas[i], unless alphas is not specified, then all the - * colors are opaque except for the transparent color. - * + * Construct an IndexColorModel from an array of red, green, blue, and + * optional alpha components. The component values are interleaved as RGB(A). + * * @param bits the number of bits needed to represent <code>size</code> colors * @param size the number of colors in the color map - * @param cmap packed color components + * @param cmap interleaved color components * @param start the offset of the first color component in <code>cmap</code> * @param hasAlpha <code>cmap</code> has alpha values * @param trans the index of the transparent color + * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. */ public IndexColorModel (int bits, int size, byte[] cmap, int start, boolean hasAlpha, int trans) { super (bits); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + opaque = !hasAlpha; + this.trans = trans; + + rgb = new int[size]; + if (hasAlpha) + { + for (int i = 0; i < size; i++) + rgb[i] = + // alpha + ((cmap[4 * i + 3 + start] & 0xff) << 24 + // red + | ((cmap[4 * i + start] & 0xff) << 16) + // green + | ((cmap[4 * i + 1 + start] & 0xff) << 8) + // blue + | (cmap[4 * i + 2 + start] & 0xff)); + } + else + { + for (int i = 0; i < size; i++) + rgb[i] = (0xff000000 + // red + | ((cmap[3 * i + start] & 0xff) << 16) + // green + | ((cmap[3 * i + 1 + start] & 0xff) << 8) + // blue + | (cmap[3 * i + 2 + start] & 0xff)); + } + + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); + } + + /** + * Construct an IndexColorModel from an array of <code>size</code> packed + * colors. Each int element contains 8-bit red, green, blue, and optional + * alpha values packed in order. If hasAlpha is false, then all the colors + * are opaque except for the transparent color. + * + * @param bits the number of bits needed to represent <code>size</code> colors + * @param size the number of colors in the color map + * @param cmap packed color components + * @param start the offset of the first color component in <code>cmap</code> + * @param hasAlpha <code>cmap</code> has alpha values + * @param trans the index of the transparent color + * @param transferType DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT + * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. + * @throws IllegalArgumentException if transferType is something other than + * TYPE_BYTE or TYPE_USHORT. + */ + public IndexColorModel (int bits, int size, int[] cmap, int start, + boolean hasAlpha, int trans, int transferType) + { + super(bits * 4, // total bits, sRGB, four channels + nArray(bits, 4), // bits for each channel + ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB + true, // has alpha + false, // not premultiplied + TRANSLUCENT, transferType); + if (transferType != DataBuffer.TYPE_BYTE + && transferType != DataBuffer.TYPE_USHORT) + throw new IllegalArgumentException(); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); map_size = size; opaque = !hasAlpha; this.trans = trans; + + rgb = new int[size]; + if (!hasAlpha) + for (int i = 0; i < size; i++) + rgb[i] = cmap[i + start] | 0xff000000; + else + System.arraycopy(cmap, start, rgb, 0, size); + + // Generate a bigint with 1's for every pixel + validBits = validBits.setBit(size).subtract(BigInteger.ONE); + } + + /** + * Construct an IndexColorModel using a colormap with holes. + * + * The IndexColorModel is built from the array of ints defining the + * colormap. Each element contains red, green, blue, and alpha + * components. The ColorSpace is sRGB. The transparency value is + * automatically determined. + * + * This constructor permits indicating which colormap entries are valid, + * using the validBits argument. Each entry in cmap is valid if the + * corresponding bit in validBits is set. + * + * @param bits the number of bits needed to represent <code>size</code> colors + * @param size the number of colors in the color map + * @param cmap packed color components + * @param start the offset of the first color component in <code>cmap</code> + * @param transferType DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT + * @throws IllegalArgumentException if bits < 1, bits > 16, or size < 1. + * @throws IllegalArgumentException if transferType is something other than + * TYPE_BYTE or TYPE_USHORT. + */ + public IndexColorModel (int bits, int size, int[] cmap, int start, + int transferType, BigInteger validBits) + { + super(bits * 4, // total bits, sRGB, four channels + nArray(bits, 4), // bits for each channel + ColorSpace.getInstance(ColorSpace.CS_sRGB), // sRGB + true, // has alpha + false, // not premultiplied + TRANSLUCENT, transferType); + if (transferType != DataBuffer.TYPE_BYTE + && transferType != DataBuffer.TYPE_USHORT) + throw new IllegalArgumentException(); + if (bits > 16) + throw new IllegalArgumentException("bits > 16"); + if (size < 1) + throw new IllegalArgumentException("size < 1"); + map_size = size; + opaque = false; + this.trans = -1; + this.validBits = validBits; + + rgb = new int[size]; + if (!hasAlpha) + for (int i = 0; i < size; i++) + rgb[i] = cmap[i + start] | 0xff000000; + else + System.arraycopy(cmap, start, rgb, 0, size); } public final int getMapSize () @@ -279,11 +436,79 @@ public class IndexColorModel extends ColorModel return 0; } - //pixel_bits is number of bits to be in generated mask + /** + * Get the RGB color values of all pixels in the map using the default + * RGB color model. + * + * @param rgb The destination array. + */ + public final void getRGBs (int[] rgb) + { + System.arraycopy(this.rgb, 0, rgb, 0, map_size); + } + + //pixel_bits is number of bits to be in generated mask private int generateMask (int offset) { return (((2 << pixel_bits ) - 1) << (pixel_bits * offset)); } + /** Return true if pixel is valid, false otherwise. */ + public boolean isValid(int pixel) + { + return validBits.testBit(pixel); + } + + /** Return true if all pixels are valid, false otherwise. */ + public boolean isValid() + { + // Generate a bigint with 1's for every pixel + BigInteger allbits = new BigInteger("0"); + allbits.setBit(map_size); + allbits.subtract(new BigInteger("1")); + return allbits.equals(validBits); + } + + /** + * Returns a BigInteger where each bit represents an entry in the color + * model. If the bit is on, the entry is valid. + */ + public BigInteger getValidPixels() + { + return validBits; + } + + /** + * Construct a BufferedImage with rgb pixel values from a Raster. + * + * Constructs a new BufferedImage in which each pixel is an RGBA int from + * a Raster with index-valued pixels. If this model has no alpha component + * or transparent pixel, the type of the new BufferedImage is TYPE_INT_RGB. + * Otherwise the type is TYPE_INT_ARGB. If forceARGB is true, the type is + * forced to be TYPE_INT_ARGB no matter what. + * + * @param raster The source of pixel values. + * @param forceARGB True if type must be TYPE_INT_ARGB. + * @return New BufferedImage with RBGA int pixel values. + */ + public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB) + { + int type = forceARGB ? BufferedImage.TYPE_INT_ARGB + : ((opaque && trans == -1) ? BufferedImage.TYPE_INT_RGB : + BufferedImage.TYPE_INT_ARGB); + + // FIXME: assuming that raster has only 1 band since pixels are supposed + // to be int indexes. + // FIXME: it would likely be more efficient to fetch a complete array, + // but it would take much more memory. + // FIXME: I'm not sure if transparent pixels or alpha values need special + // handling here. + BufferedImage im = new BufferedImage(raster.width, raster.height, type); + for (int x = raster.minX; x < raster.width + raster.minX; x++) + for (int y = raster.minY; y < raster.height + raster.minY; y++) + im.setRGB(x, y, rgb[raster.getSample(x, y, 0)]); + + return im; + } } |
