Frames | No Frames |
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