blob: 896d97f9372c44cf9e5b95737f0703e567d14b3f [file] [log] [blame]
/* Copyright (C) 2000 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.awt.image;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import gnu.gcj.awt.Buffers;
/**
* @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
*/
public class IndexColorModel extends ColorModel
{
private byte[] r;
private byte[] g;
private byte[] b;
private byte[] a;
private int[] argb;
private byte[] cmap;
private int start;
private int transparent;
private int size;
public IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b)
{
super(bits, nArray(bits, 3),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
false, // no transparency
false, // no premultiplied
Transparency.OPAQUE,
Buffers.smallestAppropriateTransferType(bits));
this.r = r;
this.g = g;
this.b = b;
this.size = size;
}
public IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b,
int transparent)
{
super(bits, nArray(bits, 4),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
true, // has transparency
false,
Transparency.BITMASK,
Buffers.smallestAppropriateTransferType(bits));
this.r = r;
this.g = g;
this.b = b;
this.transparent = transparent;
this.size = size;
}
public IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b,
byte[] a)
{
super(bits, nArray(bits, 4),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
true, // has transparency
false,
Transparency.BITMASK,
Buffers.smallestAppropriateTransferType(bits));
this.r = r;
this.g = g;
this.b = b;
this.a = a;
this.size = size;
}
public IndexColorModel(int bits, int size, byte[] cmap, int start,
boolean hasAlpha)
{
super(bits, nArray(bits, hasAlpha ? 4 : 3),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
hasAlpha,
false,
hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE,
Buffers.smallestAppropriateTransferType(bits));
this.cmap = cmap;
this.start = start;
this.size = size;
}
public IndexColorModel(int bits, int size, byte[] cmap, int start,
boolean hasAlpha, int transparent,
int transferType)
{
super(bits, nArray(bits, hasAlpha ? 4 : 3),
ColorSpace.getInstance(ColorSpace.CS_sRGB),
hasAlpha,
false,
hasAlpha ?
Transparency.TRANSLUCENT :
((transparent < 0) ?
Transparency.OPAQUE :
Transparency.BITMASK),
transferType);
this.cmap = cmap;
this.start = start;
this.size = size;
}
public final int getMapSize()
{
return size;
}
public final int getTransparentPixel()
{
return transparent;
}
public final void getReds(byte r[])
{
if (this.r == null) calcRGBArrays();
System.arraycopy(this.r, 0, r, 0, getMapSize());
}
public final void getGreens(byte g[])
{
if (this.g == null) calcRGBArrays();
System.arraycopy(this.g, 0, g, 0, getMapSize());
}
public final void getBlues(byte b[])
{
if (this.b == null) calcRGBArrays();
System.arraycopy(this.b, 0, b, 0, getMapSize());
}
public final void getAlphas(byte a[])
{
if (this.a == null) calcAlphaArray();
System.arraycopy(this.a, 0, a, 0, getMapSize());
}
public final void getRGBs(int rgb[])
{
if (this.argb == null) calcARGBArray();
System.arraycopy(this.argb, 0, rgb, 0, getMapSize());
}
public int getRed(int pixel)
{
try
{
return r[pixel];
}
catch (NullPointerException npe)
{
calcRGBArrays();
return r[pixel];
}
}
public int getGreen(int pixel)
{
try
{
return g[pixel];
}
catch (NullPointerException npe)
{
calcRGBArrays();
return g[pixel];
}
}
public int getBlue(int pixel)
{
try
{
return b[pixel];
}
catch (NullPointerException npe)
{
calcRGBArrays();
return b[pixel];
}
}
public int getAlpha(int pixel)
{
try
{
return a[pixel];
}
catch (NullPointerException npe)
{
calcAlphaArray();
return a[pixel];
}
}
private void calcRGBArrays() {
int j=0;
boolean hasAlpha = hasAlpha();
r = new byte[size];
g = new byte[size];
b = new byte[size];
if (hasAlpha) a = new byte[size];
for (int i=0; i<size; i++)
{
r[i] = cmap[j++];
g[i] = cmap[j++];
b[i] = cmap[j++];
if (hasAlpha()) a[i] = cmap[j++];
}
}
private void calcAlphaArray()
{
int transparency = getTransparency();
switch (transparency)
{
case Transparency.OPAQUE:
case Transparency.BITMASK:
a = nArray((byte) 255, size);
if (transparency == Transparency.BITMASK)
a[transparent] = 0;
break;
case Transparency.TRANSLUCENT:
calcRGBArrays();
}
}
private void calcARGBArray()
{
int mapSize = getMapSize();
argb = new int[mapSize];
for (int p=0; p<mapSize; p++) argb[p] = getRGB(p);
}
public int getRed(Object inData)
{
return getRed(getPixelFromArray(inData));
}
public int getGreen(Object inData)
{
return getGreen(getPixelFromArray(inData));
}
public int getBlue(Object inData)
{
return getBlue(getPixelFromArray(inData));
}
public int getAlpha(Object inData)
{
return getAlpha(getPixelFromArray(inData));
}
public int getRGB(Object inData)
{
return getRGB(getPixelFromArray(inData));
}
public Object getDataElements(int rgb, Object pixel)
{
int av, rv, gv, bv;
// using 8 bit values
av = (rgb >>> 24) & 0xff;
rv = (rgb >>> 16) & 0xff;
gv = (rgb >>> 8) & 0xff;
bv = (rgb >>> 0) & 0xff;
int pixelValue = getPixelValue(av, rv, gv, bv);
/* In this color model, the whole pixel fits in the first element
of the array. */
DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
buffer.setElem(0, pixelValue);
return Buffers.getData(buffer);
}
private int getPixelValue(int av, int rv, int gv, int bv)
{
if (r == null) calcRGBArrays();
if (a == null) calcAlphaArray();
int minDAlpha = 1<<8;
int minDRGB = (1<<8)*(1<<8)*3;
int pixelValue = -1;
for (int i=0; i<size; i++)
{
int dAlpha = Math.abs(av-(a[i]&0xff));
if (dAlpha > minDAlpha) continue;
int dR = rv-(r[i]&0xff);
int dG = gv-(g[i]&0xff);
int dB = bv-(b[i]&0xff);
int dRGB = dR*dR + dG*dG + dB*dB;
if (dRGB >= minDRGB) continue;
pixelValue = i;
minDRGB = dRGB;
}
return pixelValue;
}
public int[] getComponents(int pixel, int[] components, int offset)
{
int numComponents = getNumComponents();
if (components == null) components = new int[offset + numComponents];
components[offset++] = (r[pixel]&0xff);
components[offset++] = (g[pixel]&0xff);
components[offset++] = (b[pixel]&0xff);
if (hasAlpha()) components[offset++] = (a[pixel]&0xff);
return components;
}
public final int[] getComponents(Object pixel, int[] components,
int offset)
{
return getComponents(getPixelFromArray(pixel), components, offset);
}
public int getDataElement(int[] components, int offset)
{
int r = components[offset++];
int g = components[offset++];
int b = components[offset++];
int a = hasAlpha() ? components[offset++] : 255;
return getPixelValue(a, r, g, b);
}
public Object getDataElements(int[] components, int offset, Object pixel)
{
int pixelValue = getDataElement(components, offset);
/* In this color model, the whole pixel fits in the first element
of the array. */
DataBuffer buffer = Buffers.createBuffer(transferType, pixel, 1);
buffer.setElem(0, pixelValue);
return Buffers.getData(buffer);
}
public SampleModel createCompatibleSampleModel(int w, int h)
{
int[] bandOffsets = {0};
return new ComponentSampleModel(transferType, w, h,
1, // pixel stride
w, // scanline stride
bandOffsets);
}
}