001 /* ICC_ColorSpace.java -- the canonical color space implementation 002 Copyright (C) 2000, 2002, 2004 Free Software Foundation 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package java.awt.color; 040 041 import gnu.java.awt.color.CieXyzConverter; 042 import gnu.java.awt.color.ClutProfileConverter; 043 import gnu.java.awt.color.ColorSpaceConverter; 044 import gnu.java.awt.color.GrayProfileConverter; 045 import gnu.java.awt.color.GrayScaleConverter; 046 import gnu.java.awt.color.LinearRGBConverter; 047 import gnu.java.awt.color.PyccConverter; 048 import gnu.java.awt.color.RgbProfileConverter; 049 import gnu.java.awt.color.SrgbConverter; 050 051 import java.io.IOException; 052 import java.io.ObjectInputStream; 053 054 /** 055 * ICC_ColorSpace - an implementation of ColorSpace 056 * 057 * While an ICC_Profile class abstracts the data in an ICC profile file 058 * an ICC_ColorSpace performs the color space conversions defined by 059 * an ICC_Profile instance. 060 * 061 * Typically, an ICC_Profile will either be created using getInstance, 062 * either from the built-in colorspaces, or from an ICC profile file. 063 * Then a ICC_Colorspace will be used to perform transforms from the 064 * device colorspace to and from the profile color space. 065 * 066 * The PCS used by ColorSpace is CIE XYZ relative a D50 white point. 067 * (Profiles using a CIE Lab PCS will have their input and output converted 068 * to D50 CIE XYZ accordingly. 069 * 070 * Note that a valid profile may not contain transforms in both directions, 071 * in which case the output may be undefined. 072 * All built-in colorspaces have bidirectional transforms, but developers 073 * using an ICC profile file may want to check the profile class using 074 * the ICC_Profile.getProfileClass() method. Input class profiles are 075 * guaranteed to have transforms to the PCS, output class profiles are 076 * guaranteed to have transforms from the PCS to device space. 077 * 078 * @author Sven de Marothy 079 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no) 080 * @since 1.2 081 */ 082 public class ICC_ColorSpace extends ColorSpace 083 { 084 /** 085 * Compatible with JDK 1.2+. 086 */ 087 private static final long serialVersionUID = 3455889114070431483L; 088 089 /** 090 * @serial 091 */ 092 private ICC_Profile thisProfile; 093 094 /** 095 * @serial 096 */ 097 private float[] minVal; 098 099 /** 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