summaryrefslogtreecommitdiffstats
path: root/awt/java/awt/image/IndexColorModel.java
diff options
context:
space:
mode:
Diffstat (limited to 'awt/java/awt/image/IndexColorModel.java')
-rw-r--r--awt/java/awt/image/IndexColorModel.java1080
1 files changed, 1080 insertions, 0 deletions
diff --git a/awt/java/awt/image/IndexColorModel.java b/awt/java/awt/image/IndexColorModel.java
new file mode 100644
index 0000000..0b06acd
--- /dev/null
+++ b/awt/java/awt/image/IndexColorModel.java
@@ -0,0 +1,1080 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Igor V. Stolyarov
+ * @version $Revision$
+ */
+
+package java.awt.image;
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.math.BigInteger;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class IndexColorModel represents a color model in which the color values
+ * of the pixels are read from a palette.
+ *
+ * @since Android 1.0
+ */
+public class IndexColorModel extends ColorModel {
+
+ /**
+ * The color map.
+ */
+ private int colorMap[]; // Color Map
+
+ /**
+ * The map size.
+ */
+ private int mapSize; // Color Map size
+
+ /**
+ * The transparent index.
+ */
+ private int transparentIndex; // Index of fully transparent pixel
+
+ /**
+ * The gray palette.
+ */
+ private boolean grayPalette; // Color Model has Color Map with Gray Pallete
+
+ /**
+ * The valid bits.
+ */
+ private BigInteger validBits; // Specify valid Color Map values
+
+ /**
+ * The Constant CACHESIZE.
+ */
+ private static final int CACHESIZE = 20; // Cache size. Cache used for
+
+ // improving performace of selection
+ // nearest color in Color Map
+
+ /**
+ * The cachetable.
+ */
+ private final int cachetable[] = new int[CACHESIZE * 2]; // Cache table -
+
+ // used for
+
+ // storing RGB values and that appropriate indices
+ // in the Color Map
+
+ /**
+ * The next insert idx.
+ */
+ private int nextInsertIdx = 0; // Next index for insertion into Cache table
+
+ /**
+ * The total inserted.
+ */
+ private int totalInserted = 0; // Number of inserted values into Cache table
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param cmap
+ * the array that gives the color mapping.
+ * @param start
+ * the start index of the color mapping data within the cmap
+ * array.
+ * @param transferType
+ * the transfer type (primitive java type to use for the
+ * components).
+ * @param validBits
+ * a list of which bits represent valid colormap values, or null
+ * if all are valid.
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ */
+ public IndexColorModel(int bits, int size, int cmap[], int start, int transferType,
+ BigInteger validBits) {
+
+ super(bits, IndexColorModel.createBits(true), ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ true, false, Transparency.OPAQUE, validateTransferType(transferType));
+
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ transparentIndex = -1;
+
+ if (validBits != null) {
+ for (int i = 0; i < mapSize; i++) {
+ if (!validBits.testBit(i)) {
+ this.validBits = validBits;
+ }
+ break;
+ }
+ }
+
+ transparency = Transparency.OPAQUE;
+ int alphaMask = 0xff000000;
+ int alpha = 0;
+
+ for (int i = 0; i < mapSize; i++, start++) {
+ colorMap[i] = cmap[start];
+ alpha = cmap[start] & alphaMask;
+
+ if (alpha == alphaMask) {
+ continue;
+ }
+ if (alpha == 0) {
+ if (transparentIndex < 0) {
+ transparentIndex = i;
+ }
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ } else if (alpha != alphaMask && transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+
+ }
+ checkPalette();
+
+ }
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param cmap
+ * the array that gives the color mapping.
+ * @param start
+ * the start index of the color mapping data within the cmap
+ * array.
+ * @param hasalpha
+ * whether this color model uses alpha.
+ * @param trans
+ * the transparency supported, @see java.awt.Transparency.
+ * @param transferType
+ * the transfer type (primitive java type to use for the
+ * components).
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ */
+ public IndexColorModel(int bits, int size, int cmap[], int start, boolean hasalpha, int trans,
+ int transferType) {
+
+ super(bits, IndexColorModel.createBits(hasalpha || (trans >= 0)), ColorSpace
+ .getInstance(ColorSpace.CS_sRGB), (hasalpha || (trans >= 0)), false,
+ Transparency.OPAQUE, validateTransferType(transferType));
+
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ if (trans >= 0 && trans < mapSize) {
+ transparentIndex = trans;
+ transparency = Transparency.BITMASK;
+ } else {
+ transparentIndex = -1;
+ transparency = Transparency.OPAQUE;
+ }
+
+ int alphaMask = 0xff000000;
+ int alpha = 0;
+
+ for (int i = 0; i < mapSize; i++, start++) {
+ if (transparentIndex == i) {
+ colorMap[i] = cmap[start] & 0x00ffffff;
+ continue;
+ }
+ if (hasalpha) {
+ alpha = cmap[start] & alphaMask;
+ colorMap[i] = cmap[start];
+
+ if (alpha == alphaMask) {
+ continue;
+ }
+ if (alpha == 0) {
+ if (trans < 0) {
+ trans = i;
+ }
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ } else if (alpha != 0 && transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+ } else {
+ colorMap[i] = alphaMask | cmap[start];
+ }
+ }
+ checkPalette();
+
+ }
+
+ /**
+ * Instantiates a new index color model by building the color map from
+ * arrays of red, green, blue, and alpha values.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param r
+ * the array giving the red components of the entries in the
+ * color map.
+ * @param g
+ * the array giving the green components of the entries in the
+ * color map.
+ * @param b
+ * the array giving the blue components of the entries in the
+ * color map.
+ * @param a
+ * the array giving the alpha components of the entries in the
+ * color map.
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ * @throws ArrayIndexOutOfBoundsException
+ * if the size of one of the component arrays is less than the
+ * size of the color map.
+ */
+ public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[], byte a[]) {
+
+ super(bits, IndexColorModel.createBits(true), ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ true, false, Transparency.OPAQUE, validateTransferType(ColorModel
+ .getTransferType(bits)));
+
+ createColorMap(size, r, g, b, a, -1);
+ checkPalette();
+ }
+
+ /**
+ * Instantiates a new index color model by building the color map from
+ * arrays of red, green, and blue values.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param r
+ * the array giving the red components of the entries in the
+ * color map.
+ * @param g
+ * the array giving the green components of the entries in the
+ * color map.
+ * @param b
+ * the array giving the blue components of the entries in the
+ * color map.
+ * @param trans
+ * the transparency supported, @see java.awt.Transparency.
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ * @throws ArrayIndexOutOfBoundsException
+ * if the size of one of the component arrays is less than the
+ * size of the color map.
+ */
+ public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[], int trans) {
+
+ super(bits, IndexColorModel.createBits((trans >= 0)), ColorSpace
+ .getInstance(ColorSpace.CS_sRGB), (trans >= 0), false, Transparency.OPAQUE,
+ validateTransferType(ColorModel.getTransferType(bits)));
+
+ createColorMap(size, r, g, b, null, trans);
+ checkPalette();
+ }
+
+ /**
+ * Instantiates a new index color model by building the color map from
+ * arrays of red, green, and blue values.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param r
+ * the array giving the red components of the entries in the
+ * color map.
+ * @param g
+ * the array giving the green components of the entries in the
+ * color map.
+ * @param b
+ * the array giving the blue components of the entries in the
+ * color map.
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ * @throws ArrayIndexOutOfBoundsException
+ * if the size of one of the component arrays is less than the
+ * size of the color map.
+ */
+ public IndexColorModel(int bits, int size, byte r[], byte g[], byte b[]) {
+ super(bits, IndexColorModel.createBits(false), ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ false, false, Transparency.OPAQUE, validateTransferType(ColorModel
+ .getTransferType(bits)));
+
+ createColorMap(size, r, g, b, null, -1);
+ checkPalette();
+ }
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param cmap
+ * the array that gives the color mapping.
+ * @param start
+ * the start index of the color mapping data within the cmap
+ * array.
+ * @param hasalpha
+ * whether this color model uses alpha.
+ * @param trans
+ * the transparency supported, @see java.awt.Transparency.
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ */
+ public IndexColorModel(int bits, int size, byte cmap[], int start, boolean hasalpha, int trans) {
+
+ super(bits, IndexColorModel.createBits(hasalpha || (trans >= 0)), ColorSpace
+ .getInstance(ColorSpace.CS_sRGB), (hasalpha || (trans >= 0)), false,
+ Transparency.OPAQUE, validateTransferType(ColorModel.getTransferType(bits)));
+
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ transparentIndex = -1;
+
+ transparency = Transparency.OPAQUE;
+ int alpha = 0xff000000;
+
+ for (int i = 0; i < mapSize; i++) {
+ colorMap[i] = (cmap[start++] & 0xff) << 16 | (cmap[start++] & 0xff) << 8
+ | (cmap[start++] & 0xff);
+ if (trans == i) {
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ if (hasalpha) {
+ start++;
+ }
+ continue;
+ }
+ if (hasalpha) {
+ alpha = cmap[start++] & 0xff;
+ if (alpha == 0) {
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ if (trans < 0) {
+ trans = i;
+ }
+ }
+ } else {
+ if (alpha != 0xff && transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+ }
+ alpha <<= 24;
+ }
+ colorMap[i] |= alpha;
+ }
+
+ if (trans >= 0 && trans < mapSize) {
+ transparentIndex = trans;
+ }
+ checkPalette();
+
+ }
+
+ /**
+ * Instantiates a new index color model.
+ *
+ * @param bits
+ * the array of component masks.
+ * @param size
+ * the size of the color map.
+ * @param cmap
+ * the array that gives the color mapping.
+ * @param start
+ * the start index of the color mapping data within the cmap
+ * array.
+ * @param hasalpha
+ * whether this color model uses alpha.
+ * @throws IllegalArgumentException
+ * if the size of the color map is less than one.
+ */
+ public IndexColorModel(int bits, int size, byte cmap[], int start, boolean hasalpha) {
+
+ this(bits, size, cmap, start, hasalpha, -1);
+ }
+
+ @Override
+ public Object getDataElements(int[] components, int offset, Object pixel) {
+ int rgb = (components[offset] << 16) | (components[offset + 1]) << 8
+ | components[offset + 2];
+ if (hasAlpha) {
+ rgb |= components[offset + 3] << 24;
+ } else {
+ rgb |= 0xff000000;
+ }
+ return getDataElements(rgb, pixel);
+ }
+
+ @Override
+ public synchronized Object getDataElements(int rgb, Object pixel) {
+ int red = (rgb >> 16) & 0xff;
+ int green = (rgb >> 8) & 0xff;
+ int blue = rgb & 0xff;
+ int alpha = rgb >>> 24;
+ int pixIdx = 0;
+
+ for (int i = 0; i < totalInserted; i++) {
+ int idx = i * 2;
+ if (rgb == cachetable[idx]) {
+ return createDataObject(cachetable[idx + 1], pixel);
+ }
+ }
+
+ if (!hasAlpha && grayPalette) {
+ int grey = (red * 77 + green * 150 + blue * 29 + 128) >>> 8;
+ int minError = 255;
+ int error = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ error = Math.abs((colorMap[i] & 0xff) - grey);
+ if (error < minError) {
+ pixIdx = i;
+ if (error == 0) {
+ break;
+ }
+ minError = error;
+ }
+ }
+ } else if (alpha == 0 && transparentIndex > -1) {
+ pixIdx = transparentIndex;
+ } else {
+ int minAlphaError = 255;
+ int minError = 195075; // 255^2 + 255^2 + 255^2
+ int alphaError;
+ int error = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ int pix = colorMap[i];
+ if (rgb == pix) {
+ pixIdx = i;
+ break;
+ }
+ alphaError = Math.abs(alpha - (pix >>> 24));
+ if (alphaError <= minAlphaError) {
+ minAlphaError = alphaError;
+
+ int buf = ((pix >> 16) & 0xff) - red;
+ error = buf * buf;
+
+ if (error < minError) {
+ buf = ((pix >> 8) & 0xff) - green;
+ error += buf * buf;
+
+ if (error < minError) {
+ buf = (pix & 0xff) - blue;
+ error += buf * buf;
+
+ if (error < minError) {
+ pixIdx = i;
+ minError = error;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ cachetable[nextInsertIdx] = rgb;
+ cachetable[nextInsertIdx + 1] = pixIdx;
+
+ nextInsertIdx = (nextInsertIdx + 2) % (CACHESIZE * 2);
+ if (totalInserted < CACHESIZE) {
+ totalInserted++;
+ }
+
+ return createDataObject(pixIdx, pixel);
+ }
+
+ /**
+ * Converts an image from indexed to RGB format.
+ *
+ * @param raster
+ * the raster containing the source image.
+ * @param forceARGB
+ * whether to use the default RGB color model.
+ * @return the buffered image.
+ * @throws IllegalArgumentException
+ * if the raster is not compatible with this color model.
+ */
+ public BufferedImage convertToIntDiscrete(Raster raster, boolean forceARGB) {
+
+ if (!isCompatibleRaster(raster)) {
+ // awt.265=The raster argument is not compatible with this
+ // IndexColorModel
+ throw new IllegalArgumentException(Messages.getString("awt.265")); //$NON-NLS-1$
+ }
+
+ ColorModel model;
+ if (forceARGB || transparency == Transparency.TRANSLUCENT) {
+ model = ColorModel.getRGBdefault();
+ } else if (transparency == Transparency.BITMASK) {
+ model = new DirectColorModel(25, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x01000000);
+ } else {
+ model = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
+ }
+
+ int w = raster.getWidth();
+ int h = raster.getHeight();
+
+ WritableRaster distRaster = model.createCompatibleWritableRaster(w, h);
+
+ int minX = raster.getMinX();
+ int minY = raster.getMinY();
+
+ Object obj = null;
+ int pixels[] = null;
+
+ for (int i = 0; i < h; i++, minY++) {
+ obj = raster.getDataElements(minX, minY, w, 1, obj);
+ if (obj instanceof byte[]) {
+ byte ba[] = (byte[])obj;
+ if (pixels == null) {
+ pixels = new int[ba.length];
+ }
+ for (int j = 0; j < ba.length; j++) {
+ pixels[j] = colorMap[ba[j] & 0xff];
+ }
+ } else if (obj instanceof short[]) {
+ short sa[] = (short[])obj;
+ if (pixels == null) {
+ pixels = new int[sa.length];
+ }
+ for (int j = 0; j < sa.length; j++) {
+ pixels[j] = colorMap[sa[j] & 0xffff];
+ }
+ }
+ if (obj instanceof int[]) {
+ int ia[] = (int[])obj;
+ if (pixels == null) {
+ pixels = new int[ia.length];
+ }
+ for (int j = 0; j < ia.length; j++) {
+ pixels[j] = colorMap[ia[j]];
+ }
+ }
+
+ distRaster.setDataElements(0, i, w, 1, pixels);
+ }
+
+ return new BufferedImage(model, distRaster, false, null);
+ }
+
+ /**
+ * Gets the valid pixels.
+ *
+ * @return the valid pixels.
+ */
+ public BigInteger getValidPixels() {
+ return validBits;
+ }
+
+ @Override
+ public String toString() {
+ // The output format based on 1.5 release behaviour.
+ // It could be reveled such way:
+ // BufferedImage bi = new BufferedImage(1, 1,
+ // BufferedImage.TYPE_BYTE_INDEXED);
+ // ColorModel cm = bi.getColorModel();
+ // System.out.println(cm.toString());
+ String str = "IndexColorModel: #pixel_bits = " + pixel_bits + //$NON-NLS-1$
+ " numComponents = " + numComponents + " color space = " + cs + //$NON-NLS-1$ //$NON-NLS-2$
+ " transparency = "; //$NON-NLS-1$
+
+ if (transparency == Transparency.OPAQUE) {
+ str = str + "Transparency.OPAQUE"; //$NON-NLS-1$
+ } else if (transparency == Transparency.BITMASK) {
+ str = str + "Transparency.BITMASK"; //$NON-NLS-1$
+ } else {
+ str = str + "Transparency.TRANSLUCENT"; //$NON-NLS-1$
+ }
+
+ str = str + " transIndex = " + transparentIndex + " has alpha = " + //$NON-NLS-1$ //$NON-NLS-2$
+ hasAlpha + " isAlphaPre = " + isAlphaPremultiplied; //$NON-NLS-1$
+
+ return str;
+ }
+
+ @Override
+ public int[] getComponents(Object pixel, int components[], int offset) {
+ int pixIdx = -1;
+ if (pixel instanceof byte[]) {
+ byte ba[] = (byte[])pixel;
+ pixIdx = ba[0] & 0xff;
+ } else if (pixel instanceof short[]) {
+ short sa[] = (short[])pixel;
+ pixIdx = sa[0] & 0xffff;
+ } else if (pixel instanceof int[]) {
+ int ia[] = (int[])pixel;
+ pixIdx = ia[0];
+ } else {
+ // awt.219=This transferType is not supported by this color model
+ throw new UnsupportedOperationException(Messages.getString("awt.219")); //$NON-NLS-1$
+ }
+
+ return getComponents(pixIdx, components, offset);
+ }
+
+ @Override
+ public WritableRaster createCompatibleWritableRaster(int w, int h) {
+ WritableRaster raster;
+ if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
+ raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w, h, 1, pixel_bits, null);
+ } else if (pixel_bits <= 8) {
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 1, null);
+ } else if (pixel_bits <= 16) {
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, w, h, 1, null);
+ } else {
+ // awt.266=The number of bits in a pixel is greater than 16
+ throw new UnsupportedOperationException(Messages.getString("awt.266")); //$NON-NLS-1$
+ }
+
+ return raster;
+ }
+
+ @Override
+ public boolean isCompatibleSampleModel(SampleModel sm) {
+ if (sm == null) {
+ return false;
+ }
+
+ if (!(sm instanceof MultiPixelPackedSampleModel) && !(sm instanceof ComponentSampleModel)) {
+ return false;
+ }
+
+ if (sm.getTransferType() != transferType) {
+ return false;
+ }
+ if (sm.getNumBands() != 1) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4) {
+ return new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, w, h, pixel_bits);
+ }
+ int bandOffsets[] = new int[1];
+ bandOffsets[0] = 0;
+ return new ComponentSampleModel(transferType, w, h, 1, w, bandOffsets);
+
+ }
+
+ @Override
+ public boolean isCompatibleRaster(Raster raster) {
+ int sampleSize = raster.getSampleModel().getSampleSize(0);
+ return (raster.getTransferType() == transferType && raster.getNumBands() == 1 && (1 << sampleSize) >= mapSize);
+ }
+
+ @Override
+ public int getDataElement(int components[], int offset) {
+ int rgb = (components[offset] << 16) | (components[offset + 1]) << 8
+ | components[offset + 2];
+
+ if (hasAlpha) {
+ rgb |= components[offset + 3] << 24;
+ } else {
+ rgb |= 0xff000000;
+ }
+
+ int pixel;
+
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte ba[] = (byte[])getDataElements(rgb, null);
+ pixel = ba[0] & 0xff;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ short sa[] = (short[])getDataElements(rgb, null);
+ pixel = sa[0] & 0xffff;
+ break;
+ default:
+ // awt.267=The transferType is invalid
+ throw new UnsupportedOperationException(Messages.getString("awt.267")); //$NON-NLS-1$
+ }
+
+ return pixel;
+ }
+
+ /**
+ * Gets the color map.
+ *
+ * @param rgb
+ * the destination array where the color map is written.
+ */
+ public final void getRGBs(int rgb[]) {
+ System.arraycopy(colorMap, 0, rgb, 0, mapSize);
+ }
+
+ /**
+ * Gets the red component of the color map.
+ *
+ * @param r
+ * the destination array.
+ */
+ public final void getReds(byte r[]) {
+ for (int i = 0; i < mapSize; i++) {
+ r[i] = (byte)(colorMap[i] >> 16);
+ }
+ }
+
+ /**
+ * Gets the green component of the color map.
+ *
+ * @param g
+ * the destination array.
+ */
+ public final void getGreens(byte g[]) {
+ for (int i = 0; i < mapSize; i++) {
+ g[i] = (byte)(colorMap[i] >> 8);
+ }
+ }
+
+ /**
+ * Gets the blue component of the color map.
+ *
+ * @param b
+ * the destination array.
+ */
+ public final void getBlues(byte b[]) {
+ for (int i = 0; i < mapSize; i++) {
+ b[i] = (byte)colorMap[i];
+ }
+ }
+
+ /**
+ * Gets the alpha component of the color map.
+ *
+ * @param a
+ * the destination array.
+ */
+ public final void getAlphas(byte a[]) {
+ for (int i = 0; i < mapSize; i++) {
+ a[i] = (byte)(colorMap[i] >> 24);
+ }
+ }
+
+ @Override
+ public int[] getComponents(int pixel, int components[], int offset) {
+ if (components == null) {
+ components = new int[offset + numComponents];
+ }
+
+ components[offset + 0] = getRed(pixel);
+ components[offset + 1] = getGreen(pixel);
+ components[offset + 2] = getBlue(pixel);
+ if (hasAlpha && (components.length - offset) > 3) {
+ components[offset + 3] = getAlpha(pixel);
+ }
+
+ return components;
+ }
+
+ /**
+ * Checks if the specified pixel is valid for this color model.
+ *
+ * @param pixel
+ * the pixel.
+ * @return true, if the pixel is valid.
+ */
+ public boolean isValid(int pixel) {
+ if (validBits == null) {
+ return (pixel >= 0 && pixel < mapSize);
+ }
+ return (pixel < mapSize && validBits.testBit(pixel));
+ }
+
+ @Override
+ public final int getRed(int pixel) {
+ return (colorMap[pixel] >> 16) & 0xff;
+ }
+
+ @Override
+ public final int getRGB(int pixel) {
+ return colorMap[pixel];
+ }
+
+ @Override
+ public final int getGreen(int pixel) {
+ return (colorMap[pixel] >> 8) & 0xff;
+ }
+
+ @Override
+ public final int getBlue(int pixel) {
+ return colorMap[pixel] & 0xff;
+ }
+
+ @Override
+ public final int getAlpha(int pixel) {
+ return (colorMap[pixel] >> 24) & 0xff;
+ }
+
+ @Override
+ public int[] getComponentSize() {
+ return bits.clone();
+ }
+
+ /**
+ * Checks if this color model validates pixels.
+ *
+ * @return true, if all pixels are valid, otherwise false.
+ */
+ public boolean isValid() {
+ return (validBits == null);
+ }
+
+ @Override
+ public void finalize() {
+ // TODO: implement
+ return;
+ }
+
+ /**
+ * Gets the index that represents the transparent pixel.
+ *
+ * @return the index that represents the transparent pixel.
+ */
+ public final int getTransparentPixel() {
+ return transparentIndex;
+ }
+
+ @Override
+ public int getTransparency() {
+ return transparency;
+ }
+
+ /**
+ * Gets the size of the color map.
+ *
+ * @return the map size.
+ */
+ public final int getMapSize() {
+ return mapSize;
+ }
+
+ /**
+ * Creates the color map.
+ *
+ * @param size
+ * the size.
+ * @param r
+ * the r.
+ * @param g
+ * the g.
+ * @param b
+ * the b.
+ * @param a
+ * the a.
+ * @param trans
+ * the trans.
+ */
+ private void createColorMap(int size, byte r[], byte g[], byte b[], byte a[], int trans) {
+ if (size < 1) {
+ // awt.264=Size of the color map is less than 1
+ throw new IllegalArgumentException(Messages.getString("awt.264")); //$NON-NLS-1$
+ }
+
+ mapSize = size;
+ colorMap = new int[mapSize];
+ if (trans >= 0 && trans < mapSize) {
+ transparency = Transparency.BITMASK;
+ transparentIndex = trans;
+ } else {
+ transparency = Transparency.OPAQUE;
+ transparentIndex = -1;
+ }
+ int alpha = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ colorMap[i] = ((r[i] & 0xff) << 16) | ((g[i] & 0xff) << 8) | (b[i] & 0xff);
+
+ if (trans == i) {
+ continue;
+ }
+
+ if (a == null) {
+ colorMap[i] |= 0xff000000;
+ } else {
+ alpha = a[i] & 0xff;
+ if (alpha == 0xff) {
+ colorMap[i] |= 0xff000000;
+ } else if (alpha == 0) {
+ if (transparency == Transparency.OPAQUE) {
+ transparency = Transparency.BITMASK;
+ }
+ if (transparentIndex < 0) {
+ transparentIndex = i;
+ }
+ } else {
+ colorMap[i] |= (a[i] & 0xff) << 24;
+ if (transparency != Transparency.TRANSLUCENT) {
+ transparency = Transparency.TRANSLUCENT;
+ }
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * This method checking, if Color Map has Gray palette.
+ */
+ private void checkPalette() {
+ grayPalette = false;
+ if (transparency > Transparency.OPAQUE) {
+ return;
+ }
+ int rgb = 0;
+
+ for (int i = 0; i < mapSize; i++) {
+ rgb = colorMap[i];
+ if (((rgb >> 16) & 0xff) != ((rgb >> 8) & 0xff) || ((rgb >> 8) & 0xff) != (rgb & 0xff)) {
+ return;
+ }
+ }
+ grayPalette = true;
+ }
+
+ /**
+ * Construction an array pixel representation.
+ *
+ * @param colorMapIdx
+ * the index into Color Map.
+ * @param pixel
+ * the pixel
+ * @return the pixel representation array.
+ */
+ private Object createDataObject(int colorMapIdx, Object pixel) {
+ if (pixel == null) {
+ switch (transferType) {
+ case DataBuffer.TYPE_BYTE:
+ byte[] ba = new byte[1];
+ ba[0] = (byte)colorMapIdx;
+ pixel = ba;
+ break;
+ case DataBuffer.TYPE_USHORT:
+ short[] sa = new short[1];
+ sa[0] = (short)colorMapIdx;
+ pixel = sa;
+ break;
+ default:
+ // awt.267=The transferType is invalid
+ throw new UnsupportedOperationException(Messages.getString("awt.267")); //$NON-NLS-1$
+ }
+ } else if (pixel instanceof byte[] && transferType == DataBuffer.TYPE_BYTE) {
+ byte ba[] = (byte[])pixel;
+ ba[0] = (byte)colorMapIdx;
+ pixel = ba;
+ } else if (pixel instanceof short[] && transferType == DataBuffer.TYPE_USHORT) {
+ short[] sa = (short[])pixel;
+ sa[0] = (short)colorMapIdx;
+ pixel = sa;
+ } else if (pixel instanceof int[]) {
+ int ia[] = (int[])pixel;
+ ia[0] = colorMapIdx;
+ pixel = ia;
+ } else {
+ // awt.268=The pixel is not a primitive array of type transferType
+ throw new ClassCastException(Messages.getString("awt.268")); //$NON-NLS-1$
+ }
+ return pixel;
+ }
+
+ /**
+ * Creates the bits.
+ *
+ * @param hasAlpha
+ * the has alpha.
+ * @return the int[].
+ */
+ private static int[] createBits(boolean hasAlpha) {
+
+ int numChannels;
+ if (hasAlpha) {
+ numChannels = 4;
+ } else {
+ numChannels = 3;
+ }
+
+ int bits[] = new int[numChannels];
+ for (int i = 0; i < numChannels; i++) {
+ bits[i] = 8;
+ }
+
+ return bits;
+
+ }
+
+ /**
+ * Validate transfer type.
+ *
+ * @param transferType
+ * the transfer type.
+ * @return the int.
+ */
+ private static int validateTransferType(int transferType) {
+ if (transferType != DataBuffer.TYPE_BYTE && transferType != DataBuffer.TYPE_USHORT) {
+ // awt.269=The transferType is not one of DataBuffer.TYPE_BYTE or
+ // DataBuffer.TYPE_USHORT
+ throw new IllegalArgumentException(Messages.getString("awt.269")); //$NON-NLS-1$
+ }
+ return transferType;
+ }
+
+ /**
+ * Checks if is gray palette.
+ *
+ * @return true, if is gray palette.
+ */
+ boolean isGrayPallete() {
+ return grayPalette;
+ }
+
+}