Source for java.awt.color.ICC_ColorSpace

   1: /* ICC_ColorSpace.java -- the canonical color space implementation
   2:    Copyright (C) 2000, 2002, 2004 Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt.color;
  40: 
  41: import gnu.java.awt.color.CieXyzConverter;
  42: import gnu.java.awt.color.ClutProfileConverter;
  43: import gnu.java.awt.color.ColorSpaceConverter;
  44: import gnu.java.awt.color.GrayProfileConverter;
  45: import gnu.java.awt.color.GrayScaleConverter;
  46: import gnu.java.awt.color.LinearRGBConverter;
  47: import gnu.java.awt.color.PyccConverter;
  48: import gnu.java.awt.color.RgbProfileConverter;
  49: import gnu.java.awt.color.SrgbConverter;
  50: 
  51: import java.io.IOException;
  52: import java.io.ObjectInputStream;
  53: 
  54: /**
  55:  * ICC_ColorSpace - an implementation of ColorSpace
  56:  *
  57:  * While an ICC_Profile class abstracts the data in an ICC profile file
  58:  * an ICC_ColorSpace performs the color space conversions defined by
  59:  * an ICC_Profile instance.
  60:  *
  61:  * Typically, an ICC_Profile will either be created using getInstance,
  62:  * either from the built-in colorspaces, or from an ICC profile file.
  63:  * Then a ICC_Colorspace will be used to perform transforms from the
  64:  * device colorspace to and from the profile color space.
  65:  *
  66:  * The PCS used by ColorSpace is CIE XYZ relative a D50 white point.
  67:  * (Profiles using a CIE Lab PCS will have their input and output converted
  68:  * to D50 CIE XYZ accordingly.
  69:  *
  70:  * Note that a valid profile may not contain transforms in both directions,
  71:  * in which case the output may be undefined.
  72:  * All built-in colorspaces have bidirectional transforms, but developers
  73:  * using an ICC profile file may want to check the profile class using
  74:  * the ICC_Profile.getProfileClass() method. Input class profiles are
  75:  * guaranteed to have transforms to the PCS, output class profiles are
  76:  * guaranteed to have transforms from the PCS to device space.
  77:  *
  78:  * @author Sven de Marothy
  79:  * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
  80:  * @since 1.2
  81:  */
  82: public class ICC_ColorSpace extends ColorSpace
  83: {
  84:   /**
  85:    * Compatible with JDK 1.2+.
  86:    */
  87:   private static final long serialVersionUID = 3455889114070431483L;
  88: 
  89:   /**
  90:    * @serial
  91:    */
  92:   private ICC_Profile thisProfile;
  93: 
  94:   /**
  95:    * @serial
  96:    */
  97:   private float[] minVal;
  98: 
  99:   /**
 100:    * @serial
 101:    */
 102:   private float[] maxVal;
 103: 
 104:   /**
 105:    * @serial
 106:    */
 107:   private float[] diffMinMax;
 108: 
 109:   /**
 110:    * @serial
 111:    */
 112:   private float[] invDiffMinMax;
 113: 
 114:   /**
 115:    * @serial
 116:    */
 117:   private boolean needScaleInit;
 118: 
 119:   /**
 120:    * Tells us if the PCS is CIE LAB (must be CIEXYZ otherwise)
 121:    */
 122:   private transient int type;
 123:   private transient int nComponents;
 124:   private transient ColorSpaceConverter converter;
 125: 
 126:   /**
 127:    * Constructs a new ICC_ColorSpace from an ICC_Profile object.
 128:    *
 129:    * @exception IllegalArgumentException If profile is inappropriate for
 130:    * representing a ColorSpace.
 131:    */
 132:   public ICC_ColorSpace(ICC_Profile profile)
 133:   {
 134:     super(profile.getColorSpaceType(), profile.getNumComponents());
 135: 
 136:     converter = getConverter(profile);
 137:     thisProfile = profile;
 138:     nComponents = profile.getNumComponents();
 139:     type = profile.getColorSpaceType();
 140:     makeArrays();
 141:   }
 142: 
 143:   /**
 144:    * Return the profile
 145:    */
 146:   public ICC_Profile getProfile()
 147:   {
 148:     return thisProfile;
 149:   }
 150: 
 151:   /**
 152:    * Transforms a color value assumed to be in this ColorSpace into a value in
 153:    * the default CS_sRGB color space.
 154:    *
 155:    * @exception ArrayIndexOutOfBoundsException If array length is not at least
 156:    * the number of components in this ColorSpace.
 157:    */
 158:   public float[] toRGB(float[] colorvalue)
 159:   {
 160:     return converter.toRGB(colorvalue);
 161:   }
 162: 
 163:   /**
 164:    * Transforms a color value assumed to be in the default CS_sRGB color space
 165:    * into this ColorSpace.
 166:    *
 167:    * @exception ArrayIndexOutOfBoundsException If array length is not at
 168:    * least 3.
 169:    */
 170:   public float[] fromRGB(float[] rgbvalue)
 171:   {
 172:     return converter.fromRGB(rgbvalue);
 173:   }
 174: 
 175:   /**
 176:    * Transforms a color value assumed to be in this ColorSpace into the
 177:    * CS_CIEXYZ conversion color space.
 178:    *
 179:    * @exception ArrayIndexOutOfBoundsException If array length is not at
 180:    * least the number of components in this ColorSpace.
 181:    */
 182:   public float[] toCIEXYZ(float[] colorvalue)
 183:   {
 184:     return converter.toCIEXYZ(colorvalue);
 185:   }
 186: 
 187:   /**
 188:    * Transforms a color value assumed to be in the CS_CIEXYZ conversion color
 189:    * space into this ColorSpace.
 190:    *
 191:    * @exception ArrayIndexOutOfBoundsException If array length is not at
 192:    * least 3.
 193:    */
 194:   public float[] fromCIEXYZ(float[] colorvalue)
 195:   {
 196:     return converter.fromCIEXYZ(colorvalue);
 197:   }
 198: 
 199:   public boolean isCS_sRGB()
 200:   {
 201:     return converter instanceof SrgbConverter;
 202:   }
 203: 
 204:   /**
 205:    * Returns the minimum normalized color component value for the specified
 206:    * component.
 207:    *
 208:    * @exception IllegalArgumentException If component is less than 0 or greater
 209:    * than numComponents - 1.
 210:    *
 211:    * @since 1.4
 212:    */
 213:   public float getMinValue(int idx)
 214:   {
 215:     // FIXME: Not 100% certain of this. 
 216:     if (type == ColorSpace.TYPE_Lab && (idx == 1 || idx == 2))
 217:       return -128f;
 218: 
 219:     if (idx < 0 || idx >= nComponents)
 220:       throw new IllegalArgumentException();
 221:     return 0;
 222:   }
 223: 
 224:   /**
 225:    * Returns the maximum normalized color component value for the specified
 226:    * component.
 227:    *
 228:    * @exception IllegalArgumentException If component is less than 0 or greater
 229:    * than numComponents - 1.
 230:    *
 231:    * @since 1.4
 232:    */
 233:   public float getMaxValue(int idx)
 234:   {
 235:     if (type == ColorSpace.TYPE_XYZ && idx >= 0 && idx <= 2)
 236:       return 1 + 32767 / 32768f;
 237:     else if (type == ColorSpace.TYPE_Lab)
 238:       {
 239:     if (idx == 0)
 240:       return 100;
 241:     if (idx == 1 || idx == 2)
 242:       return 127;
 243:       }
 244:     if (idx < 0 || idx >= nComponents)
 245:       throw new IllegalArgumentException();
 246:     return 1;
 247:   }
 248: 
 249:   /**
 250:    * Returns a colorspace converter suitable for a given profile
 251:    */
 252:   private ColorSpaceConverter getConverter(ICC_Profile profile)
 253:   {
 254:     ColorSpaceConverter converter;
 255:     switch (profile.isPredefined())
 256:       {
 257:       case CS_sRGB:
 258:     converter = new SrgbConverter();
 259:     break;
 260:       case CS_CIEXYZ:
 261:     converter = new CieXyzConverter();
 262:     break;
 263:       case CS_GRAY:
 264:     converter = new GrayScaleConverter();
 265:     break;
 266:       case CS_LINEAR_RGB:
 267:     converter = new LinearRGBConverter();
 268:     break;
 269:       case CS_PYCC:
 270:     converter = new PyccConverter();
 271:     break;
 272:       default:
 273:     if (profile instanceof ICC_ProfileRGB)
 274:       converter = new RgbProfileConverter((ICC_ProfileRGB) profile);
 275:     else if (profile instanceof ICC_ProfileGray)
 276:       converter = new GrayProfileConverter((ICC_ProfileGray) profile);
 277:     else
 278:       converter = new ClutProfileConverter(profile);
 279:     break;
 280:       }
 281:     return converter;
 282:   }
 283: 
 284:   /**
 285:    * Serialization compatibility requires these variable to be set,
 286:    * although we don't use them. Perhaps we should?
 287:    */
 288:   private void makeArrays()
 289:   {
 290:     minVal = new float[nComponents];
 291:     maxVal = new float[nComponents];
 292: 
 293:     invDiffMinMax = diffMinMax = null;
 294:     for (int i = 0; i < nComponents; i++)
 295:       {
 296:     minVal[i] = getMinValue(i);
 297:     maxVal[i] = getMaxValue(i);
 298:       }
 299:     needScaleInit = true;
 300:   }
 301: 
 302:   /**
 303:    * Deserializes the object
 304:    */
 305:   private void readObject(ObjectInputStream s)
 306:                    throws IOException, ClassNotFoundException
 307:   {
 308:     s.defaultReadObject();
 309:     // set up objects
 310:     converter = getConverter(thisProfile);
 311:     nComponents = thisProfile.getNumComponents();
 312:     type = thisProfile.getColorSpaceType();
 313:   }
 314: } // class ICC_ColorSpace