This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI [gui] Added java.awt.color work from GNU Classpath


Hi,

This adds the java.awt.color work done in GNU Classpath by Sven:

2004-11-06  Mark Wielaard  <mark@klomp.org>

       * Makefile.am (awt_java_source_files): Add new gnu/java/awt/color
       java source files.
       * Makefile.in: Regenerated.

2004-11-06  Sven de Marothy  <sven@physto.se>

       * gnu/java/awt/color/CieXyzConverter.java,
       gnu/java/awt/color/GrayScaleConverter.java,
       gnu/java/awt/color/SrgbConverter.java,
       gnu/java/awt/color/ClutProfileConverter.java,
       gnu/java/awt/color/LinearRGBConverter.java,
       gnu/java/awt/color/TagEntry.java,
       gnu/java/awt/color/ColorLookUpTable.java,
       gnu/java/awt/color/ProfileHeader.java,
       gnu/java/awt/color/ToneReproductionCurve.java,
       gnu/java/awt/color/ColorSpaceConverter.java,
       gnu/java/awt/color/PyccConverter.java,
       gnu/java/awt/color/GrayProfileConverter.java,
       gnu/java/awt/color/RgbProfileConverter.java:
       New files.
       * java/awt/color/ICC_ColorSpace.java,
       java/awt/color/ICC_Profile.java,
       java/awt/color/ICC_ProfileGray.java,
       java/awt/color/ICC_ProfileRGB.java:
       Implemented (sans PhotoYCC color space).

Committed to the gui branch.

Cheers,

Mark
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.361.2.56
diff -u -r1.361.2.56 Makefile.am
--- Makefile.am	2 Nov 2004 03:33:08 -0000	1.361.2.56
+++ Makefile.am	6 Nov 2004 18:50:45 -0000
@@ -965,6 +965,19 @@
 gnu/java/awt/EmbeddedWindow.java \
 gnu/java/awt/EmbeddedWindowSupport.java \
 gnu/java/awt/EventModifier.java \
+gnu/java/awt/color/CieXyzConverter.java \
+gnu/java/awt/color/ClutProfileConverter.java \
+gnu/java/awt/color/ColorLookUpTable.java \
+gnu/java/awt/color/ColorSpaceConverter.java \
+gnu/java/awt/color/GrayProfileConverter.java \
+gnu/java/awt/color/GrayScaleConverter.java \
+gnu/java/awt/color/LinearRGBConverter.java \
+gnu/java/awt/color/ProfileHeader.java \
+gnu/java/awt/color/PyccConverter.java \
+gnu/java/awt/color/RgbProfileConverter.java \
+gnu/java/awt/color/SrgbConverter.java \
+gnu/java/awt/color/TagEntry.java \
+gnu/java/awt/color/ToneReproductionCurve.java \
 gnu/java/awt/image/ImageDecoder.java \
 gnu/java/awt/image/XBMDecoder.java \
 gnu/java/awt/peer/EmbeddedWindowPeer.java \
Index: gnu/java/awt/color/CieXyzConverter.java
===================================================================
RCS file: gnu/java/awt/color/CieXyzConverter.java
diff -N gnu/java/awt/color/CieXyzConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/CieXyzConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,74 @@
+/* CieXyzConverter.java -- CieXyz conversion class
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * CieXyzConverter - converts to/from a D50-relative CIE XYZ color space.
+ * 
+ * The sRGB<->CIE XYZ conversions in SrgbConverter are used.
+ *
+ * @author Sven de Marothy
+ */
+public class CieXyzConverter implements ColorSpaceConverter
+{
+  public float[] toCIEXYZ(float[] in)
+  {
+    float[] out = new float[3];
+    System.arraycopy(in, 0, out, 0, 3);
+    return out;
+  }
+
+  public float[] fromCIEXYZ(float[] in)
+  {
+    float[] out = new float[3];
+    System.arraycopy(in, 0, out, 0, 3);
+    return out;
+  }
+
+  public float[] toRGB(float[] in)
+  {
+    return SrgbConverter.XYZtoRGB(in);
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    return SrgbConverter.RGBtoXYZ(in);
+  }
+}
Index: gnu/java/awt/color/ClutProfileConverter.java
===================================================================
RCS file: gnu/java/awt/color/ClutProfileConverter.java
diff -N gnu/java/awt/color/ClutProfileConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/ClutProfileConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,154 @@
+/* ClutProfileConverter.java -- Conversion routines for CLUT-Based profiles
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+
+
+/**
+ * ClutProfileConverter - conversions through a CLUT-based profile
+ *
+ * @author Sven de Marothy
+ */
+public class ClutProfileConverter implements ColorSpaceConverter
+{
+  private ColorLookUpTable toPCS;
+  private ColorLookUpTable fromPCS;
+  private int nChannels;
+
+  public ClutProfileConverter(ICC_Profile profile)
+  {
+    nChannels = profile.getNumComponents();
+
+    // Sun does not specifiy which rendering intent should be used,
+    // neither does the ICC v2 spec really. 
+    // Try intent 0
+    try
+      {
+	toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag);
+      }
+    catch (Exception e)
+      {
+	toPCS = null;
+      }
+
+    try
+      {
+	fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag);
+      }
+    catch (Exception e)
+      {
+	fromPCS = null;
+      }
+
+    if (toPCS != null || fromPCS != null)
+      return;
+
+    // If no intent 0 clut is available, look for a intent 1 clut.
+    try
+      {
+	toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB1Tag);
+      }
+    catch (Exception e)
+      {
+	toPCS = null;
+      }
+
+    try
+      {
+	fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA1Tag);
+      }
+    catch (Exception e)
+      {
+	fromPCS = null;
+      }
+
+    if (toPCS != null || fromPCS != null)
+      return;
+
+    // Last shot.. intent 2 CLUT.
+    try
+      {
+	toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB2Tag);
+      }
+    catch (Exception e)
+      {
+	toPCS = null;
+      }
+
+    try
+      {
+	fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA2Tag);
+      }
+    catch (Exception e)
+      {
+	fromPCS = null;
+      }
+
+    if (toPCS == null && fromPCS == null)
+      throw new IllegalArgumentException("No CLUTs in profile!");
+  }
+
+  public float[] toCIEXYZ(float[] in)
+  {
+    if (toPCS != null)
+      return toPCS.lookup(in);
+    else
+      return new float[3];
+  }
+
+  public float[] toRGB(float[] in)
+  {
+    return SrgbConverter.XYZtoRGB(toCIEXYZ(in));
+  }
+
+  public float[] fromCIEXYZ(float[] in)
+  {
+    if (fromPCS != null)
+      return fromPCS.lookup(in);
+    else
+      return new float[nChannels];
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    return fromCIEXYZ(SrgbConverter.RGBtoXYZ(in));
+  }
+}
Index: gnu/java/awt/color/ColorLookUpTable.java
===================================================================
RCS file: gnu/java/awt/color/ColorLookUpTable.java
diff -N gnu/java/awt/color/ColorLookUpTable.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/ColorLookUpTable.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,430 @@
+/* ColorLookUpTable.java -- ICC v2 CLUT
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.nio.ByteBuffer;
+
+
+/**
+ * ColorLookUpTable handles color lookups through a color lookup table,
+ * as defined in the ICC specification.
+ * Both 'mft2' and 'mft1' (8 and 16-bit) type CLUTs are handled.
+ *
+ * This will have to be updated later for ICC 4.0.0
+ *
+ * @author Sven de Marothy
+ */
+public class ColorLookUpTable
+{
+  /**
+   * CIE 1931 D50 white point (in Lab coordinates)
+   */
+  private static float[] D50 = { 0.96422f, 1.00f, 0.82521f };
+
+  /**
+   * Number of input/output channels
+   */
+  int nIn;
+
+  /**
+   * Number of input/output channels
+   */
+  int nOut;
+  int nInTableEntries; // Number of input table entries
+  int nOutTableEntries; // Number of output table entries
+  int gridpoints; // Number of gridpoints
+  int nClut; // This is nOut*(gridpoints**nIn)
+  double[][] inTable; // 1D input table ([channel][table])
+  short[][] outTable; // 1D input table ([channel][table])
+  double[] clut; // The color lookup table
+  float[][] inMatrix; // input matrix (XYZ only)
+  boolean useMatrix; // Whether to use the matrix or not.
+  int[] multiplier;
+  int[] offsets; // Hypercube offsets 
+  boolean inputLab; // Set if the CLUT input CS is Lab
+  boolean outputLab; // Set if the CLUT output CS is Lab
+
+  /**
+   * Constructor
+   * Requires a profile file to get the CLUT from and the tag of the
+   * CLUT to create. (icSigXToYZTag where X,Y = [A | B], Z = [0,1,2])
+   */
+  public ColorLookUpTable(ICC_Profile profile, int tag)
+  {
+    useMatrix = false;
+
+    switch (tag)
+      {
+      case ICC_Profile.icSigAToB0Tag:
+      case ICC_Profile.icSigAToB1Tag:
+      case ICC_Profile.icSigAToB2Tag:
+	if (profile.getColorSpaceType() == ColorSpace.TYPE_XYZ)
+	  useMatrix = true;
+	inputLab = false;
+	outputLab = (profile.getPCSType() == ColorSpace.TYPE_Lab);
+	break;
+      case ICC_Profile.icSigBToA0Tag:
+      case ICC_Profile.icSigBToA1Tag:
+      case ICC_Profile.icSigBToA2Tag:
+	if (profile.getPCSType() == ColorSpace.TYPE_XYZ)
+	  useMatrix = true;
+	inputLab = (profile.getPCSType() == ColorSpace.TYPE_Lab);
+	outputLab = false;
+	break;
+      default:
+	throw new IllegalArgumentException("Not a clut-type tag.");
+      }
+
+    byte[] data = profile.getData(tag);
+    if (data == null)
+      throw new IllegalArgumentException("Unsuitable profile, does not contain a CLUT.");
+
+    // check 'mft'
+    if (data[0] != 0x6d || data[1] != 0x66 || data[2] != 0x74)
+      throw new IllegalArgumentException("Unsuitable profile, invalid CLUT data.");
+
+    if (data[3] == 0x32)
+      readClut16(data);
+    else if (data[3] == 0x31)
+      readClut8(data);
+    else
+      throw new IllegalArgumentException("Unknown/invalid CLUT type.");
+  }
+
+  /**
+   * Loads a 16-bit CLUT into our data structures
+   */
+  private void readClut16(byte[] data)
+  {
+    ByteBuffer buf = ByteBuffer.wrap(data);
+
+    nIn = data[8] & (0xFF);
+    nOut = data[9] & (0xFF);
+    nInTableEntries = buf.getShort(48);
+    nOutTableEntries = buf.getShort(50);
+    gridpoints = data[10] & (0xFF);
+
+    inMatrix = new float[3][3];
+    for (int i = 0; i < 3; i++)
+      for (int j = 0; j < 3; j++)
+	inMatrix[i][j] = ((float) (buf.getInt(12 + (i * 3 + j) * 4))) / 65536.0f;
+
+    inTable = new double[nIn][nInTableEntries];
+    for (int channel = 0; channel < nIn; channel++)
+      for (int i = 0; i < nInTableEntries; i++)
+	inTable[channel][i] = (double) ((int) buf.getShort(52
+	                                                   + (channel * nInTableEntries
+	                                                   + i) * 2)
+	                      & (0xFFFF)) / 65536.0;
+
+    nClut = nOut;
+    multiplier = new int[nIn];
+    multiplier[nIn - 1] = nOut;
+    for (int i = 0; i < nIn; i++)
+      {
+	nClut *= gridpoints;
+	if (i > 0)
+	  multiplier[nIn - i - 1] = multiplier[nIn - i] * gridpoints;
+      }
+
+    int clutOffset = 52 + nIn * nInTableEntries * 2;
+    clut = new double[nClut];
+    for (int i = 0; i < nClut; i++)
+      clut[i] = (double) ((int) buf.getShort(clutOffset + i * 2) & (0xFFFF)) / 65536.0;
+
+    outTable = new short[nOut][nOutTableEntries];
+    for (int channel = 0; channel < nOut; channel++)
+      for (int i = 0; i < nOutTableEntries; i++)
+	outTable[channel][i] = buf.getShort(clutOffset
+	                                    + (nClut
+	                                    + channel * nOutTableEntries + i) * 2);
+
+    // calculate the hypercube corner offsets
+    offsets = new int[(1 << nIn)];
+    offsets[0] = 0;
+    for (int j = 0; j < nIn; j++)
+      {
+	int factor = 1 << j;
+	for (int i = 0; i < factor; i++)
+	  offsets[factor + i] = offsets[i] + multiplier[j];
+      }
+  }
+
+  /**
+   * Loads a 8-bit CLUT into our data structures.
+   */
+  private void readClut8(byte[] data)
+  {
+    ByteBuffer buf = ByteBuffer.wrap(data);
+
+    nIn = (data[8] & (0xFF));
+    nOut = (data[9] & (0xFF));
+    nInTableEntries = 256; // always 256
+    nOutTableEntries = 256; // always 256
+    gridpoints = (data[10] & (0xFF));
+
+    inMatrix = new float[3][3];
+    for (int i = 0; i < 3; i++)
+      for (int j = 0; j < 3; j++)
+	inMatrix[i][j] = ((float) (buf.getInt(12 + (i * 3 + j) * 4))) / 65536.0f;
+
+    inTable = new double[nIn][nInTableEntries];
+    for (int channel = 0; channel < nIn; channel++)
+      for (int i = 0; i < nInTableEntries; i++)
+	inTable[channel][i] = (double) ((int) buf.get(48
+	                                              + (channel * nInTableEntries
+	                                              + i)) & (0xFF)) / 255.0;
+
+    nClut = nOut;
+    multiplier = new int[nIn];
+    multiplier[nIn - 1] = nOut;
+    for (int i = 0; i < nIn; i++)
+      {
+	nClut *= gridpoints;
+	if (i > 0)
+	  multiplier[nIn - i - 1] = multiplier[nIn - i] * gridpoints;
+      }
+
+    int clutOffset = 48 + nIn * nInTableEntries;
+    clut = new double[nClut];
+    for (int i = 0; i < nClut; i++)
+      clut[i] = (double) ((int) buf.get(clutOffset + i) & (0xFF)) / 255.0;
+
+    outTable = new short[nOut][nOutTableEntries];
+    for (int channel = 0; channel < nOut; channel++)
+      for (int i = 0; i < nOutTableEntries; i++)
+	outTable[channel][i] = (short) (buf.get(clutOffset + nClut
+	                                        + channel * nOutTableEntries
+	                                        + i) * 257);
+
+    // calculate the hypercube corner offsets
+    offsets = new int[(1 << nIn)];
+    offsets[0] = 0;
+    for (int j = 0; j < nIn; j++)
+      {
+	int factor = 1 << j;
+	for (int i = 0; i < factor; i++)
+	  offsets[factor + i] = offsets[i] + multiplier[j];
+      }
+  }
+
+  /**
+   * Performs a lookup through the Color LookUp Table.
+   * If the CLUT tag type is AtoB the conversion will be from the device
+   * color space to the PCS, BtoA type goes in the opposite direction.
+   *
+   * For convenience, the PCS values for input or output will always be
+   * CIE XYZ (D50), if the actual PCS is Lab, the values will be converted.
+   *
+   * N-dimensional linear interpolation is used.
+   */
+  float[] lookup(float[] in)
+  {
+    float[] in2 = new float[in.length];
+    if (useMatrix)
+      {
+	for (int i = 0; i < 3; i++)
+	  in2[i] = in[0] * inMatrix[i][0] + in[1] * inMatrix[i][1]
+	           + in[2] * inMatrix[i][2];
+      }
+    else if (inputLab)
+      in2 = XYZtoLab(in);
+    else
+      System.arraycopy(in, 0, in2, 0, in.length);
+
+    // input table 
+    for (int i = 0; i < nIn; i++)
+      {
+	int index = (int) Math.floor(in2[i] * (double) (nInTableEntries - 1)); // floor in
+
+	// clip values.
+	if (index >= nInTableEntries - 1)
+	  in2[i] = (float) inTable[i][nInTableEntries - 1];
+	else if (index < 0)
+	  in2[i] = (float) inTable[i][0];
+	else
+	  {
+	    // linear interpolation
+	    double alpha = in2[i] * ((double) nInTableEntries - 1.0) - index;
+	    in2[i] = (float) (inTable[i][index] * (1 - alpha)
+	             + inTable[i][index + 1] * alpha);
+	  }
+      }
+
+    // CLUT lookup
+    double[] output2 = new double[nOut];
+    double[] weights = new double[(1 << nIn)];
+    double[] clutalpha = new double[nIn]; // interpolation values
+    int offset = 0; // = gp
+    for (int i = 0; i < nIn; i++)
+      {
+	int index = (int) Math.floor(in2[i] * ((double) gridpoints - 1.0));
+	double alpha = in2[i] * ((double) gridpoints - 1.0) - (double) index;
+
+	// clip values.
+	if (index >= gridpoints - 1)
+	  {
+	    index = gridpoints - 1;
+	    alpha = 1.0;
+	  }
+	else if (index < 0)
+	  index = 0;
+	clutalpha[i] = alpha;
+	offset += index * multiplier[i];
+      }
+
+    // Calculate interpolation weights
+    weights[0] = 1.0;
+    for (int j = 0; j < nIn; j++)
+      {
+	int factor = 1 << j;
+	for (int i = 0; i < factor; i++)
+	  {
+	    weights[factor + i] = weights[i] * clutalpha[j];
+	    weights[i] *= (1.0 - clutalpha[j]);
+	  }
+      }
+
+    for (int i = 0; i < nOut; i++)
+      output2[i] = weights[0] * clut[offset + i];
+
+    for (int i = 1; i < (1 << nIn); i++)
+      {
+	int offset2 = offset + offsets[i];
+	for (int f = 0; f < nOut; f++)
+	  output2[f] += weights[i] * clut[offset2 + f];
+      }
+
+    // output table 
+    float[] output = new float[nOut];
+    for (int i = 0; i < nOut; i++)
+      {
+	int index = (int) Math.floor(output2[i] * ((double) nOutTableEntries
+	                             - 1.0));
+
+	// clip values.
+	if (index >= nOutTableEntries - 1)
+	  output[i] = outTable[i][nOutTableEntries - 1];
+	else if (index < 0)
+	  output[i] = outTable[i][0];
+	else
+	  {
+	    // linear interpolation
+	    double a = output2[i] * ((double) nOutTableEntries - 1.0)
+	               - (double) index;
+	    output[i] = (float) ((double) ((int) outTable[i][index] & (0xFFFF)) * (1
+	                - a)
+	                + (double) ((int) outTable[i][index + 1] & (0xFFFF)) * a) / 65536f;
+	  }
+      }
+
+    if (outputLab)
+      return LabtoXYZ(output);
+    return output;
+  }
+
+  /**
+   * Converts CIE Lab coordinates to (D50) XYZ ones.
+   */
+  private float[] LabtoXYZ(float[] in)
+  {
+    // Convert from byte-packed format to a 
+    // more convenient one (actual Lab values)
+    // (See ICC spec for details)
+    // factor is 100 * 65536 / 65280
+    in[0] = (float) (100.392156862745 * in[0]);
+    in[1] = (in[1] * 256.0f) - 128.0f;
+    in[2] = (in[2] * 256.0f) - 128.0f;
+
+    float[] out = new float[3];
+
+    out[1] = (in[0] + 16.0f) / 116.0f;
+    out[0] = in[1] / 500.0f + out[1];
+    out[2] = out[1] - in[2] / 200.0f;
+
+    for (int i = 0; i < 3; i++)
+      {
+	double exp = out[i] * out[i] * out[i];
+	if (exp <= 0.008856)
+	  out[i] = (out[i] - 16.0f / 116.0f) / 7.787f;
+	else
+	  out[i] = (float) exp;
+	out[i] = D50[i] * out[i];
+      }
+    return out;
+  }
+
+  /**
+   * Converts CIE XYZ coordinates to Lab ones.
+   */
+  private float[] XYZtoLab(float[] in)
+  {
+    float[] temp = new float[3];
+
+    for (int i = 0; i < 3; i++)
+      {
+	temp[i] = in[i] / D50[i];
+
+	if (temp[i] <= 0.008856f)
+	  temp[i] = (7.7870689f * temp[i]) + (16f / 116.0f);
+	else
+	  temp[i] = (float) Math.exp((1.0 / 3.0) * Math.log(temp[i]));
+      }
+
+    float[] out = new float[3];
+    out[0] = (116.0f * temp[1]) - 16f;
+    out[1] = 500.0f * (temp[0] - temp[1]);
+    out[2] = 200.0f * (temp[1] - temp[2]);
+
+    // Normalize to packed format
+    out[0] = (float) (out[0] / 100.392156862745);
+    out[1] = (out[1] + 128f) / 256f;
+    out[2] = (out[2] + 128f) / 256f;
+    for (int i = 0; i < 3; i++)
+      {
+	if (out[i] < 0f)
+	  out[i] = 0f;
+	if (out[i] > 1f)
+	  out[i] = 1f;
+      }
+    return out;
+  }
+}
Index: gnu/java/awt/color/ColorSpaceConverter.java
===================================================================
RCS file: gnu/java/awt/color/ColorSpaceConverter.java
diff -N gnu/java/awt/color/ColorSpaceConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/ColorSpaceConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,70 @@
+/* ColorSpaceConverter.java -- an interface for colorspace conversion
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * ColorSpaceConverter - used by java.awt.color.ICC_ColorSpace
+ *
+ * Color space conversion can occur in several ways:
+ *
+ * -Directly (for the built in spaces sRGB, linear RGB, gray, CIE XYZ and PYCC
+ * -ICC_ProfileRGB works through TRC curves and a matrix
+ * -ICC_ProfileGray works through a single TRC
+ * -Everything else is done through Color lookup tables.
+ *
+ * The different conversion methods are implemented through
+ * an interface. The built-in colorspaces are implemented directly
+ * with the relevant conversion equations.
+ *
+ * In this way, we hopefully will always use the fastest and most
+ * accurate method available.
+ *
+ * @author Sven de Marothy
+ */
+public interface ColorSpaceConverter
+{
+  float[] toCIEXYZ(float[] in);
+
+  float[] fromCIEXYZ(float[] in);
+
+  float[] toRGB(float[] in);
+
+  float[] fromRGB(float[] in);
+}
Index: gnu/java/awt/color/GrayProfileConverter.java
===================================================================
RCS file: gnu/java/awt/color/GrayProfileConverter.java
diff -N gnu/java/awt/color/GrayProfileConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/GrayProfileConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,138 @@
+/* GrayProfileConverter.java -- Gray profile conversion class
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+import java.awt.color.ProfileDataException;
+import java.awt.color.ICC_Profile;
+import java.awt.color.ICC_ProfileGray;
+
+
+/**
+ * GrayProfileConverter - converts Grayscale profiles (ICC_ProfileGray)
+ *
+ * This type of profile contains a single tone reproduction curve (TRC).
+ * Conversion consists of simple TRC lookup.
+ *
+ * This implementation is very lazy and does everything applying the TRC and
+ * utilizing the built-in linear grayscale color space.
+ *
+ * @author Sven de Marothy
+ */
+public class GrayProfileConverter implements ColorSpaceConverter
+{
+  private GrayScaleConverter gc;
+  private ToneReproductionCurve trc;
+  private ColorLookUpTable toPCS;
+  private ColorLookUpTable fromPCS;
+
+  /**
+   * Constructs the converter described by an ICC_ProfileGray object
+   */
+  public GrayProfileConverter(ICC_ProfileGray profile)
+  {
+    try
+      {
+	trc = new ToneReproductionCurve(profile.getGamma());
+      }
+    catch (ProfileDataException e)
+      {
+	trc = new ToneReproductionCurve(profile.getTRC());
+      }
+
+    // linear grayscale converter
+    gc = new GrayScaleConverter();
+
+    // If a CLUT is available, it should be used, and the TRCs ignored.
+    // Note: A valid profile may only have CLUTs in one direction, and
+    // TRC:s without useful info, making reverse-transforms impossible.
+    // In this case the TRC will be used for the reverse-transform with
+    // unpredictable results. This is in line with the Java specification,
+    try
+      {
+	toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag);
+      }
+    catch (Exception e)
+      {
+	toPCS = null;
+      }
+
+    try
+      {
+	fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag);
+      }
+    catch (Exception e)
+      {
+	fromPCS = null;
+      }
+  }
+
+  public float[] toCIEXYZ(float[] in)
+  {
+    if (toPCS != null)
+      return toPCS.lookup(in);
+    float[] gray = new float[1];
+    gray[0] = trc.lookup(in[0]);
+    return gc.toCIEXYZ(gray);
+  }
+
+  public float[] toRGB(float[] in)
+  {
+    float[] gray = new float[1];
+    gray[0] = trc.lookup(in[0]);
+    return gc.toRGB(gray);
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    // get linear grayscale value
+    float[] gray = gc.fromRGB(in);
+    gray[0] = trc.reverseLookup(gray[0]);
+    return gray;
+  }
+
+  public float[] fromCIEXYZ(float[] in)
+  {
+    if (fromPCS != null)
+      return fromPCS.lookup(in);
+
+    float[] gray = gc.fromCIEXYZ(in);
+    gray[0] = trc.reverseLookup(gray[0]);
+    return gray;
+  }
+}
Index: gnu/java/awt/color/GrayScaleConverter.java
===================================================================
RCS file: gnu/java/awt/color/GrayScaleConverter.java
diff -N gnu/java/awt/color/GrayScaleConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/GrayScaleConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,111 @@
+/* GrayScaleConverter.java -- Linear grayscale conversion class
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * Linear Grayscale converter
+ *
+ * @author Sven de Marothy
+ */
+public class GrayScaleConverter implements ColorSpaceConverter
+{
+  // intensity factors (ITU Rec. BT.709)
+  double[] coeff = { 0.2125f, 0.7154f, 0.0721f };
+
+  /**
+   * CIE 1931 D50 white point (in Lab coordinates)
+   */
+  private static float[] D50 = { 0.96422f, 1.00f, 0.82521f };
+
+  public float[] toCIEXYZ(float[] in)
+  {
+    float g = in[0];
+    if (g < 0)
+      g = 1 + g;
+    float[] out = { g * D50[0], g * D50[1], g * D50[2] }; // White spot
+    return out;
+  }
+
+  public float[] toRGB(float[] in)
+  {
+    float[] out = new float[3];
+    if (in[0] <= 0.00304f)
+      out[0] = in[0] * 12.92f;
+    else
+      out[0] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(in[0])))
+               - 0.055f;
+    out[1] = out[2] = out[0];
+    return out;
+  }
+
+  public float[] fromCIEXYZ(float[] in)
+  {
+    float[] temp = new float[3];
+    temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2];
+    temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2];
+    temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2];
+    float[] out = new float[1];
+    for (int i = 0; i < 3; i++)
+      out[0] = (float) (temp[i] * coeff[i]);
+    return out;
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    float[] out = new float[1];
+
+    // Convert non-linear RGB coordinates to linear ones,
+    //  numbers from the w3 spec.
+    out[0] = 0;
+    for (int i = 0; i < 3; i++)
+      {
+	float n = in[i];
+	if (n < 0)
+	  n = 0f;
+	if (n > 1)
+	  n = 1f;
+	if (n <= 0.03928f)
+	  out[0] += (float) (coeff[i] * n / 12.92);
+	else
+	  out[0] += (float) (coeff[i] * Math.exp(2.4 * Math.log((n + 0.055) / 1.055)));
+      }
+    return out;
+  }
+}
Index: gnu/java/awt/color/LinearRGBConverter.java
===================================================================
RCS file: gnu/java/awt/color/LinearRGBConverter.java
diff -N gnu/java/awt/color/LinearRGBConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/LinearRGBConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,156 @@
+/* LinearRGBConverter.java -- conversion to a linear RGB color space
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
+
+package gnu.java.awt.color;
+
+
+/**
+ * LinearRGBConverter - conversion routines for a linear sRGB colorspace
+ * sRGB is a standard for RGB colorspaces, adopted by the w3c.
+ *
+ * The specification is available at:
+ * http://www.w3.org/Graphics/Color/sRGB.html
+ *
+ * @author Sven de Marothy
+ */
+/**
+ * Linear RGB.
+ * TESTED
+ */
+public class LinearRGBConverter implements ColorSpaceConverter
+{
+  /**
+   * linear RGB --> sRGB
+   * Use the inverse gamma curve
+   */
+  public float[] toRGB(float[] in)
+  {
+    float[] out = new float[3];
+    for (int i = 0; i < 3; i++)
+      {
+	float n = in[i];
+	if (n < 0)
+	  n = 0f;
+	if (n > 1)
+	  n = 1f;
+	if (n <= 0.00304f)
+	  out[i] = in[0] * 12.92f;
+	else
+	  out[i] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(n)))
+	           - 0.055f;
+      }
+    return out;
+  }
+
+  /**
+   * sRGB --> linear RGB
+   * Use the gamma curve (gamma=2.4 in sRGB)
+   */
+  public float[] fromRGB(float[] in)
+  {
+    float[] out = new float[3];
+
+    // Convert non-linear RGB coordinates to linear ones,
+    //  numbers from the w3 spec.
+    for (int i = 0; i < 3; i++)
+      {
+	float n = in[i];
+	if (n < 0)
+	  n = 0f;
+	if (n > 1)
+	  n = 1f;
+	if (n <= 0.03928f)
+	  out[i] = (float) (n / 12.92);
+	else
+	  out[i] = (float) (Math.exp(2.4 * Math.log((n + 0.055) / 1.055)));
+      }
+    return out;
+  }
+
+  /**
+   * Linear RGB --> CIE XYZ (D50 relative)
+   * This is a simple matrix transform, the matrix (relative D65)
+   * is given in the sRGB spec. This has been combined with a
+   * linear Bradford transform for the D65-->D50 mapping, resulting
+   * in a single matrix which does the whole thing.
+   *
+   */
+  public float[] fromCIEXYZ(float[] in)
+  {
+    /*
+     * Note: The numbers which were used to calculate this only had four
+     * digits of accuracy. So don't be fooled by the number of digits here.
+     * If someone has more accurate source, feel free to update this.
+     */
+    float[] out = new float[3];
+    out[0] = (float) (3.13383065124221 * in[0] - 1.61711949411313 * in[1]
+             - 0.49071914111101 * in[2]);
+    out[1] = (float) (-0.97847026691142 * in[0] + 1.91597856031996 * in[1]
+             + 0.03340430640699 * in[2]);
+    out[2] = (float) (0.07203679486279 * in[0] - 0.22903073553113 * in[1]
+             + 1.40557835776234 * in[2]);
+    if (out[0] < 0)
+      out[0] = 0f;
+    if (out[1] < 0)
+      out[1] = 0f;
+    if (out[2] < 0)
+      out[2] = 0f;
+    if (out[0] > 1.0f)
+      out[0] = 1.0f;
+    if (out[1] > 1.0f)
+      out[1] = 1.0f;
+    if (out[2] > 1.0f)
+      out[2] = 1.0f;
+    return out;
+  }
+
+  /**
+   * Linear RGB --> CIE XYZ (D50 relative)
+   * Uses the inverse of the above matrix.
+   */
+  public float[] toCIEXYZ(float[] in)
+  {
+    float[] out = new float[3];
+    out[0] = (float) (0.43606375022190 * in[0] + 0.38514960146481 * in[1]
+             + 0.14308641888799 * in[2]);
+    out[1] = (float) (0.22245089403542 * in[0] + 0.71692584775182 * in[1]
+             + 0.06062451125578 * in[2]);
+    out[2] = (float) (0.01389851860679 * in[0] + 0.09707969011198 * in[1]
+             + 0.71399604572506 * in[2]);
+    return out;
+  }
+}
Index: gnu/java/awt/color/ProfileHeader.java
===================================================================
RCS file: gnu/java/awt/color/ProfileHeader.java
diff -N gnu/java/awt/color/ProfileHeader.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/ProfileHeader.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,399 @@
+/* ProfileHeader.java -- Encapsules ICC Profile header data
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.nio.ByteBuffer;
+
+
+/**
+ * Header, abstracts and validates the header data.
+ *
+ * @author Sven de Marothy
+ */
+public class ProfileHeader
+{
+  /**
+   * Magic identifier (ASCII 'acsp')
+   */
+  private static final int icMagicNumber = 0x61637370;
+
+  /**
+   * Mapping from ICC Profile signatures to ColorSpace types
+   */
+  private static final int[] csTypeMap = 
+                                         {
+                                           ICC_Profile.icSigXYZData,
+                                           ColorSpace.TYPE_XYZ,
+                                           ICC_Profile.icSigLabData,
+                                           ColorSpace.TYPE_Lab,
+                                           ICC_Profile.icSigLuvData,
+                                           ColorSpace.TYPE_Luv,
+                                           ICC_Profile.icSigYCbCrData,
+                                           ColorSpace.TYPE_YCbCr,
+                                           ICC_Profile.icSigYxyData,
+                                           ColorSpace.TYPE_Yxy,
+                                           ICC_Profile.icSigRgbData,
+                                           ColorSpace.TYPE_RGB,
+                                           ICC_Profile.icSigGrayData,
+                                           ColorSpace.TYPE_GRAY,
+                                           ICC_Profile.icSigHsvData,
+                                           ColorSpace.TYPE_HSV,
+                                           ICC_Profile.icSigHlsData,
+                                           ColorSpace.TYPE_HLS,
+                                           ICC_Profile.icSigCmykData,
+                                           ColorSpace.TYPE_CMYK,
+                                           ICC_Profile.icSigCmyData,
+                                           ColorSpace.TYPE_CMY,
+                                           ICC_Profile.icSigSpace2CLR,
+                                           ColorSpace.TYPE_2CLR,
+                                           ICC_Profile.icSigSpace3CLR,
+                                           ColorSpace.TYPE_3CLR,
+                                           ICC_Profile.icSigSpace4CLR,
+                                           ColorSpace.TYPE_4CLR,
+                                           ICC_Profile.icSigSpace5CLR,
+                                           ColorSpace.TYPE_5CLR,
+                                           ICC_Profile.icSigSpace6CLR,
+                                           ColorSpace.TYPE_6CLR,
+                                           ICC_Profile.icSigSpace7CLR,
+                                           ColorSpace.TYPE_7CLR,
+                                           ICC_Profile.icSigSpace8CLR,
+                                           ColorSpace.TYPE_8CLR,
+                                           ICC_Profile.icSigSpace9CLR,
+                                           ColorSpace.TYPE_9CLR,
+                                           ICC_Profile.icSigSpaceACLR,
+                                           ColorSpace.TYPE_ACLR,
+                                           ICC_Profile.icSigSpaceBCLR,
+                                           ColorSpace.TYPE_BCLR,
+                                           ICC_Profile.icSigSpaceCCLR,
+                                           ColorSpace.TYPE_CCLR,
+                                           ICC_Profile.icSigSpaceDCLR,
+                                           ColorSpace.TYPE_DCLR,
+                                           ICC_Profile.icSigSpaceECLR,
+                                           ColorSpace.TYPE_ECLR,
+                                           ICC_Profile.icSigSpaceFCLR,
+                                           ColorSpace.TYPE_FCLR
+                                         };
+
+  /**
+   * Size of an ICC header (128 bytes)
+   */
+  public static final int HEADERSIZE = 128;
+
+  /**
+   * Mapping of ICC class signatures to profile class constants
+   */
+  private static final int[] classMap = 
+                                        {
+                                          ICC_Profile.icSigInputClass,
+                                          ICC_Profile.CLASS_INPUT,
+                                          ICC_Profile.icSigDisplayClass,
+                                          ICC_Profile.CLASS_DISPLAY,
+                                          ICC_Profile.icSigOutputClass,
+                                          ICC_Profile.CLASS_OUTPUT,
+                                          ICC_Profile.icSigLinkClass,
+                                          ICC_Profile.CLASS_DEVICELINK,
+                                          ICC_Profile.icSigColorSpaceClass,
+                                          ICC_Profile.CLASS_COLORSPACECONVERSION,
+                                          ICC_Profile.icSigAbstractClass,
+                                          ICC_Profile.CLASS_ABSTRACT,
+                                          ICC_Profile.icSigNamedColorClass,
+                                          ICC_Profile.CLASS_NAMEDCOLOR
+                                        };
+  private int size;
+  private int cmmId;
+
+  // Major/Minor version, The ICC-1998 spec is major v2
+  private int majorVersion;
+
+  // Major/Minor version, The ICC-1998 spec is major v2
+  private int minorVersion;
+  private int profileClass; // profile device class
+  private int colorSpace; // data color space type
+  private int profileColorSpace; // profile connection space (PCS) type
+  private byte[] timestamp; // original creation timestamp
+  private int platform; // platform signature
+  private int flags; // flags
+  private int magic; // magic number.
+  private int manufacturerSig; // manufacturer sig
+  private int modelSig; // model sig
+  private byte[] attributes; // Attributes
+  private int intent; // rendering intent
+  private byte[] illuminant; // illuminant info (Coordinates of D50 in the PCS)
+  private int creatorSig; // Creator sig (same type as manufacturer)
+
+  /**
+   * Creates a 'default' header for use with our predefined profiles.
+   * Note the device and profile color spaces are not set.
+   */
+  public ProfileHeader()
+  {
+    creatorSig = 0;
+    intent = 0;
+    modelSig = manufacturerSig = (int) 0x6E6f6E65; // 'none'
+    magic = icMagicNumber;
+    cmmId = 0;
+    platform = 0; // no preferred platform
+    timestamp = new byte[8];
+    majorVersion = 2;
+    minorVersion = 0x10;
+    flags = 0;
+
+    // D50 in XYZ format (encoded)
+    illuminant = new byte[]
+                 {
+                   (byte) 0x00, (byte) 0x00, (byte) 0xf6, (byte) 0xd6,
+                   (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+                   (byte) 0x00, (byte) 0x00, (byte) 0xd3, (byte) 0x2d
+                 };
+    attributes = new byte[8];
+    profileClass = ICC_Profile.CLASS_DISPLAY;
+  }
+
+  /**
+   * Creates a header from profile data. Only the header portion (128 bytes)
+   * is read, so the array passed need not be the full profile.
+   */
+  public ProfileHeader(byte[] data)
+  {
+    ByteBuffer buf = ByteBuffer.wrap(data);
+
+    // Get size (the sign bit shouldn't matter. 	
+    // A valid profile can never be +2Gb)
+    size = buf.getInt(ICC_Profile.icHdrSize);
+
+    // CMM ID
+    cmmId = buf.getInt(ICC_Profile.icHdrCmmId);
+
+    // Version number
+    majorVersion = (int) (data[ICC_Profile.icHdrVersion]);
+    minorVersion = (int) (data[ICC_Profile.icHdrVersion + 1]);
+
+    // Profile/Device class
+    int classSig = buf.getInt(ICC_Profile.icHdrDeviceClass);
+    profileClass = -1;
+    for (int i = 0; i < classMap.length; i += 2)
+      if (classMap[i] == classSig)
+        {
+	  profileClass = classMap[i + 1];
+	  break;
+        }
+
+    // get the data color space
+    int csSig = buf.getInt(ICC_Profile.icHdrColorSpace);
+    colorSpace = -1;
+    for (int i = 0; i < csTypeMap.length; i += 2)
+      if (csTypeMap[i] == csSig)
+        {
+	  colorSpace = csTypeMap[i + 1];
+	  break;
+        }
+
+    // get the profile color space (PCS), must be xyz or lab except
+    // for device-link-class profiles
+    int pcsSig = buf.getInt(ICC_Profile.icHdrPcs);
+    profileColorSpace = -1;
+    if (profileClass != ICC_Profile.CLASS_DEVICELINK)
+      {
+	if (pcsSig == ICC_Profile.icSigXYZData)
+	  profileColorSpace = ColorSpace.TYPE_XYZ;
+	if (pcsSig == ICC_Profile.icSigLabData)
+	  profileColorSpace = ColorSpace.TYPE_Lab;
+      }
+    else
+      {
+	for (int i = 0; i < csTypeMap.length; i += 2)
+	  if (csTypeMap[i] == pcsSig)
+	    {
+	      profileColorSpace = csTypeMap[i + 1];
+	      break;
+	    }
+      }
+
+    // creation timestamp
+    timestamp = new byte[8];
+    System.arraycopy(data, ICC_Profile.icHdrDate, timestamp, 0, 8);
+
+    // magic number
+    magic = buf.getInt(ICC_Profile.icHdrMagic);
+
+    //  platform info
+    platform = buf.getInt(ICC_Profile.icHdrPlatform);
+    // get flags
+    flags = buf.getInt(ICC_Profile.icHdrFlags);
+    // get manufacturer sign
+    manufacturerSig = buf.getInt(ICC_Profile.icHdrManufacturer);
+    // get header model
+    modelSig = buf.getInt(ICC_Profile.icHdrModel);
+    // attributes
+    attributes = new byte[8];
+    System.arraycopy(data, ICC_Profile.icHdrAttributes, attributes, 0, 8);
+    // rendering intent
+    intent = buf.getInt(ICC_Profile.icHdrRenderingIntent);
+    // illuminant info 
+    illuminant = new byte[12];
+    System.arraycopy(data, ICC_Profile.icHdrIlluminant, illuminant, 0, 12);
+    // Creator signature
+    creatorSig = buf.getInt(ICC_Profile.icHdrCreator);
+    // The rest of the header (Total size: 128 bytes) is unused..
+  }
+
+  /**
+   * Verify that the header is valid
+   * @param size equals the file size if it is to be verified, -1 otherwise
+   * @throws IllegalArgumentException if the header is found to be invalid.
+   */
+  public void verifyHeader(int size) throws IllegalArgumentException
+  {
+    // verify size
+    if (size != -1 && this.size != size)
+      throw new IllegalArgumentException("Invalid profile length:" + size);
+
+    // Check version number
+    if (majorVersion != 2)
+      throw new IllegalArgumentException("Wrong major version number:"
+                                         + majorVersion);
+
+    // Profile/Device class
+    if (profileClass == -1)
+      throw new IllegalArgumentException("Invalid profile/device class");
+
+    // get the data color space
+    if (colorSpace == -1)
+      throw new IllegalArgumentException("Invalid colorspace");
+
+    // profile color space
+    if (profileColorSpace == -1)
+      throw new IllegalArgumentException("Invalid PCS.");
+
+    // check magic number
+    if (magic != icMagicNumber)
+      throw new IllegalArgumentException("Invalid magic number!");
+  }
+
+  /**
+   * Creates a header, setting the header file size at the same time.
+   * @param size the profile file size.
+   */
+  public byte[] getData(int size)
+  {
+    byte[] data = new byte[HEADERSIZE];
+    ByteBuffer buf = ByteBuffer.wrap(data);
+    buf.putInt(ICC_Profile.icHdrSize, size);
+    buf.putInt(ICC_Profile.icHdrCmmId, cmmId);
+    buf.putShort(ICC_Profile.icHdrVersion,
+                 (short) (majorVersion << 8 | minorVersion));
+    for (int i = 1; i < classMap.length; i += 2)
+      if (profileClass == classMap[i])
+	buf.putInt(ICC_Profile.icHdrDeviceClass, classMap[i - 1]);
+    for (int i = 1; i < csTypeMap.length; i += 2)
+      if (csTypeMap[i] == colorSpace)
+	buf.putInt(ICC_Profile.icHdrColorSpace, csTypeMap[i - 1]);
+    for (int i = 1; i < csTypeMap.length; i += 2)
+      if (csTypeMap[i] == profileColorSpace)
+	buf.putInt(ICC_Profile.icHdrPcs, csTypeMap[i - 1]);
+
+    System.arraycopy(timestamp, 0, data, ICC_Profile.icHdrDate,
+                     timestamp.length);
+    buf.putInt(ICC_Profile.icHdrMagic, icMagicNumber);
+    buf.putInt(ICC_Profile.icHdrPlatform, platform);
+    buf.putInt(ICC_Profile.icHdrFlags, flags);
+    buf.putInt(ICC_Profile.icHdrManufacturer, manufacturerSig);
+    buf.putInt(ICC_Profile.icHdrModel, modelSig);
+    System.arraycopy(attributes, 0, data, ICC_Profile.icHdrAttributes,
+                     attributes.length);
+    buf.putInt(ICC_Profile.icHdrRenderingIntent, intent);
+    System.arraycopy(illuminant, 0, data, ICC_Profile.icHdrIlluminant,
+                     illuminant.length);
+    buf.putInt(ICC_Profile.icHdrCreator, creatorSig);
+    return buf.array();
+  }
+
+  public int getSize()
+  {
+    return size;
+  }
+
+  public void setSize(int s)
+  {
+    size = s;
+  }
+
+  public int getMajorVersion()
+  {
+    return majorVersion;
+  }
+
+  public int getMinorVersion()
+  {
+    return minorVersion;
+  }
+
+  public int getProfileClass()
+  {
+    return profileClass;
+  }
+
+  public void setProfileClass(int pc)
+  {
+    profileClass = pc;
+  }
+
+  public int getColorSpace()
+  {
+    return colorSpace;
+  }
+
+  public int getProfileColorSpace()
+  {
+    return profileColorSpace;
+  }
+
+  public void setColorSpace(int cs)
+  {
+    colorSpace = cs;
+  }
+
+  public void setProfileColorSpace(int pcs)
+  {
+    profileColorSpace = pcs;
+  }
+
+}
Index: gnu/java/awt/color/PyccConverter.java
===================================================================
RCS file: gnu/java/awt/color/PyccConverter.java
diff -N gnu/java/awt/color/PyccConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/PyccConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,73 @@
+/* PyccConverter.java -- PhotoYCC conversion class
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * PyccConverter - conversion routines for the PhotoYCC colorspace
+ *
+ * Also known as PhotoCD YCC, it is an expansion of the conventional
+ * YCC color space to also include colors with over 100% white.
+ *
+ * XXX FIXME: Not yet implemented, implementation pending.
+ *
+ * @author Sven de Marothy
+ */
+public class PyccConverter implements ColorSpaceConverter
+{
+  public float[] toRGB(float[] in)
+  {
+    return null;
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    return null;
+  }
+
+  public float[] toCIEXYZ(float[] in)
+  {
+    return null;
+  }
+
+  public float[] fromCIEXYZ(float[] in)
+  {
+    return null;
+  }
+}
Index: gnu/java/awt/color/RgbProfileConverter.java
===================================================================
RCS file: gnu/java/awt/color/RgbProfileConverter.java
diff -N gnu/java/awt/color/RgbProfileConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/RgbProfileConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,236 @@
+/* RgbProfileConverter.java -- RGB Profile conversion class
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+import java.awt.color.ProfileDataException;
+import java.awt.color.ICC_Profile;
+import java.awt.color.ICC_ProfileRGB;
+
+
+/**
+ * RgbProfileConverter - converts RGB profiles (ICC_ProfileRGB)
+ *
+ * This type of profile contains a matrix and three
+ * tone reproduction curves (TRCs).
+ *
+ * Device RGB --> CIE XYZ is done through first multiplying with
+ * a matrix, then each component is looked-up against it's TRC.
+ *
+ * The opposite transform is done using the inverse of the matrix,
+ * and TRC:s.
+ *
+ * @author Sven de Marothy
+ */
+public class RgbProfileConverter implements ColorSpaceConverter
+{
+  private float[][] matrix;
+  private float[][] inv_matrix;
+  private ToneReproductionCurve rTRC;
+  private ToneReproductionCurve gTRC;
+  private ToneReproductionCurve bTRC;
+  private ColorLookUpTable toPCS;
+  private ColorLookUpTable fromPCS;
+
+  /**
+   * CIE 1931 D50 white point (in Lab coordinates)
+   */
+  private static float[] D50 = { 0.96422f, 1.00f, 0.82521f };
+
+  /**
+   * Constructs an RgbProfileConverter from a given ICC_ProfileRGB
+   */
+  public RgbProfileConverter(ICC_ProfileRGB profile)
+  {
+    toPCS = fromPCS = null;
+    matrix = profile.getMatrix();
+    inv_matrix = invertMatrix(matrix);
+
+    // get TRCs
+    try
+      {
+	rTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.REDCOMPONENT));
+      }
+    catch (ProfileDataException e)
+      {
+	rTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.REDCOMPONENT));
+      }
+    try
+      {
+	gTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.GREENCOMPONENT));
+      }
+    catch (ProfileDataException e)
+      {
+	gTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.GREENCOMPONENT));
+      }
+    try
+      {
+	bTRC = new ToneReproductionCurve(profile.getGamma(ICC_ProfileRGB.BLUECOMPONENT));
+      }
+    catch (ProfileDataException e)
+      {
+	bTRC = new ToneReproductionCurve(profile.getTRC(ICC_ProfileRGB.BLUECOMPONENT));
+      }
+
+    // If a CLUT is available, it should be used, and the TRCs ignored.
+    // Note: A valid profile may only have CLUTs in one direction, and
+    // TRC:s without useful info, making reverse-transforms impossible.
+    // In this case the TRC will be used for the reverse-transform with
+    // unpredictable results. This is in line with the Java specification,
+    try
+      {
+	toPCS = new ColorLookUpTable(profile, ICC_Profile.icSigAToB0Tag);
+      }
+    catch (Exception e)
+      {
+	toPCS = null;
+      }
+
+    try
+      {
+	fromPCS = new ColorLookUpTable(profile, ICC_Profile.icSigBToA0Tag);
+      }
+    catch (Exception e)
+      {
+	fromPCS = null;
+      }
+  }
+
+  public float[] toCIEXYZ(float[] in)
+  {
+    // CLUT takes precedence
+    if (toPCS != null)
+      return toPCS.lookup(in);
+
+    float[] temp = new float[3];
+    float[] out = new float[3];
+
+    // device space --> linear gamma
+    temp[0] = rTRC.lookup(in[0]);
+    temp[1] = gTRC.lookup(in[1]);
+    temp[2] = bTRC.lookup(in[2]);
+
+    // matrix multiplication
+    out[0] = matrix[0][0] * temp[0] + matrix[0][1] * temp[1]
+             + matrix[0][2] * temp[2];
+    out[1] = matrix[1][0] * temp[0] + matrix[1][1] * temp[1]
+             + matrix[1][2] * temp[2];
+    out[2] = matrix[2][0] * temp[0] + matrix[2][1] * temp[1]
+             + matrix[2][2] * temp[2];
+
+    return out;
+  }
+
+  public float[] toRGB(float[] in)
+  {
+    return SrgbConverter.XYZtoRGB(toCIEXYZ(in));
+  }
+
+  public float[] fromCIEXYZ(float[] in)
+  {
+    if (fromPCS != null)
+      return fromPCS.lookup(in);
+
+    float[] temp = new float[3];
+    float[] out = new float[3];
+
+    // matrix multiplication
+    temp[0] = inv_matrix[0][0] * in[0] + inv_matrix[0][1] * in[1]
+              + inv_matrix[0][2] * in[2];
+    temp[1] = inv_matrix[1][0] * in[0] + inv_matrix[1][1] * in[1]
+              + inv_matrix[1][2] * in[2];
+    temp[2] = inv_matrix[2][0] * in[0] + inv_matrix[2][1] * in[1]
+              + inv_matrix[2][2] * in[2];
+
+    // device space --> linear gamma
+    out[0] = rTRC.reverseLookup(temp[0]);
+    out[1] = gTRC.reverseLookup(temp[1]);
+    out[2] = bTRC.reverseLookup(temp[2]);
+
+    // FIXME: Sun appears to clip the return values to [0,1]
+    // I don't believe that is a Good Thing, 
+    // (some colorspaces may allow values outside that range.)
+    // So we return the actual values here.
+    return out;
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    return fromCIEXYZ(SrgbConverter.RGBtoXYZ(in));
+  }
+
+  /**
+   * Inverts a 3x3 matrix, returns the inverse,
+   * throws an IllegalArgumentException if the matrix is not
+   * invertible (this shouldn't happen for a valid profile)
+   */
+  private float[][] invertMatrix(float[][] matrix)
+  {
+    float[][] out = new float[3][3];
+    double determinant = matrix[0][0] * (matrix[1][1] * matrix[2][2]
+                         - matrix[2][1] * matrix[1][2])
+                         - matrix[0][1] * (matrix[1][0] * matrix[2][2]
+                         - matrix[2][0] * matrix[1][2])
+                         + matrix[0][2] * (matrix[1][0] * matrix[2][1]
+                         - matrix[2][0] * matrix[1][1]);
+
+    if (determinant == 0.0)
+      throw new IllegalArgumentException("Can't invert conversion matrix.");
+    float invdet = (float) (1.0 / determinant);
+
+    out[0][0] = invdet * (matrix[1][1] * matrix[2][2]
+                - matrix[1][2] * matrix[2][1]);
+    out[0][1] = invdet * (matrix[0][2] * matrix[2][1]
+                - matrix[0][1] * matrix[2][2]);
+    out[0][2] = invdet * (matrix[0][1] * matrix[1][2]
+                - matrix[0][2] * matrix[1][1]);
+    out[1][0] = invdet * (matrix[1][2] * matrix[2][0]
+                - matrix[1][0] * matrix[2][2]);
+    out[1][1] = invdet * (matrix[0][0] * matrix[2][2]
+                - matrix[0][2] * matrix[2][0]);
+    out[1][2] = invdet * (matrix[0][2] * matrix[1][0]
+                - matrix[0][0] * matrix[1][2]);
+    out[2][0] = invdet * (matrix[1][0] * matrix[2][1]
+                - matrix[1][1] * matrix[2][0]);
+    out[2][1] = invdet * (matrix[0][1] * matrix[2][0]
+                - matrix[0][0] * matrix[2][1]);
+    out[2][2] = invdet * (matrix[0][0] * matrix[1][1]
+                - matrix[0][1] * matrix[1][0]);
+    return out;
+  }
+}
Index: gnu/java/awt/color/SrgbConverter.java
===================================================================
RCS file: gnu/java/awt/color/SrgbConverter.java
diff -N gnu/java/awt/color/SrgbConverter.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/SrgbConverter.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,153 @@
+/* SrgbConverter.java -- sRGB conversion class
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * SrgbConverter - conversion routines for the sRGB colorspace
+ * sRGB is a standard for RGB colorspaces, adopted by the w3c.
+ *
+ * The specification is available at:
+ * http://www.w3.org/Graphics/Color/sRGB.html
+ *
+ * @author Sven de Marothy
+ */
+/**
+ *
+ * Note the matrix numbers used here are NOT identical to those in the
+ * w3 spec, as those numbers are CIE XYZ relative a D65 white point.
+ * The CIE XYZ we use is relative a D50 white point, so therefore a
+ * linear Bradford transform matrix for D65->D50 mapping has been applied.
+ * (The ICC documents describe this transform)
+ *
+ *   Linearized Bradford transform:
+ *    0.8951    0.2664   -0.1614
+ *   -0.7502    1.7135    0.0367
+ *    0.0389   -0.0685    1.0296
+ *
+ *   Inverse:
+ *   0.9870   -0.1471    0.1600
+ *   0.4323    0.5184    0.0493
+ *  -0.00853   0.0400    0.9685
+ */
+public class SrgbConverter implements ColorSpaceConverter
+{
+  public float[] fromCIEXYZ(float[] in)
+  {
+    return XYZtoRGB(in);
+  }
+
+  public float[] toCIEXYZ(float[] in)
+  {
+    return RGBtoXYZ(in);
+  }
+
+  public float[] toRGB(float[] in)
+  {
+    float[] out = new float[3];
+    System.arraycopy(in, 0, out, 0, 3);
+    return out;
+  }
+
+  public float[] fromRGB(float[] in)
+  {
+    float[] out = new float[3];
+    System.arraycopy(in, 0, out, 0, 3);
+    return out;
+  }
+
+  /**
+   * CIE XYZ (D50 relative) --> sRGB
+   *
+   * Static as it's used by other ColorSpaceConverters to
+   * convert to sRGB if the color space is defined in XYZ.
+   */
+  public static float[] XYZtoRGB(float[] in)
+  {
+    float[] temp = new float[3];
+    temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2];
+    temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2];
+    temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2];
+
+    float[] out = new float[3];
+    for (int i = 0; i < 3; i++)
+      {
+	if (temp[i] < 0)
+	  temp[i] = 0.0f;
+	if (temp[i] > 1)
+	  temp[i] = 1.0f;
+	if (temp[i] <= 0.00304f)
+	  out[i] = temp[i] * 12.92f;
+	else
+	  out[i] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(temp[i])))
+	           - 0.055f;
+      }
+    return out;
+  }
+
+  /**
+   * sRGB --> CIE XYZ (D50 relative)
+   *
+   * Static as it's used by other ColorSpaceConverters to
+   * convert to XYZ if the color space is defined in RGB.
+   */
+  public static float[] RGBtoXYZ(float[] in)
+  {
+    float[] temp = new float[3];
+    float[] out = new float[3];
+    for (int i = 0; i < 3; i++)
+      if (in[i] <= 0.03928f)
+	temp[i] = in[i] / 12.92f;
+      else
+	temp[i] = (float) Math.exp(2.4 * Math.log((in[i] + 0.055) / 1.055));
+
+    /*
+     * Note: The numbers which were used to calculate this only had four
+     * digits of accuracy. So don't be fooled by the number of digits here.
+     * If someone has more accurate source, feel free to update this.
+     */
+    out[0] = (float) (0.436063750222 * temp[0] + 0.385149601465 * temp[1]
+             + 0.143086418888 * temp[2]);
+    out[1] = (float) (0.222450894035 * temp[0] + 0.71692584775 * temp[1]
+             + 0.060624511256 * temp[2]);
+    out[2] = (float) (0.0138985186 * temp[0] + 0.097079690112 * temp[1]
+             + 0.713996045725 * temp[2]);
+    return out;
+  }
+}
Index: gnu/java/awt/color/TagEntry.java
===================================================================
RCS file: gnu/java/awt/color/TagEntry.java
diff -N gnu/java/awt/color/TagEntry.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/TagEntry.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,122 @@
+/* TagEntry.java -- A utility class used for storing the tags in ICC_Profile
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * TagEntry - stores a profile tag.
+ * These are conveniently stored in a hashtable with the tag signature
+ * as a key. A legal profile can only have one tag with a given sig,
+ * so we can conveniently ignore collisions.
+ *
+ * @author Sven de Marothy
+ */
+public class TagEntry
+{
+  // tag table entry size
+  public static final int entrySize = 12;
+  private int signature;
+  private int size;
+  private int offset;
+  private byte[] data;
+
+  public TagEntry(int sig, int offset, int size, byte[] data)
+  {
+    this.signature = sig;
+    this.offset = offset;
+    this.size = size;
+    this.data = new byte[size];
+    System.arraycopy(data, offset, this.data, 0, size);
+  }
+
+  public TagEntry(int sig, byte[] data)
+  {
+    this.signature = sig;
+    this.size = data.length;
+    this.data = new byte[size];
+    System.arraycopy(data, offset, this.data, 0, size);
+  }
+
+  public byte[] getData()
+  {
+    byte[] d = new byte[size];
+    System.arraycopy(this.data, 0, d, 0, size);
+    return d;
+  }
+
+  public String hashKey()
+  {
+    return tagHashKey(signature);
+  }
+
+  public String toString()
+  {
+    String s = "";
+    s = s + (char) ((byte) ((signature >> 24) & 0xFF));
+    s = s + (char) ((byte) ((signature >> 16) & 0xFF));
+    s = s + (char) ((byte) ((signature >> 8) & 0xFF));
+    s = s + (char) ((byte) (signature & 0xFF));
+    return s;
+  }
+
+  public int getSignature()
+  {
+    return signature;
+  }
+
+  public int getSize()
+  {
+    return size;
+  }
+
+  public int getOffset()
+  {
+    return offset;
+  }
+
+  public void setOffset(int offset)
+  {
+    this.offset = offset;
+  }
+
+  public static String tagHashKey(int sig)
+  {
+    return "" + sig;
+  }
+}
Index: gnu/java/awt/color/ToneReproductionCurve.java
===================================================================
RCS file: gnu/java/awt/color/ToneReproductionCurve.java
diff -N gnu/java/awt/color/ToneReproductionCurve.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/color/ToneReproductionCurve.java	6 Nov 2004 18:50:46 -0000
@@ -0,0 +1,178 @@
+/* ToneReproductionCurve.java -- Representation of an ICC 'curv' type TRC
+   Copyright (C) 2004 Free Software Foundation
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version.
+*/
+
+package gnu.java.awt.color;
+
+
+/**
+ * ToneReproductionCurve - TRCs are used to describe RGB
+ * and Grayscale profiles. The TRC is essentially the gamma
+ * function of the color space.
+ *
+ * For example, Apple RGB has a gamma of 1.8, most monitors are ~2.2,
+ * sRGB is 2.4 with a small linear part near 0.
+ * Linear spaces are of course 1.0.
+ * (The exact function is implemented in SrgbConverter)
+ *
+ * The ICC specification allows the TRC to be described as a single
+ * Gamma value, where the function is thus out = in**gamma.
+ * Alternatively, the gamma function may be represented by a lookup table
+ * of values, in which case linear interpolation is used.
+ *
+ * @author Sven de Marothy
+ */
+public class ToneReproductionCurve
+{
+  private float[] trc;
+  private float gamma;
+  private float[] reverseTrc;
+
+  /**
+   * Constructs a TRC from a gamma values
+   */
+  public ToneReproductionCurve(float gamma)
+  {
+    trc = null;
+    reverseTrc = null;
+    this.gamma = gamma;
+  }
+
+  /**
+   * Constructs a TRC from a set of float values
+   */
+  public ToneReproductionCurve(float[] trcValues)
+  {
+    trc = new float[trcValues.length];
+    System.arraycopy(trcValues, 0, trc, 0, trcValues.length);
+    setupReverseTrc();
+  }
+
+  /**
+   * Constructs a TRC from a set of short values normalized to
+   * the 0-65535 range (as in the ICC profile file).
+   * (Note the values are treated as unsigned)
+   */
+  public ToneReproductionCurve(short[] trcValues)
+  {
+    trc = new float[trcValues.length];
+    for (int i = 0; i < trcValues.length; i++)
+      trc[i] = (float) ((int) trcValues[i] & (0xFFFF)) / 65535.0f;
+    setupReverseTrc();
+  }
+
+  /**
+   * Performs a TRC lookup
+   */
+  public float lookup(float in)
+  {
+    float out;
+
+    if (trc == null)
+      {
+	if (in == 0f)
+	  return 0.0f;
+	return (float) Math.exp(gamma * Math.log(in));
+      }
+    else
+      {
+	double alpha = in * (trc.length - 1);
+	int index = (int) Math.floor(alpha);
+	alpha = alpha - (double) index;
+	if (index >= trc.length - 1)
+	  return trc[trc.length - 1];
+	if (index <= 0)
+	  return trc[0];
+	out = (float) (trc[index] * (1.0 - alpha) + trc[index + 1] * alpha);
+      }
+    return out;
+  }
+
+  /**
+   * Performs an reverse lookup
+   */
+  public float reverseLookup(float in)
+  {
+    float out;
+
+    if (trc == null)
+      {
+	if (in == 0f)
+	  return 0.0f;
+	return (float) Math.exp((1.0 / gamma) * Math.log(in));
+      }
+    else
+      {
+	double alpha = in * (reverseTrc.length - 1);
+	int index = (int) Math.floor(alpha);
+	alpha = alpha - (double) index;
+	if (index >= reverseTrc.length - 1)
+	  return reverseTrc[reverseTrc.length - 1];
+	if (index <= 0)
+	  return reverseTrc[0];
+	out = (float) (reverseTrc[index] * (1.0 - alpha)
+	      + reverseTrc[index + 1] * alpha);
+      }
+    return out;
+  }
+
+  /**
+   * Calculates a reverse-lookup table.
+   * We use a whopping 10,000 entries.. This is should be more than any
+   * real-life TRC table (typically around 256-1024) so we won't be losing
+   * any precision.
+   *
+   * This will of course generate completely invalid results if the curve
+   * is not monotonic and invertable. But what's the alternative?
+   */
+  public void setupReverseTrc()
+  {
+    reverseTrc = new float[10000];
+    int j = 0;
+    for (int i = 0; i < 10000; i++)
+      {
+	float n = ((float) i) / 10000f;
+	while (trc[j + 1] < n && j < trc.length - 2)
+	  j++;
+
+	if (j == trc.length - 2)
+	  reverseTrc[i] = trc[trc.length - 1];
+	else
+	  reverseTrc[i] = (j + (n - trc[j]) / (trc[j + 1] - trc[j])) / ((float) trc.length);
+      }
+  }
+}
Index: java/awt/color/ICC_ColorSpace.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/color/ICC_ColorSpace.java,v
retrieving revision 1.8
diff -u -r1.8 ICC_ColorSpace.java
--- java/awt/color/ICC_ColorSpace.java	13 Feb 2003 19:28:32 -0000	1.8
+++ java/awt/color/ICC_ColorSpace.java	6 Nov 2004 18:50:46 -0000
@@ -1,46 +1,80 @@
 /* ICC_ColorSpace.java -- the canonical color space implementation
    Copyright (C) 2000, 2002 Free Software Foundation
 
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
+   This file is part of GNU Classpath.
 
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
 
 package java.awt.color;
 
+import gnu.java.awt.color.CieXyzConverter;
+import gnu.java.awt.color.ClutProfileConverter;
+import gnu.java.awt.color.ColorSpaceConverter;
+import gnu.java.awt.color.GrayProfileConverter;
+import gnu.java.awt.color.GrayScaleConverter;
+import gnu.java.awt.color.LinearRGBConverter;
+import gnu.java.awt.color.PyccConverter;
+import gnu.java.awt.color.RgbProfileConverter;
+import gnu.java.awt.color.SrgbConverter;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+
 /**
- * NEEDS DOCUMENTATION
+ * ICC_ColorSpace - an implementation of ColorSpace
+ *
+ * While an ICC_Profile class abstracts the data in an ICC profile file
+ * an ICC_ColorSpace performs the color space conversions defined by
+ * an ICC_Profile instance.
+ *
+ * Typically, an ICC_Profile will either be created using getInstance,
+ * either from the built-in colorspaces, or from an ICC profile file.
+ * Then a ICC_Colorspace will be used to perform transforms from the
+ * device colorspace to and from the profile color space.
  *
+ * The PCS used by ColorSpace is CIE XYZ relative a D50 white point.
+ * (Profiles using a CIE Lab PCS will have their input and output converted
+ * to D50 CIE XYZ accordingly.
+ *
+ * Note that a valid profile may not contain transforms in both directions,
+ * in which case the output may be undefined.
+ * All built-in colorspaces have bidirectional transforms, but developers
+ * using an ICC profile file may want to check the profile class using
+ * the ICC_Profile.getProfileClass() method. Input class profiles are
+ * guaranteed to have transforms to the PCS, output class profiles are
+ * guaranteed to have transforms from the PCS to device space.
+ *
+ * @author Sven de Marothy
  * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
  * @since 1.2
  */
@@ -82,6 +116,13 @@
   private boolean needScaleInit;
 
   /**
+   * Tells us if the PCS is CIE LAB (must be CIEXYZ otherwise)
+   */
+  private transient int type;
+  private transient int nComponents;
+  private transient ColorSpaceConverter converter;
+
+  /**
    * Constructs a new ICC_ColorSpace from an ICC_Profile object.
    *
    * @exception IllegalArgumentException If profile is inappropriate for
@@ -89,10 +130,18 @@
    */
   public ICC_ColorSpace(ICC_Profile profile)
   {
-    super(CS_sRGB, profile.getNumComponents());
+    super(profile.getColorSpaceType(), profile.getNumComponents());
+
+    converter = getConverter(profile);
     thisProfile = profile;
+    nComponents = profile.getNumComponents();
+    type = profile.getColorSpaceType();
+    makeArrays();
   }
 
+  /**
+   * Return the profile
+   */
   public ICC_Profile getProfile()
   {
     return thisProfile;
@@ -107,11 +156,7 @@
    */
   public float[] toRGB(float[] colorvalue)
   {
-    if (colorvalue.length < numComponents)
-      throw new IllegalArgumentException ();
-      
-    // FIXME: Always assumes sRGB:
-    return colorvalue;
+    return converter.toRGB(colorvalue);
   }
 
   /**
@@ -123,11 +168,7 @@
    */
   public float[] fromRGB(float[] rgbvalue)
   {
-    if (rgbvalue.length < 3)
-      throw new IllegalArgumentException ();
-    
-    // FIXME: Always assumes sRGB:
-    return rgbvalue;
+    return converter.fromRGB(rgbvalue);
   }
 
   /**
@@ -139,8 +180,7 @@
    */
   public float[] toCIEXYZ(float[] colorvalue)
   {
-    // FIXME: Not implemented
-    throw new UnsupportedOperationException();
+    return converter.toCIEXYZ(colorvalue);
   }
 
   /**
@@ -152,8 +192,12 @@
    */
   public float[] fromCIEXYZ(float[] colorvalue)
   {
-    // FIXME: Not implemented
-    throw new UnsupportedOperationException();
+    return converter.fromCIEXYZ(colorvalue);
+  }
+
+  public boolean isCS_sRGB()
+  {
+    return converter instanceof SrgbConverter;
   }
 
   /**
@@ -167,9 +211,11 @@
    */
   public float getMinValue(int idx)
   {
-    if (type == TYPE_Lab && (idx == 1 || idx == 2))
-      return -128;
-    if (idx < 0 || idx >= numComponents)
+    // FIXME: Not 100% certain of this. 
+    if (type == ColorSpace.TYPE_Lab && (idx == 1 || idx == 2))
+      return -128f;
+
+    if (idx < 0 || idx >= nComponents)
       throw new IllegalArgumentException();
     return 0;
   }
@@ -185,17 +231,83 @@
    */
   public float getMaxValue(int idx)
   {
-    if (type == TYPE_XYZ && idx >= 0 && idx <= 2)
+    if (type == ColorSpace.TYPE_XYZ && idx >= 0 && idx <= 2)
       return 1 + 32767 / 32768f;
-    else if (type == TYPE_Lab)
+    else if (type == ColorSpace.TYPE_Lab)
       {
-        if (idx == 0)
-          return 100;
-        if (idx == 1 || idx == 2)
-          return 127;
+	if (idx == 0)
+	  return 100;
+	if (idx == 1 || idx == 2)
+	  return 127;
       }
-    if (idx < 0 || idx >= numComponents)
+    if (idx < 0 || idx >= nComponents)
       throw new IllegalArgumentException();
     return 1;
   }
+
+  /**
+   * Returns a colorspace converter suitable for a given profile
+   */
+  private ColorSpaceConverter getConverter(ICC_Profile profile)
+  {
+    ColorSpaceConverter converter;
+    switch (profile.isPredefined())
+      {
+      case CS_sRGB:
+	converter = new SrgbConverter();
+	break;
+      case CS_CIEXYZ:
+	converter = new CieXyzConverter();
+	break;
+      case CS_GRAY:
+	converter = new GrayScaleConverter();
+	break;
+      case CS_LINEAR_RGB:
+	converter = new LinearRGBConverter();
+	break;
+      case CS_PYCC:
+	converter = new PyccConverter();
+	break;
+      default:
+	if (profile instanceof ICC_ProfileRGB)
+	  converter = new RgbProfileConverter((ICC_ProfileRGB) profile);
+	else if (profile instanceof ICC_ProfileGray)
+	  converter = new GrayProfileConverter((ICC_ProfileGray) profile);
+	else
+	  converter = new ClutProfileConverter(profile);
+	break;
+      }
+    return converter;
+  }
+
+  /**
+   * Serialization compatibility requires these variable to be set,
+   * although we don't use them. Perhaps we should?
+   */
+  private void makeArrays()
+  {
+    minVal = new float[nComponents];
+    maxVal = new float[nComponents];
+
+    invDiffMinMax = diffMinMax = null;
+    for (int i = 0; i < nComponents; i++)
+      {
+	minVal[i] = getMinValue(i);
+	maxVal[i] = getMaxValue(i);
+      }
+    needScaleInit = true;
+  }
+
+  /**
+   * Deserializes the object
+   */
+  private void readObject(ObjectInputStream s)
+                   throws IOException, ClassNotFoundException
+  {
+    s.defaultReadObject();
+    // set up objects
+    converter = getConverter(thisProfile);
+    nComponents = thisProfile.getNumComponents();
+    type = thisProfile.getColorSpaceType();
+  }
 } // class ICC_ColorSpace
Index: java/awt/color/ICC_Profile.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/color/ICC_Profile.java,v
retrieving revision 1.8.24.1
diff -u -r1.8.24.1 ICC_Profile.java
--- java/awt/color/ICC_Profile.java	27 Sep 2004 15:14:27 -0000	1.8.24.1
+++ java/awt/color/ICC_Profile.java	6 Nov 2004 18:50:46 -0000
@@ -1,43 +1,44 @@
 /* ICC_Profile.java -- color space profiling
    Copyright (C) 2000, 2002 Free Software Foundation
 
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
+   This file is part of GNU Classpath.
 
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
 
 package java.awt.color;
 
+import gnu.java.awt.color.ProfileHeader;
+import gnu.java.awt.color.TagEntry;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -47,9 +48,36 @@
 import java.io.ObjectStreamException;
 import java.io.OutputStream;
 import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
 
 /**
- * STUBBED
+ * ICC Profile - represents an ICC Color profile.
+ * The ICC profile format is a standard file format which maps the transform
+ * from a device color space to a standard Profile Color Space (PCS), which
+ * can either be CIE L*a*b or CIE XYZ.
+ * (With the exception of device link profiles which map from one device space
+ * to another)
+ *
+ * ICC profiles calibrated to specific input/output devices are used when color
+ * fidelity is of importance.
+ *
+ * An instance of ICC_Profile can be created using the getInstance() methods,
+ * either using one of the predefined color spaces enumerated in ColorSpace,
+ * or from an ICC profile file, or from an input stream.
+ *
+ * An ICC_ColorSpace object can then be created to transform color values
+ * through the profile.
+ *
+ * The ICC_Profile class implements the version 2 format specified by
+ * International Color Consortium Specification ICC.1:1998-09,
+ * and it's addendum ICC.1A:1999-04, April 1999
+ * (available at www.color.org)
+ *
+ * @author Sven de Marothy
  * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
  * @since 1.2
  */
@@ -60,6 +88,9 @@
    */
   private static final long serialVersionUID = -3938515861990936766L;
 
+  /**
+   * ICC Profile classes
+   */
   public static final int CLASS_INPUT = 0;
   public static final int CLASS_DISPLAY = 1;
   public static final int CLASS_OUTPUT = 2;
@@ -68,92 +99,112 @@
   public static final int CLASS_ABSTRACT = 5;
   public static final int CLASS_NAMEDCOLOR = 6;
 
-  public static final int icSigXYZData = 1482250784;
-  public static final int icSigLabData = 1281450528;
-  public static final int icSigLuvData = 1282766368;
-  public static final int icSigYCbCrData = 1497588338;
-  public static final int icSigYxyData = 1501067552;
-  public static final int icSigRgbData = 1380401696;
-  public static final int icSigGrayData = 1196573017;
-  public static final int icSigHsvData = 1213421088;
-  public static final int icSigHlsData = 1212961568;
-  public static final int icSigCmykData = 1129142603;
-  public static final int icSigCmyData = 1129142560;
-  public static final int icSigSpace2CLR = 843271250;
-  public static final int icSigSpace3CLR = 860048466;
-  public static final int icSigSpace4CLR = 876825682;
-  public static final int icSigSpace5CLR = 893602898;
-  public static final int icSigSpace6CLR = 910380114;
-  public static final int icSigSpace7CLR = 927157330;
-  public static final int icSigSpace8CLR = 943934546;
-  public static final int icSigSpace9CLR = 960711762;
-  public static final int icSigSpaceACLR = 1094929490;
-  public static final int icSigSpaceBCLR = 1111706706;
-  public static final int icSigSpaceCCLR = 1128483922;
-  public static final int icSigSpaceDCLR = 1145261138;
-  public static final int icSigSpaceECLR = 1162038354;
-  public static final int icSigSpaceFCLR = 1178815570;
-
-  public static final int icSigInputClass = 1935896178;
-  public static final int icSigDisplayClass = 1835955314;
-  public static final int icSigOutputClass = 1886549106;
-  public static final int icSigLinkClass = 1818848875;
-  public static final int icSigAbstractClass = 1633842036;
-  public static final int icSigColorSpaceClass = 1936744803;
-  public static final int icSigNamedColorClass = 1852662636;
+  /**
+   * ICC Profile class signatures
+   */
+  public static final int icSigInputClass = 0x73636e72; // 'scnr'
+  public static final int icSigDisplayClass = 0x6d6e7472; // 'mntr'
+  public static final int icSigOutputClass = 0x70727472; // 'prtr'
+  public static final int icSigLinkClass = 0x6c696e6b; // 'link'
+  public static final int icSigColorSpaceClass = 0x73706163; // 'spac'
+  public static final int icSigAbstractClass = 0x61627374; // 'abst'
+  public static final int icSigNamedColorClass = 0x6e6d636c; // 'nmcl'
+
+  /**
+   * Color space signatures
+   */
+  public static final int icSigXYZData = 0x58595A20; // 'XYZ ' 
+  public static final int icSigLabData = 0x4C616220; // 'Lab '
+  public static final int icSigLuvData = 0x4C757620; // 'Luv '
+  public static final int icSigYCbCrData = 0x59436272; // 'YCbr'
+  public static final int icSigYxyData = 0x59787920; // 'Yxy '
+  public static final int icSigRgbData = 0x52474220; // 'RGB '
+  public static final int icSigGrayData = 0x47524159; // 'GRAY'
+  public static final int icSigHsvData = 0x48535620; // 'HSV '
+  public static final int icSigHlsData = 0x484C5320; // 'HLS '
+  public static final int icSigCmykData = 0x434D594B; // 'CMYK'
+  public static final int icSigCmyData = 0x434D5920; // 'CMY '
+  public static final int icSigSpace2CLR = 0x32434C52; // '2CLR'
+  public static final int icSigSpace3CLR = 0x33434C52; // '3CLR'
+  public static final int icSigSpace4CLR = 0x34434C52; // '4CLR'
+  public static final int icSigSpace5CLR = 0x35434C52; // '5CLR'
+  public static final int icSigSpace6CLR = 0x36434C52; // '6CLR'
+  public static final int icSigSpace7CLR = 0x37434C52; // '7CLR'
+  public static final int icSigSpace8CLR = 0x38434C52; // '8CLR'
+  public static final int icSigSpace9CLR = 0x39434C52; // '9CLR'
+  public static final int icSigSpaceACLR = 0x41434C52; // 'ACLR'
+  public static final int icSigSpaceBCLR = 0x42434C52; // 'BCLR'
+  public static final int icSigSpaceCCLR = 0x43434C52; // 'CCLR'
+  public static final int icSigSpaceDCLR = 0x44434C52; // 'DCLR'
+  public static final int icSigSpaceECLR = 0x45434C52; // 'ECLR'
+  public static final int icSigSpaceFCLR = 0x46434C52; // 'FCLR'
 
+  /**
+   * Rendering intents
+   */
   public static final int icPerceptual = 0;
   public static final int icRelativeColorimetric = 1;
   public static final int icSaturation = 2;
   public static final int icAbsoluteColorimetric = 3;
 
-  public static final int icSigHead = 1751474532;
-  public static final int icSigAToB0Tag = 1093812784;
-  public static final int icSigAToB1Tag = 1093812785;
-  public static final int icSigAToB2Tag = 1093812786;
-  public static final int icSigBlueColorantTag = 1649957210;
-  public static final int icSigBlueTRCTag = 1649693251;
-  public static final int icSigBToA0Tag = 1110589744;
-  public static final int icSigBToA1Tag = 1110589745;
-  public static final int icSigBToA2Tag = 1110589746;
-  public static final int icSigCalibrationDateTimeTag = 1667329140;
-  public static final int icSigCharTargetTag = 1952543335;
-  public static final int icSigCopyrightTag = 1668313716;
-  public static final int icSigCrdInfoTag = 1668441193;
-  public static final int icSigDeviceMfgDescTag = 1684893284;
-  public static final int icSigDeviceModelDescTag = 1684890724;
-  public static final int icSigDeviceSettingsTag = 1684371059;
-  public static final int icSigGamutTag = 1734438260;
-  public static final int icSigGrayTRCTag = 1800688195;
-  public static final int icSigGreenColorantTag = 1733843290;
-  public static final int icSigGreenTRCTag = 1733579331;
-  public static final int icSigLuminanceTag = 1819635049;
-  public static final int icSigMeasurementTag = 1835360627;
-  public static final int icSigMediaBlackPointTag = 1651208308;
-  public static final int icSigMediaWhitePointTag = 2004119668;
-  public static final int icSigNamedColor2Tag = 1852009522;
-  public static final int icSigOutputResponseTag = 1919251312;
-  public static final int icSigPreview0Tag = 1886545200;
-  public static final int icSigPreview1Tag = 1886545201;
-  public static final int icSigPreview2Tag = 1886545202;
-  public static final int icSigProfileDescriptionTag = 1684370275;
-  public static final int icSigProfileSequenceDescTag = 1886610801;
-  public static final int icSigPs2CRD0Tag = 1886610480;
-  public static final int icSigPs2CRD1Tag = 1886610481;
-  public static final int icSigPs2CRD2Tag = 1886610482;
-  public static final int icSigPs2CRD3Tag = 1886610483;
-  public static final int icSigPs2CSATag = 1886597747;
-  public static final int icSigPs2RenderingIntentTag = 1886597737;
-  public static final int icSigRedColorantTag = 1918392666;
-  public static final int icSigRedTRCTag = 1918128707;
-  public static final int icSigScreeningDescTag = 1935897188;
-  public static final int icSigScreeningTag = 1935897198;
-  public static final int icSigTechnologyTag = 1952801640;
-  public static final int icSigUcrBgTag = 1650877472;
-  public static final int icSigViewingCondDescTag = 1987405156;
-  public static final int icSigViewingConditionsTag = 1986618743;
-  public static final int icSigChromaticityTag = 1667789421;
+  /**
+   * Tag signatures
+   */
+  public static final int icSigAToB0Tag = 0x41324230; // 'A2B0' 
+  public static final int icSigAToB1Tag = 0x41324231; // 'A2B1' 
+  public static final int icSigAToB2Tag = 0x41324232; // 'A2B2' 
+  public static final int icSigBlueColorantTag = 0x6258595A; // 'bXYZ' 
+  public static final int icSigBlueTRCTag = 0x62545243; // 'bTRC' 
+  public static final int icSigBToA0Tag = 0x42324130; // 'B2A0' 
+  public static final int icSigBToA1Tag = 0x42324131; // 'B2A1' 
+  public static final int icSigBToA2Tag = 0x42324132; // 'B2A2' 
+  public static final int icSigCalibrationDateTimeTag = 0x63616C74; // 'calt' 
+  public static final int icSigCharTargetTag = 0x74617267; // 'targ' 
+  public static final int icSigCopyrightTag = 0x63707274; // 'cprt' 
+  public static final int icSigCrdInfoTag = 0x63726469; // 'crdi' 
+  public static final int icSigDeviceMfgDescTag = 0x646D6E64; // 'dmnd' 
+  public static final int icSigDeviceModelDescTag = 0x646D6464; // 'dmdd' 
+  public static final int icSigDeviceSettingsTag = 0x64657673; // 'devs' 
+  public static final int icSigGamutTag = 0x67616D74; // 'gamt' 
+  public static final int icSigGrayTRCTag = 0x6b545243; // 'kTRC' 
+  public static final int icSigGreenColorantTag = 0x6758595A; // 'gXYZ' 
+  public static final int icSigGreenTRCTag = 0x67545243; // 'gTRC' 
+  public static final int icSigLuminanceTag = 0x6C756d69; // 'lumi' 
+  public static final int icSigMeasurementTag = 0x6D656173; // 'meas' 
+  public static final int icSigMediaBlackPointTag = 0x626B7074; // 'bkpt' 
+  public static final int icSigMediaWhitePointTag = 0x77747074; // 'wtpt' 
+  public static final int icSigNamedColorTag = 0x6E636f6C; // ''ncol'  
+  public static final int icSigNamedColor2Tag = 0x6E636C32; // 'ncl2' 
+  public static final int icSigOutputResponseTag = 0x72657370; // 'resp' 
+  public static final int icSigPreview0Tag = 0x70726530; // 'pre0' 
+  public static final int icSigPreview1Tag = 0x70726531; // 'pre1' 
+  public static final int icSigPreview2Tag = 0x70726532; // 'pre2' 
+  public static final int icSigProfileDescriptionTag = 0x64657363; // 'desc' 
+  public static final int icSigProfileSequenceDescTag = 0x70736571; // 'pseq' 
+  public static final int icSigPs2CRD0Tag = 0x70736430; // 'psd0' 
+  public static final int icSigPs2CRD1Tag = 0x70736431; // 'psd1' 
+  public static final int icSigPs2CRD2Tag = 0x70736432; // 'psd2' 
+  public static final int icSigPs2CRD3Tag = 0x70736433; // 'psd3' 
+  public static final int icSigPs2CSATag = 0x70733273; // 'ps2s' 
+  public static final int icSigPs2RenderingIntentTag = 0x70733269; // 'ps2i' 
+  public static final int icSigRedColorantTag = 0x7258595A; // 'rXYZ' 
+  public static final int icSigRedTRCTag = 0x72545243; // 'rTRC' 
+  public static final int icSigScreeningDescTag = 0x73637264; // 'scrd' 
+  public static final int icSigScreeningTag = 0x7363726E; // 'scrn' 
+  public static final int icSigTechnologyTag = 0x74656368; // 'tech' 
+  public static final int icSigUcrBgTag = 0x62666420; // 'bfd ' 
+  public static final int icSigViewingCondDescTag = 0x76756564; // 'vued' 
+  public static final int icSigViewingConditionsTag = 0x76696577; // 'view' 
+  public static final int icSigChromaticityTag = 0x6368726D; // 'chrm'
+
+  /**
+   * Non-ICC tag 'head' for use in retrieving the header with getData()
+   */
+  public static final int icSigHead = 0x68656164;
 
+  /**
+   * Header offsets
+   */
   public static final int icHdrSize = 0;
   public static final int icHdrCmmId = 4;
   public static final int icHdrVersion = 8;
@@ -171,129 +222,1026 @@
   public static final int icHdrIlluminant = 68;
   public static final int icHdrCreator = 80;
 
+  /**
+   *
+   */
   public static final int icTagType = 0;
   public static final int icTagReserved = 4;
   public static final int icCurveCount = 8;
   public static final int icCurveData = 12;
-
   public static final int icXYZNumberX = 8;
 
   /**
+   * offset of the Tag table
+   */
+  private static final int tagTableOffset = 128;
+
+  /**
    * @serial
    */
-  final int iccProfileSerializedDataVersion = 1;
+  private final int iccProfileSerializedDataVersion = 1;
+
+  /**
+   * Constants related to generating profiles for
+   * built-in colorspace profiles
+   */
+  /**
+   * Copyright notice to stick into built-in-profile files.
+   */
+  private static final String copyrightNotice = "Generated by GNU Classpath.";
+
+  /**
+   * Resolution of the TRC to use for predefined profiles.
+   * 1024 should suffice.
+   */
+  private static final int TRC_POINTS = 1024;
+
+  /**
+   * CIE 1931 D50 white point (in Lab coordinates)
+   */
+  private static final float[] D50 = { 0.96422f, 1.00f, 0.82521f };
 
-  transient int profileID;
+  /**
+   * Color space profile ID
+   * Set to the predefined profile class (e.g. CS_sRGB) if a predefined
+   * color space is used, set to -1 otherwise.
+   * (or if the profile has been modified)
+   */
+  private transient int profileID;
 
+  /**
+   * The profile header data
+   */
+  private transient ProfileHeader header;
+
+  /**
+   * A hashtable containing the profile tags as TagEntry objects
+   */
+  private transient Hashtable tagTable;
+
+  /**
+   * Contructor for predefined colorspaces
+   */
   ICC_Profile(int profileID)
   {
-    this.profileID = profileID;
+    header = null;
+    tagTable = null;
+    createProfile(profileID);
+  }
+
+  /**
+   * Constructs an ICC_Profile from a header and a table of loaded tags.
+   */
+  ICC_Profile(ProfileHeader h, Hashtable tags) throws IllegalArgumentException
+  {
+    header = h;
+    tagTable = tags;
+    profileID = -1; // Not a predefined color space
   }
 
+  /**
+   * Constructs an ICC_Profile from a byte array of data.
+   */
+  ICC_Profile(byte[] data) throws IllegalArgumentException
+  {
+    // get header and verify it
+    header = new ProfileHeader(data);
+    header.verifyHeader(data.length);
+    tagTable = createTagTable(data);
+    profileID = -1; // Not a predefined color space
+  }
+
+  /**
+   * Free up the used memory.
+   */
   protected void finalize()
   {
-    // XXX What resources should we free?
+    header = null;
+    tagTable = null;
   }
 
+  /**
+   * Returns an ICC_Profile instance from a byte array of profile data.
+   *
+   * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+   * may be returned if appropriate.
+   *
+   * @throws IllegalArgumentException if the profile data is an invalid
+   * v2 profile.
+   *
+   * @param data - the profile data
+   * @return An ICC_Profile object
+   */
   public static ICC_Profile getInstance(byte[] data)
   {
-    throw new Error("not implemented");
+    ProfileHeader header = new ProfileHeader(data);
+
+    // verify it as a correct ICC header, including size
+    header.verifyHeader(data.length);
+
+    Hashtable tags = createTagTable(data);
+
+    if (isRGBProfile(header, tags))
+      return new ICC_ProfileRGB(data);
+    if (isGrayProfile(header, tags))
+      return new ICC_ProfileGray(data);
+
+    return new ICC_Profile(header, tags);
   }
 
+  /**
+   * Returns an predefined ICC_Profile instance.
+   *
+   * This will construct an ICC_Profile instance from one of the predefined
+   * color spaces in the ColorSpace class. (e.g. CS_sRGB, CS_GRAY, etc)
+   *
+   * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+   * may be returned if appropriate.
+   *
+   * @return An ICC_Profile object
+   */
   public static ICC_Profile getInstance(int cspace)
   {
+    if (cspace == ColorSpace.CS_sRGB || cspace == ColorSpace.CS_LINEAR_RGB)
+      return new ICC_ProfileRGB(cspace);
+    if (cspace == ColorSpace.CS_GRAY)
+      return new ICC_ProfileGray(cspace);
     return new ICC_Profile(cspace);
   }
 
-  public static ICC_Profile getInstance(String filename) throws IOException
+  /**
+   * Returns an ICC_Profile instance from an ICC Profile file.
+   *
+   * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+   * may be returned if appropriate.
+   *
+   * @throws IllegalArgumentException if the profile data is an invalid
+   * v2 profile.
+   * @throws IOException if the file could not be read.
+   *
+   * @param filename - the file name of the profile file.
+   * @return An ICC_Profile object
+   */
+  public static ICC_Profile getInstance(String filename)
+                                 throws IOException
   {
     return getInstance(new FileInputStream(filename));
   }
 
-  public static ICC_Profile getInstance(InputStream in) throws IOException
+  /**
+   * Returns an ICC_Profile instance from an InputStream.
+   *
+   * This method can be used for reading ICC profiles embedded in files
+   * which support this. (JPEG and SVG for instance).
+   *
+   * The stream is treated in the following way: The profile header
+   * (128 bytes) is read first, and the header is validated. If the profile
+   * header is valid, it will then attempt to read the rest of the profile
+   * from the stream. The stream is not closed after reading.
+   *
+   * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
+   * may be returned if appropriate.
+   *
+   * @throws IllegalArgumentException if the profile data is an invalid
+   * v2 profile.
+   * @throws IOException if the stream could not be read.
+   *
+   * @param in - the input stream to read the profile from.
+   * @return An ICC_Profile object
+   */
+  public static ICC_Profile getInstance(InputStream in)
+                                 throws IOException
   {
-    throw new Error("not implemented");
+    // read the header
+    byte[] headerData = new byte[ProfileHeader.HEADERSIZE];
+    if (in.read(headerData) != ProfileHeader.HEADERSIZE)
+      throw new IllegalArgumentException("Invalid profile header");
+
+    ProfileHeader header = new ProfileHeader(headerData);
+
+    // verify it as a correct ICC header, but do not verify the
+    // size as we are reading from a stream.
+    header.verifyHeader(-1);
+
+    // get the size
+    byte[] data = new byte[header.getSize()];
+    System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE);
+
+    // read the rest
+    if (in.read(data, ProfileHeader.HEADERSIZE,
+                header.getSize() - ProfileHeader.HEADERSIZE) != header.getSize()
+        - ProfileHeader.HEADERSIZE)
+      throw new IOException("Incorrect profile size");
+
+    return getInstance(data);
   }
 
+  /**
+   * Returns the major version number
+   */
   public int getMajorVersion()
   {
-    throw new Error("not implemented");
+    return header.getMajorVersion();
   }
 
+  /**
+   * Returns the minor version number.
+   *
+   * Only the least-significant byte contains data, in BCD form:
+   * the least-significant nibble is the BCD bug fix revision,
+   * the most-significant nibble is the BCD minor revision number.
+   *
+   * (E.g. For a v2.1.0 profile this will return <code>0x10</code>)
+   */
   public int getMinorVersion()
   {
-    throw new Error("not implemented");
+    return header.getMinorVersion();
   }
 
+  /**
+   * Returns the device class of this profile,
+   *
+   * (E.g. CLASS_INPUT for a scanner profile,
+   * CLASS_OUTPUT for a printer)
+   */
   public int getProfileClass()
   {
-    throw new Error("not implemented");
+    return header.getProfileClass();
   }
 
+  /**
+   * Returns the color space of this profile, in terms
+   * of the color space constants defined in ColorSpace.
+   * (For example, it may be a ColorSpace.TYPE_RGB)
+   */
   public int getColorSpaceType()
   {
-    throw new Error("not implemented");
+    return header.getColorSpace();
   }
 
+  /**
+   * Returns the color space of this profile's Profile Connection Space (OCS)
+   *
+   * In terms of the color space constants defined in ColorSpace.
+   * This may be TYPE_XYZ or TYPE_Lab
+   */
   public int getPCSType()
   {
-    throw new Error("not implemented");
+    return header.getProfileColorSpace();
   }
 
+  /**
+   * Writes the profile data to an ICC profile file.
+   * @param filename - The name of the file to write
+   * @throws IOException if the write failed.
+   */
   public void write(String filename) throws IOException
   {
-    write(new FileOutputStream(filename));
+    FileOutputStream out = new FileOutputStream(filename);
+    write(out);
+    out.flush();
+    out.close();
   }
 
+  /**
+   * Writes the profile data in ICC profile file-format to a stream.
+   * This is useful for embedding ICC profiles in file formats which
+   * support this (such as JPEG and SVG).
+   *
+   * The stream is not closed after writing.
+   * @param out - The outputstream to which the profile data should be written
+   * @throws IOException if the write failed.
+   */
   public void write(OutputStream out) throws IOException
   {
-    throw new Error("not implemented");
+    out.write(getData());
   }
 
+  /**
+   * Returns the data corresponding to this ICC_Profile as a byte array.
+   *
+   * @return The data in a byte array,
+   * where the first element corresponds to first byte of the profile file.
+   */
   public byte[] getData()
   {
-    throw new Error("not implemented");
+    int size = getSize();
+    byte[] data = new byte[size];
+
+    // Header
+    System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
+    // # of tags
+    byte[] tt = getTagTable();
+    System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
+
+    Enumeration e = tagTable.elements();
+    while (e.hasMoreElements())
+      {
+	TagEntry tag = (TagEntry) e.nextElement();
+	System.arraycopy(tag.getData(), 0, 
+			 data, tag.getOffset(), tag.getSize());
+      }
+    return data;
   }
 
+  /**
+   * Returns the ICC profile tag data
+   * The non ICC-tag icSigHead is also permitted to request the header data.
+   *
+   * @param tagSignature The ICC signature of the requested tag
+   * @return A byte array containing the tag data
+   */
   public byte[] getData(int tagSignature)
   {
-    throw new Error("not implemented");
+    if (tagSignature == icSigHead)
+      return header.getData(getSize());
+
+    TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
+    if (t == null)
+      return null;
+    return t.getData();
   }
 
+  /**
+   * Sets the ICC profile tag data.
+   *
+   * Note that an ICC profile can only contain one tag of each type, if
+   * a tag already exists with the given signature, it is replaced.
+   *
+   * @param tagSignature - The signature of the tag to set
+   * @param data - A byte array containing the tag data
+   */
   public void setData(int tagSignature, byte[] data)
   {
-    throw new Error("not implemented");
+    profileID = -1; // Not a predefined color space if modified.
+
+    if (tagSignature == icSigHead)
+      header = new ProfileHeader(data);
+    else
+      {
+	TagEntry t = new TagEntry(tagSignature, data);
+	tagTable.put(t.hashKey(), t);
+      }
   }
 
+  /**
+   * Get the number of components in the profile's device color space.
+   */
   public int getNumComponents()
   {
-    switch (profileID)
+    int[] lookup = 
+                   {
+                     ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
+                     ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
+                     ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
+                     ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
+                     ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
+                     ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
+                     ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
+                     ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
+                     ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
+                     ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
+                     ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
+                     ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
+                     ColorSpace.TYPE_FCLR, 15
+                   };
+    for (int i = 0; i < lookup.length; i += 2)
+      if (header.getColorSpace() == lookup[i])
+	return lookup[i + 1];
+    return 3; // should never happen.
+  }
+
+  /**
+   * After deserializing we must determine if the class we want
+   * is really one of the more specialized ICC_ProfileRGB or
+   * ICC_ProfileGray classes.
+   */
+  protected Object readResolve() throws ObjectStreamException
+  {
+    if (isRGBProfile(header, tagTable))
+      return new ICC_ProfileRGB(getData());
+    if (isGrayProfile(header, tagTable))
+      return new ICC_ProfileGray(getData());
+    return this;
+  }
+
+  /**
+   * Deserializes an instance
+   */
+  private void readObject(ObjectInputStream s)
+                   throws IOException, ClassNotFoundException
+  {
+    s.defaultReadObject();
+    String predef = (String) s.readObject();
+    byte[] data = (byte[]) s.readObject();
+
+    if (data != null)
+      {
+	header = new ProfileHeader(data);
+	tagTable = createTagTable(data);
+	profileID = -1; // Not a predefined color space
+      }
+
+    if (predef != null)
+      {
+	predef = predef.intern();
+	if (predef.equals("CS_sRGB"))
+	  createProfile(ColorSpace.CS_sRGB);
+	if (predef.equals("CS_LINEAR_RGB"))
+	  createProfile(ColorSpace.CS_LINEAR_RGB);
+	if (predef.equals("CS_CIEXYZ"))
+	  createProfile(ColorSpace.CS_CIEXYZ);
+	if (predef.equals("CS_GRAY"))
+	  createProfile(ColorSpace.CS_GRAY);
+	if (predef.equals("CS_PYCC"))
+	  createProfile(ColorSpace.CS_PYCC);
+      }
+  }
+
+  /**
+   * Serializes an instance
+   * The format is a String and a byte array,
+   * The string is non-null if the instance is one of the built-in profiles.
+   * Otherwise the byte array is non-null and represents the profile data.
+   */
+  private void writeObject(ObjectOutputStream s) throws IOException
+  {
+    s.defaultWriteObject();
+    if (profileID == ColorSpace.CS_sRGB)
+      s.writeObject("CS_sRGB");
+    else if (profileID == ColorSpace.CS_LINEAR_RGB)
+      s.writeObject("CS_LINEAR_RGB");
+    else if (profileID == ColorSpace.CS_CIEXYZ)
+      s.writeObject("CS_CIEXYZ");
+    else if (profileID == ColorSpace.CS_GRAY)
+      s.writeObject("CS_GRAY");
+    else if (profileID == ColorSpace.CS_PYCC)
+      s.writeObject("CS_PYCC");
+    else
+      {
+	s.writeObject(null); // null string
+	s.writeObject(getData()); // data
+	return;
+      }
+    s.writeObject(null); // null data
+  }
+
+  /**
+   * Sorts a ICC profile byte array into TagEntry objects stored in
+   * a hash table.
+   */
+  private static Hashtable createTagTable(byte[] data)
+                                   throws IllegalArgumentException
+  {
+    ByteBuffer buf = ByteBuffer.wrap(data);
+    int nTags = buf.getInt(tagTableOffset);
+
+    Hashtable tagTable = new Hashtable();
+    for (int i = 0; i < nTags; i++)
+      {
+	TagEntry te = new TagEntry(buf.getInt(tagTableOffset
+	                                      + i * TagEntry.entrySize + 4),
+	                           buf.getInt(tagTableOffset
+	                                      + i * TagEntry.entrySize + 8),
+	                           buf.getInt(tagTableOffset
+	                                      + i * TagEntry.entrySize + 12),
+	                           data);
+
+	//	    System.out.println("Tag:"+te);
+	if (tagTable.put(te.hashKey(), te) != null)
+	  throw new IllegalArgumentException("Duplicate tag in profile:" + te);
+      }
+    return tagTable;
+  }
+
+  /**
+   * Returns the total size of the padded, stored data
+   * Note: Tags must be stored on 4-byte aligned offsets.
+   */
+  private int getSize()
+  {
+    int totalSize = ProfileHeader.HEADERSIZE; // size of header
+
+    int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table	
+    if ((tagTableSize & 0x0003) != 0)
+      tagTableSize += 4 - (tagTableSize & 0x0003); // pad
+    totalSize += tagTableSize;
+
+    Enumeration e = tagTable.elements();
+    while (e.hasMoreElements())
+      { // tag data
+	int tagSize = ((TagEntry) e.nextElement()).getSize();
+	if ((tagSize & 0x0003) != 0)
+	  tagSize += 4 - (tagSize & 0x0003); // pad
+	totalSize += tagSize;
+      }
+    return totalSize;
+  }
+
+  /**
+   * Generates the tag index table
+   */
+  private byte[] getTagTable()
+  {
+    int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
+    if ((tagTableSize & 0x0003) != 0)
+      tagTableSize += 4 - (tagTableSize & 0x0003); // pad 
+
+    int offset = 4;
+    int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
+    ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
+    buf.putInt(tagTable.size()); // number of tags
+
+    Enumeration e = tagTable.elements();
+    while (e.hasMoreElements())
+      {
+	TagEntry tag = (TagEntry) e.nextElement();
+	buf.putInt(offset, tag.getSignature());
+	buf.putInt(offset + 4, tagOffset);
+	buf.putInt(offset + 8, tag.getSize());
+	tag.setOffset(tagOffset);
+	int tagSize = tag.getSize();
+	if ((tagSize & 0x0003) != 0)
+	  tagSize += 4 - (tagSize & 0x0003); // pad	    
+	tagOffset += tagSize;
+	offset += 12;
+      }
+    return buf.array();
+  }
+
+  /**
+   * Returns if the criteria for an ICC_ProfileRGB are met.
+   * This means:
+   * Color space is TYPE_RGB
+   * (r,g,b)ColorantTags included
+   * (r,g,b)TRCTags included
+   * mediaWhitePointTag included
+   */
+  private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
+  {
+    if (header.getColorSpace() != ColorSpace.TYPE_RGB)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
+      return false;
+    return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
+  }
+
+  /**
+   * Returns if the criteria for an ICC_ProfileGray are met.
+   * This means:
+   * Colorspace is TYPE_GRAY
+   * grayTRCTag included
+   * mediaWhitePointTag included
+   */
+  private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
+  {
+    if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
+      return false;
+    if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
+      return false;
+    return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
+  }
+
+  /**
+   * Returns curve data for a 'curv'-type tag
+   * If it's a gamma curve, a singly entry will be returned with the
+   * gamma value (including 1.0 for linear response)
+   * Otherwise the TRC table is returned.
+   *
+   * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray)
+   */
+  short[] getCurve(int signature)
+  {
+    byte[] data = getData(signature);
+    short[] curve;
+
+    // can't find tag?
+    if (data == null)
+      return null;
+
+    // not an curve type tag?
+    ByteBuffer buf = ByteBuffer.wrap(data);
+    if (buf.getInt(0) != 0x63757276) // 'curv' type
+      return null;
+    int count = buf.getInt(8);
+    if (count == 0)
+      {
+	curve = new short[1];
+	curve[0] = 0x0100; // 1.00 in u8fixed8
+	return curve;
+      }
+    if (count == 1)
+      {
+	curve = new short[1];
+	curve[0] = buf.getShort(12); // other u8fixed8 gamma
+	return curve;
+      }
+    curve = new short[count];
+    for (int i = 0; i < count; i++)
+      curve[i] = buf.getShort(12 + i * 2);
+    return curve;
+  }
+
+  /**
+   * Returns XYZ tristimulus values for an 'XYZ ' type tag
+   * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag.
+   *
+   * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray)
+   */
+  float[] getXYZData(int signature)
+  {
+    byte[] data = getData(signature);
+
+    // can't find tag?
+    if (data == null)
+      return null;
+
+    // not an XYZData type tag?
+    ByteBuffer buf = ByteBuffer.wrap(data);
+    if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type
+      return null;
+
+    float[] point = new float[3];
+
+    // get the X,Y,Z tristimulus values
+    point[0] = ((float) buf.getInt(8)) / 65536f;
+    point[1] = ((float) buf.getInt(12)) / 65536f;
+    point[2] = ((float) buf.getInt(16)) / 65536f;
+    return point;
+  }
+
+  /**
+   * Returns the profile ID if it's a predefined profile
+   * Or -1 for a profile loaded from an ICC profile
+   *
+   * (Package private - used by ICC_ColorSpace)
+   */
+  int isPredefined()
+  {
+    return profileID;
+  }
+
+  /**
+   * Creates a tag of XYZ-value type.
+   */
+  private byte[] makeXYZData(float[] values)
+  {
+    ByteBuffer buf = ByteBuffer.allocate(20);
+    buf.putInt(0, icSigXYZData); // 'XYZ '
+    buf.putInt(4, 0);
+    buf.putInt(8, (int) (values[0] * 65536.0));
+    buf.putInt(12, (int) (values[1] * 65536.0));
+    buf.putInt(16, (int) (values[2] * 65536.0));
+    return buf.array();
+  }
+
+  /**
+   * Creates a tag of text type
+   */
+  private byte[] makeTextTag(String text)
+  {
+    int length = text.length();
+    ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
+    byte[] data;
+    try
+      {
+	data = text.getBytes("US-ASCII");
+      }
+    catch (UnsupportedEncodingException e)
+      {
+	data = new byte[length]; // shouldn't happen
+      }
+
+    buf.putInt(0, (int) 0x74657874); // 'text'
+    buf.putInt(4, 0);
+    for (int i = 0; i < length; i++)
+      buf.put(8 + i, data[i]);
+    buf.put(8 + length, (byte) 0); // null-terminate
+    return buf.array();
+  }
+
+  /**
+   * Creates a tag of textDescriptionType
+   */
+  private byte[] makeDescTag(String text)
+  {
+    int length = text.length();
+    ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
+    buf.putInt(0, (int) 0x64657363); // 'desc'
+    buf.putInt(4, 0); // reserved 
+    buf.putInt(8, length + 1); // ASCII length, including null termination
+    byte[] data;
+
+    try
+      {
+	data = text.getBytes("US-ASCII");
+      }
+    catch (UnsupportedEncodingException e)
+      {
+	data = new byte[length]; // shouldn't happen
+      }
+
+    for (int i = 0; i < length; i++)
+      buf.put(12 + i, data[i]);
+    buf.put(12 + length, (byte) 0); // null-terminate
+
+    for (int i = 0; i < 39; i++)
+      buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore
+
+    return buf.array();
+  }
+
+  /**
+   * Creates a tag of TRC type (linear curve)
+   */
+  private byte[] makeTRC()
+  {
+    ByteBuffer buf = ByteBuffer.allocate(12);
+    buf.putInt(0, 0x63757276); // 'curv' type
+    buf.putInt(4, 0); // reserved
+    buf.putInt(8, 0);
+    return buf.array();
+  }
+
+  /**
+   * Creates a tag of TRC type (single gamma value)
+   */
+  private byte[] makeTRC(float gamma)
+  {
+    short gammaValue = (short) (gamma * 256f);
+    ByteBuffer buf = ByteBuffer.allocate(14);
+    buf.putInt(0, 0x63757276); // 'curv' type
+    buf.putInt(4, 0); // reserved
+    buf.putInt(8, 1);
+    buf.putShort(12, gammaValue); // 1.00 in u8fixed8
+    return buf.array();
+  }
+
+  /**
+   * Creates a tag of TRC type (TRC curve points)
+   */
+  private byte[] makeTRC(float[] trc)
+  {
+    ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
+    buf.putInt(0, 0x63757276); // 'curv' type
+    buf.putInt(4, 0); // reserved
+    buf.putInt(8, trc.length); // number of points
+
+    // put the curve values 
+    for (int i = 0; i < trc.length; i++)
+      buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
+
+    return buf.array();
+  }
+
+  /**
+   * Creates an identity color lookup table.
+   */
+  private byte[] makeIdentityClut()
+  {
+    final int nIn = 3;
+    final int nOut = 3;
+    final int nInEntries = 256;
+    final int nOutEntries = 256;
+    final int gridpoints = 16;
+
+    // gridpoints**nIn
+    final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
+    final int totalSize = clutSize + 2 * nInEntries * nIn
+                          + 2 * nOutEntries * nOut + 52;
+
+    ByteBuffer buf = ByteBuffer.allocate(totalSize);
+    buf.putInt(0, 0x6D667432); // 'mft2'
+    buf.putInt(4, 0); // reserved
+    buf.put(8, (byte) nIn); // number input channels
+    buf.put(9, (byte) nOut); // number output channels
+    buf.put(10, (byte) gridpoints); // number gridpoints
+    buf.put(11, (byte) 0); // padding
+
+    // identity matrix
+    buf.putInt(12, 65536); // = 1 in s15.16 fixed point
+    buf.putInt(16, 0);
+    buf.putInt(20, 0);
+    buf.putInt(24, 0);
+    buf.putInt(28, 65536);
+    buf.putInt(32, 0);
+    buf.putInt(36, 0);
+    buf.putInt(40, 0);
+    buf.putInt(44, 65536);
+
+    buf.putShort(48, (short) nInEntries); // input table entries
+    buf.putShort(50, (short) nOutEntries); // output table entries
+
+    // write the linear input channels, unsigned 16.16 fixed point,
+    // from 0.0 to FF.FF
+    for (int channel = 0; channel < 3; channel++)
+      for (int i = 0; i < nInEntries; i++)
+        {
+	  short n = (short) ((i << 8) | i); // assumes 256 entries
+	  buf.putShort(52 + (channel * nInEntries + i) * 2, n);
+        }
+    int clutOffset = 52 + nInEntries * nIn * 2;
+
+    for (int x = 0; x < gridpoints; x++)
+      for (int y = 0; y < gridpoints; y++)
+	for (int z = 0; z < gridpoints; z++)
+	  {
+	    int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
+	                 + x * gridpoints * gridpoints * 2 * nOut;
+	    double xf = ((double) x) / ((double) gridpoints - 1.0);
+	    double yf = ((double) y) / ((double) gridpoints - 1.0);
+	    double zf = ((double) z) / ((double) gridpoints - 1.0);
+	    buf.putShort(offset, (short) (xf * 65535.0));
+	    buf.putShort(offset + 2, (short) (yf * 65535.0));
+	    buf.putShort(offset + 4, (short) (zf * 65535.0));
+	  }
+
+    for (int channel = 0; channel < 3; channel++)
+      for (int i = 0; i < nOutEntries; i++)
+        {
+	  short n = (short) ((i << 8) | i); // assumes 256 entries
+	  buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
+	               n);
+        }
+
+    return buf.array();
+  }
+
+  /**
+   * Creates profile data corresponding to the built-in colorspaces.
+   */
+  private void createProfile(int colorSpace) throws IllegalArgumentException
+  {
+    this.profileID = colorSpace;
+    header = new ProfileHeader();
+    tagTable = new Hashtable();
+
+    switch (colorSpace)
       {
       case ColorSpace.CS_sRGB:
+	createRGBProfile();
+	return;
       case ColorSpace.CS_LINEAR_RGB:
+	createLinearRGBProfile();
+	return;
       case ColorSpace.CS_CIEXYZ:
-	return 3;
+	createCIEProfile();
+	return;
       case ColorSpace.CS_GRAY:
-	return 1;
-      case ColorSpace.CS_PYCC: // have no clue about this one
+	createGrayProfile();
+	return;
+      case ColorSpace.CS_PYCC:
+	createPyccProfile();
+	return;
       default:
-	throw new UnsupportedOperationException("profile not implemented");
+	throw new IllegalArgumentException("Not a predefined color space!");
       }
   }
 
-  protected Object readResolve() throws ObjectStreamException
+  /**
+   * Creates an ICC_Profile representing the sRGB color space
+   */
+  private void createRGBProfile()
   {
-    throw new Error("not implemented");
+    header.setColorSpace( ColorSpace.TYPE_RGB );
+    header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
+    ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+    float[] r = { 1f, 0f, 0f };
+    float[] g = { 0f, 1f, 0f };
+    float[] b = { 0f, 0f, 1f };
+    float[] black = { 0f, 0f, 0f };
+
+    // CIE 1931 D50 white point (in Lab coordinates)
+    float[] white = D50;
+
+    // Get tristimulus values (matrix elements)
+    r = cs.toCIEXYZ(r);
+    g = cs.toCIEXYZ(g);
+    b = cs.toCIEXYZ(b);
+
+    // Generate the sRGB TRC curve, this is the linear->nonlinear
+    // RGB transform.
+    cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
+    float[] points = new float[TRC_POINTS];
+    float[] in = new float[3];
+    for (int i = 0; i < TRC_POINTS; i++)
+      {
+	in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
+	in = cs.fromRGB(in);
+	// Note this value is the same for all components.
+	points[i] = in[0];
+      }
+
+    setData(icSigRedColorantTag, makeXYZData(r));
+    setData(icSigGreenColorantTag, makeXYZData(g));
+    setData(icSigBlueColorantTag, makeXYZData(b));
+    setData(icSigMediaWhitePointTag, makeXYZData(white));
+    setData(icSigMediaBlackPointTag, makeXYZData(black));
+    setData(icSigRedTRCTag, makeTRC(points));
+    setData(icSigGreenTRCTag, makeTRC(points));
+    setData(icSigBlueTRCTag, makeTRC(points));
+    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+    setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
+    this.profileID = ColorSpace.CS_sRGB;
   }
 
-  private void readObject(ObjectInputStream s)
-    throws IOException, ClassNotFoundException
+  /**
+   * Creates an linear sRGB profile
+   */
+  private void createLinearRGBProfile()
   {
-    throw new Error("not implemented");
+    header.setColorSpace(ColorSpace.TYPE_RGB);
+    header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+    ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+    float[] r = { 1f, 0f, 0f };
+    float[] g = { 0f, 1f, 0f };
+    float[] b = { 0f, 0f, 1f };
+    float[] black = { 0f, 0f, 0f };
+
+    float[] white = D50;
+
+    // Get tristimulus values (matrix elements)
+    r = cs.toCIEXYZ(r);
+    g = cs.toCIEXYZ(g);
+    b = cs.toCIEXYZ(b);
+
+    setData(icSigRedColorantTag, makeXYZData(r));
+    setData(icSigGreenColorantTag, makeXYZData(g));
+    setData(icSigBlueColorantTag, makeXYZData(b));
+
+    setData(icSigMediaWhitePointTag, makeXYZData(white));
+    setData(icSigMediaBlackPointTag, makeXYZData(black));
+
+    setData(icSigRedTRCTag, makeTRC());
+    setData(icSigGreenTRCTag, makeTRC());
+    setData(icSigBlueTRCTag, makeTRC());
+    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+    setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
+    this.profileID = ColorSpace.CS_LINEAR_RGB;
   }
 
-  private void writeObject(ObjectOutputStream s) throws IOException
+  /**
+   * Creates an CIE XYZ identity profile
+   */
+  private void createCIEProfile()
+  {
+    header.setColorSpace( ColorSpace.TYPE_XYZ );
+    header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
+    header.setProfileClass( CLASS_COLORSPACECONVERSION );
+    ICC_ColorSpace cs = new ICC_ColorSpace(this);
+
+    float[] white = D50;
+
+    setData(icSigMediaWhitePointTag, makeXYZData(white));
+    setData(icSigAToB0Tag, makeIdentityClut());
+    setData(icSigBToA0Tag, makeIdentityClut());
+    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+    setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
+    this.profileID = ColorSpace.CS_CIEXYZ;
+  }
+
+  /**
+   * Creates a linear gray ICC_Profile
+   */
+  private void createGrayProfile()
+  {
+    header.setColorSpace(ColorSpace.TYPE_GRAY);
+    header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+
+    // CIE 1931 D50 white point (in Lab coordinates)
+    float[] white = D50;
+
+    setData(icSigMediaWhitePointTag, makeXYZData(white));
+    setData(icSigGrayTRCTag, makeTRC(1.0f));
+    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+    setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
+    this.profileID = ColorSpace.CS_GRAY;
+  }
+
+  /**
+   * XXX Implement me
+   */
+  private void createPyccProfile()
   {
-    throw new Error("not implemented");
+    header.setColorSpace(ColorSpace.TYPE_3CLR);
+    header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
+
+    // Create CLUTs here. :-)
+
+    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
+    setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
+    this.profileID = ColorSpace.CS_PYCC;
   }
 } // class ICC_Profile
Index: java/awt/color/ICC_ProfileGray.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/color/ICC_ProfileGray.java,v
retrieving revision 1.1
diff -u -r1.1 ICC_ProfileGray.java
--- java/awt/color/ICC_ProfileGray.java	10 Nov 2002 00:16:42 -0000	1.1
+++ java/awt/color/ICC_ProfileGray.java	6 Nov 2004 18:50:47 -0000
@@ -1,45 +1,60 @@
 /* ICC_ProfileGray.java -- the ICC profile for a Gray colorspace
    Copyright (C) 2002 Free Software Foundation, Inc.
 
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
+   This file is part of GNU Classpath.
 
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
 
 package java.awt.color;
 
+
 /**
- * STUBBED
+ * ICC_ProfileGray - a special case of ICC_Profiles.
+ *
+ * The ICC_Profile.getInstance() method will return an instance of the 
+ * ICC_ProfileGray subclass when all the following conditions are met:
+ * The device color space of the profile is TYPE_GRAY.
+ * The profile contains a gray TRCTag.
+ * The profile contains a mediaWhitePointTag.
+ *
+ * As per the ICC specification, the color space conversion can then
+ * be done through the following method:
+ * linearGray = grayTRC[deviceGray]
+ *
+ * Note that if the profile contains a CLUT for the color space conversion,
+ * it should be used instead, and the TRC information ignored. 
+ *
+ * @author Sven de Marothy
  * @since 1.2
  */
 public class ICC_ProfileGray extends ICC_Profile
@@ -48,24 +63,71 @@
    * Compatible with JDK 1.2+.
    */
   private static final long serialVersionUID = -1124721290732002649L;
+  private transient float[] whitePoint;
+
+  /**
+   * Package-private constructor used by ICC_ColorSpace for creating an
+   * ICC_ProfileRGB from a predefined ColorSpace (CS_GRAY)
+   */
+  ICC_ProfileGray(int cspace)
+  {
+    super(cspace);
+    whitePoint = getXYZData(icSigMediaWhitePointTag);
+  }
 
-  ICC_ProfileGray()
+  /**
+   * Package-private constructor used by ICC_ColorSpace for creating an
+   * ICC_ProfileGray from profile data.
+   */
+  ICC_ProfileGray(byte[] data)
   {
-    super(ColorSpace.CS_GRAY);
+    super(data);
+    whitePoint = getXYZData(icSigMediaWhitePointTag);
   }
 
+
+  /**
+   * Returns the media white point of the profile.
+   */
   public float[] getMediaWhitePoint()
   {
-    return null;
+    float[] wp = new float[3];
+    wp[0] = whitePoint[0];
+    wp[1] = whitePoint[1];
+    wp[2] = whitePoint[2];
+    return wp;
   }
 
+  /**
+   * Returns the TRC gamma value.
+   * @throws IllegalArgumentException if the TRC is described by a lookup
+   * table and not a gamma value.
+   */
   public float getGamma()
   {
-    return 0;
+    short[] data = getCurve(icSigGrayTRCTag);
+    if (data == null)
+      throw new IllegalArgumentException("Couldn't read Gray TRC data.");
+    if (data.length != 1)
+      throw new ProfileDataException("TRC is a table, not a gamma value.");
+
+    // convert the unsigned 7.8 fixed-point gamma to a float.
+    double gamma = (double) (data[0] & (0xFFFF)) / 256.0;
+    return (float) gamma;
   }
 
+  /**
+   * Returns the TRC lookup table.
+   * @throws IllegalArgumentException if the TRC is described by a gamma value
+   * and not a lookup table.
+   */
   public short[] getTRC()
   {
-    return null;
+    short[] data = getCurve(icSigGrayTRCTag);
+    if (data == null)
+      throw new IllegalArgumentException("Couldn't read Gray TRC data.");
+    if (data.length <= 1)
+      throw new ProfileDataException("Gamma value, not a TRC table.");
+    return data;
   }
 } // class ICC_ProfileGray
Index: java/awt/color/ICC_ProfileRGB.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/color/ICC_ProfileRGB.java,v
retrieving revision 1.1
diff -u -r1.1 ICC_ProfileRGB.java
--- java/awt/color/ICC_ProfileRGB.java	10 Nov 2002 00:16:42 -0000	1.1
+++ java/awt/color/ICC_ProfileRGB.java	6 Nov 2004 18:50:47 -0000
@@ -1,45 +1,74 @@
 /* ICC_ProfileRGB.java -- the ICC profile for a RGB colorspace
    Copyright (C) 2002 Free Software Foundation, Inc.
 
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
+   This file is part of GNU Classpath.
 
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
 
 package java.awt.color;
 
+import java.nio.ByteBuffer;
+
+
 /**
- * STUBBED
+ * ICC_ProfileRGB - a special case of ICC_Profiles.
+ *
+ * The ICC_Profile.getInstance() method will return an instance of the 
+ * ICC_ProfileRGB subclass when all the following conditions are met:
+ * The device color space of the profile is TYPE_RGB.
+ * The profile contains red, green and blue ColorantTags.
+ * The profile contains red, green and blue TRCTags.
+ * The profile contains a mediaWhitePointTag included.
+ *
+ * As per the ICC specification, the color space conversion can then
+ * be done through the following method:
+ * linearR = redTRC[deviceR]
+ * linearG = greenTRC[deviceG]
+ * linearB = blueTRC[deviceB]
+ * TRC curves are either a single gamma value, or a 1-dimensional lookup table.
+ * 
+ * Followed by the matrix transform:
+ * PCS = M*linear
+ *
+ * Where PCS is the vector of profile color space (must be XYZ) coordinates,
+ * linear is the vector of linear RGB coordinates, and the matrix M is 
+ * constructed from the ColorantTags, where the columns are red, green and
+ * blue respectively, and the rows are X, Y and Z.
+ *
+ * Note that if the profile contains a CLUT for the color space conversion,
+ * it should be used instead, and the TRC information ignored. 
+ *
+ * @author Sven de Marothy
  * @since 1.2
  */
 public class ICC_ProfileRGB extends ICC_Profile
@@ -50,31 +79,151 @@
   private static final long serialVersionUID = 8505067385152579334L;
 
   public static final int REDCOMPONENT = 0;
+
   public static final int GREENCOMPONENT = 1;
+
   public static final int BLUECOMPONENT = 2;
 
-  ICC_ProfileRGB()
+  private transient float[][] matrix;
+
+  private transient float[] gamma;
+
+  private transient float[] whitePoint;
+
+
+  /**
+   * Package-private constructor used by ICC_ColorSpace for creating an
+   * ICC_ProfileRGB from a predefined ColorSpace (CS_LINEAR_RGB and CS_sRGB)
+   */
+  ICC_ProfileRGB(int cspace)
+  {
+    super(cspace);
+    matrix = createMatrix();
+    whitePoint = getXYZData(icSigMediaWhitePointTag);
+  }
+
+  /**
+   * Package-private constructor used by ICC_ColorSpace for creating an
+   * ICC_ProfileRGB from profile data.
+   */
+  ICC_ProfileRGB(byte[] data)
   {
-    super(ColorSpace.CS_sRGB);
+    super(data);
+    matrix = createMatrix();
+    whitePoint = getXYZData(icSigMediaWhitePointTag);
   }
 
+  /**
+   * Returns the media white point of the profile.
+   */
   public float[] getMediaWhitePoint()
   {
-    return null;
+    float[] wp = new float[3];
+    wp[0] = whitePoint[0];
+    wp[1] = whitePoint[1];
+    wp[2] = whitePoint[2];
+    return wp;
   }
 
+  /**
+   * Returns the colorant matrix of the conversion.
+   */
   public float[][] getMatrix()
   {
-    return null;
+    float[][] mat = new float[3][3];
+    for (int i = 0; i < 3; i++)
+      for (int j = 0; j < 3; j++)
+	mat[i][j] = matrix[i][j];
+    return mat;
   }
 
+  /**
+   * Returns the gamma value of a component
+   * @throws IllegalArgumentException if the TRC is described by a lookup
+   * table and not a gamma value.
+   */
   public float getGamma(int component)
   {
-    return 0;
+    short[] data;
+    switch (component)
+      {
+      case REDCOMPONENT:
+	data = getCurve(icSigRedTRCTag);
+	break;
+      case GREENCOMPONENT:
+	data = getCurve(icSigGreenTRCTag);
+	break;
+      case BLUECOMPONENT:
+	data = getCurve(icSigBlueTRCTag);
+	break;
+      default:
+	throw new IllegalArgumentException("Not a valid component");
+      }
+    if (data == null)
+      throw new IllegalArgumentException("Error reading TRC");
+
+    if (data.length != 1)
+      throw new ProfileDataException("Not a single-gamma TRC");
+
+    // convert the unsigned 7.8 fixed-point gamma to a float.
+    float gamma = (float) (((int) data[0] & 0xFF00) >> 8);
+    double fraction = ((int) data[0] & 0x00FF) / 256.0;
+    gamma += (float) fraction;
+    return gamma;
   }
 
+  /**
+   * Returns the TRC lookup table for a component
+   * @throws IllegalArgumentException if the TRC is described by a gamma
+   * value and not a lookup table.
+   */
   public short[] getTRC(int component)
   {
-    return null;
+    short[] data;
+    switch (component)
+      {
+      case REDCOMPONENT:
+	data = getCurve(icSigRedTRCTag);
+	break;
+      case GREENCOMPONENT:
+	data = getCurve(icSigGreenTRCTag);
+	break;
+      case BLUECOMPONENT:
+	data = getCurve(icSigBlueTRCTag);
+	break;
+      default:
+	throw new IllegalArgumentException("Not a valid component");
+      }
+    if (data == null)
+      throw new IllegalArgumentException("Error reading TRC");
+
+    if (data.length <= 1)
+      throw new ProfileDataException("Gamma value, not a TRC table.");
+
+    return data;
+  }
+
+  /**
+   * Creates the colorspace conversion matrix from the RGB tristimulus
+   * values.
+   */
+  private float[][] createMatrix() throws IllegalArgumentException
+  {
+    float[][] mat = new float[3][3];
+    float[] r;
+    float[] g;
+    float[] b;
+    r = getXYZData(icSigRedColorantTag);
+    g = getXYZData(icSigGreenColorantTag);
+    b = getXYZData(icSigBlueColorantTag);
+    if (r == null || g == null || b == null)
+      throw new IllegalArgumentException("Error reading colorant tags!");
+    for (int i = 0; i < 3; i++)
+      {
+	mat[i][0] = r[i];
+	mat[i][1] = g[i];
+	mat[i][2] = b[i];
+      }
+    return mat;
   }
 } // class ICC_ProfileRGB

Attachment: signature.asc
Description: This is a digitally signed message part


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]