1 /* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 ********************************************************************** 28 ********************************************************************** 29 ********************************************************************** 30 *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** 31 *** As an unpublished work pursuant to Title 17 of the United *** 32 *** States Code. All rights reserved. *** 33 ********************************************************************** 34 ********************************************************************** 35 **********************************************************************/ 36 37 package java.awt.color; 38 39 import sun.java2d.cmm.ColorTransform; 40 import sun.java2d.cmm.CMSManager; 41 import sun.java2d.cmm.PCMM; 42 43 44 /** 45 * 46 * The ICC_ColorSpace class is an implementation of the abstract 47 * ColorSpace class. This representation of 48 * device independent and device dependent color spaces is based on the 49 * International Color Consortium Specification ICC.1:2001-12, File Format for 50 * Color Profiles (see <A href="http://www.color.org">http://www.color.org</A>). 51 * <p> 52 * Typically, a Color or ColorModel would be associated with an ICC 53 * Profile which is either an input, display, or output profile (see 54 * the ICC specification). There are other types of ICC Profiles, e.g. 55 * abstract profiles, device link profiles, and named color profiles, 56 * which do not contain information appropriate for representing the color 57 * space of a color, image, or device (see ICC_Profile). 58 * Attempting to create an ICC_ColorSpace object from an inappropriate ICC 59 * Profile is an error. 60 * <p> 61 * ICC Profiles represent transformations from the color space of 62 * the profile (e.g. a monitor) to a Profile Connection Space (PCS). 63 * Profiles of interest for tagging images or colors have a 64 * PCS which is one of the device independent 65 * spaces (one CIEXYZ space and two CIELab spaces) defined in the 66 * ICC Profile Format Specification. Most profiles of interest 67 * either have invertible transformations or explicitly specify 68 * transformations going both directions. Should an ICC_ColorSpace 69 * object be used in a way requiring a conversion from PCS to 70 * the profile's native space and there is inadequate data to 71 * correctly perform the conversion, the ICC_ColorSpace object will 72 * produce output in the specified type of color space (e.g. TYPE_RGB, 73 * TYPE_CMYK, etc.), but the specific color values of the output data 74 * will be undefined. 75 * <p> 76 * The details of this class are not important for simple applets, 77 * which draw in a default color space or manipulate and display 78 * imported images with a known color space. At most, such applets 79 * would need to get one of the default color spaces via 80 * ColorSpace.getInstance(). 81 * @see ColorSpace 82 * @see ICC_Profile 83 */ 84 85 86 87 public class ICC_ColorSpace extends ColorSpace { 88 89 static final long serialVersionUID = 3455889114070431483L; 90 91 private ICC_Profile thisProfile; 92 private float[] minVal; 93 private float[] maxVal; 94 private float[] diffMinMax; 95 private float[] invDiffMinMax; 96 private boolean needScaleInit = true; 97 98 // {to,from}{RGB,CIEXYZ} methods create and cache these when needed 99 private transient ColorTransform this2srgb; 100 private transient ColorTransform srgb2this; 101 private transient ColorTransform this2xyz; 102 private transient ColorTransform xyz2this; 103 104 105 /** 106 * Constructs a new ICC_ColorSpace from an ICC_Profile object. 107 * @param profile the specified ICC_Profile object 108 * @exception IllegalArgumentException if profile is inappropriate for 109 * representing a ColorSpace. 110 */ 111 public ICC_ColorSpace (ICC_Profile profile) { 112 super (profile.getColorSpaceType(), profile.getNumComponents()); 113 114 int profileClass = profile.getProfileClass(); 115 116 /* REMIND - is NAMEDCOLOR OK? */ 117 if ((profileClass != ICC_Profile.CLASS_INPUT) && 118 (profileClass != ICC_Profile.CLASS_DISPLAY) && 119 (profileClass != ICC_Profile.CLASS_OUTPUT) && 120 (profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) && 121 (profileClass != ICC_Profile.CLASS_NAMEDCOLOR) && 122 (profileClass != ICC_Profile.CLASS_ABSTRACT)) { 123 throw new IllegalArgumentException("Invalid profile type"); 124 } 125 126 thisProfile = profile; 127 setMinMax(); 128 } 129 130 /** 131 * Validate an ICC_ColorSpace read from an object input stream 132 */ 133 private void readObject(java.io.ObjectInputStream s) 134 throws ClassNotFoundException, java.io.IOException { 135 136 s.defaultReadObject(); 137 if (thisProfile == null) { 138 thisProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB); 139 } 140 } 141 142 /** 143 * Returns the ICC_Profile for this ICC_ColorSpace. 144 * @return the ICC_Profile for this ICC_ColorSpace. 145 */ 146 public ICC_Profile getProfile() { 147 return thisProfile; 148 } 149 150 /** 151 * Transforms a color value assumed to be in this ColorSpace 152 * into a value in the default CS_sRGB color space. 153 * <p> 154 * This method transforms color values using algorithms designed 155 * to produce the best perceptual match between input and output 156 * colors. In order to do colorimetric conversion of color values, 157 * you should use the {@code toCIEXYZ} 158 * method of this color space to first convert from the input 159 * color space to the CS_CIEXYZ color space, and then use the 160 * {@code fromCIEXYZ} method of the CS_sRGB color space to 161 * convert from CS_CIEXYZ to the output color space. 162 * See {@link #toCIEXYZ(float[]) toCIEXYZ} and 163 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 164 * 165 * @param colorvalue a float array with length of at least the number 166 * of components in this ColorSpace. 167 * @return a float array of length 3. 168 * @throws ArrayIndexOutOfBoundsException if array length is not 169 * at least the number of components in this ColorSpace. 170 */ 171 public float[] toRGB (float[] colorvalue) { 172 173 if (this2srgb == null) { 174 ColorTransform[] transformList = new ColorTransform [2]; 175 ICC_ColorSpace srgbCS = 176 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB); 177 PCMM mdl = CMSManager.getModule(); 178 transformList[0] = mdl.createTransform( 179 thisProfile, ColorTransform.Any, ColorTransform.In); 180 transformList[1] = mdl.createTransform( 181 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 182 this2srgb = mdl.createTransform(transformList); 183 if (needScaleInit) { 184 setComponentScaling(); 185 } 186 } 187 188 int nc = this.getNumComponents(); 189 short tmp[] = new short[nc]; 190 for (int i = 0; i < nc; i++) { 191 tmp[i] = (short) 192 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f); 193 } 194 tmp = this2srgb.colorConvert(tmp, null); 195 float[] result = new float [3]; 196 for (int i = 0; i < 3; i++) { 197 result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f; 198 } 199 return result; 200 } 201 202 /** 203 * Transforms a color value assumed to be in the default CS_sRGB 204 * color space into this ColorSpace. 205 * <p> 206 * This method transforms color values using algorithms designed 207 * to produce the best perceptual match between input and output 208 * colors. In order to do colorimetric conversion of color values, 209 * you should use the {@code toCIEXYZ} 210 * method of the CS_sRGB color space to first convert from the input 211 * color space to the CS_CIEXYZ color space, and then use the 212 * {@code fromCIEXYZ} method of this color space to 213 * convert from CS_CIEXYZ to the output color space. 214 * See {@link #toCIEXYZ(float[]) toCIEXYZ} and 215 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 216 * 217 * @param rgbvalue a float array with length of at least 3. 218 * @return a float array with length equal to the number of 219 * components in this ColorSpace. 220 * @throws ArrayIndexOutOfBoundsException if array length is not 221 * at least 3. 222 */ 223 public float[] fromRGB(float[] rgbvalue) { 224 225 if (srgb2this == null) { 226 ColorTransform[] transformList = new ColorTransform [2]; 227 ICC_ColorSpace srgbCS = 228 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB); 229 PCMM mdl = CMSManager.getModule(); 230 transformList[0] = mdl.createTransform( 231 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In); 232 transformList[1] = mdl.createTransform( 233 thisProfile, ColorTransform.Any, ColorTransform.Out); 234 srgb2this = mdl.createTransform(transformList); 235 if (needScaleInit) { 236 setComponentScaling(); 237 } 238 } 239 240 short tmp[] = new short[3]; 241 for (int i = 0; i < 3; i++) { 242 tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f); 243 } 244 tmp = srgb2this.colorConvert(tmp, null); 245 int nc = this.getNumComponents(); 246 float[] result = new float [nc]; 247 for (int i = 0; i < nc; i++) { 248 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * 249 diffMinMax[i] + minVal[i]; 250 } 251 return result; 252 } 253 254 255 /** 256 * Transforms a color value assumed to be in this ColorSpace 257 * into the CS_CIEXYZ conversion color space. 258 * <p> 259 * This method transforms color values using relative colorimetry, 260 * as defined by the ICC Specification. This 261 * means that the XYZ values returned by this method are represented 262 * relative to the D50 white point of the CS_CIEXYZ color space. 263 * This representation is useful in a two-step color conversion 264 * process in which colors are transformed from an input color 265 * space to CS_CIEXYZ and then to an output color space. This 266 * representation is not the same as the XYZ values that would 267 * be measured from the given color value by a colorimeter. 268 * A further transformation is necessary to compute the XYZ values 269 * that would be measured using current CIE recommended practices. 270 * The paragraphs below explain this in more detail. 271 * <p> 272 * The ICC standard uses a device independent color space (DICS) as the 273 * mechanism for converting color from one device to another device. In 274 * this architecture, colors are converted from the source device's color 275 * space to the ICC DICS and then from the ICC DICS to the destination 276 * device's color space. The ICC standard defines device profiles which 277 * contain transforms which will convert between a device's color space 278 * and the ICC DICS. The overall conversion of colors from a source 279 * device to colors of a destination device is done by connecting the 280 * device-to-DICS transform of the profile for the source device to the 281 * DICS-to-device transform of the profile for the destination device. 282 * For this reason, the ICC DICS is commonly referred to as the profile 283 * connection space (PCS). The color space used in the methods 284 * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC 285 * Specification. This is also the color space represented by 286 * ColorSpace.CS_CIEXYZ. 287 * <p> 288 * The XYZ values of a color are often represented as relative to some 289 * white point, so the actual meaning of the XYZ values cannot be known 290 * without knowing the white point of those values. This is known as 291 * relative colorimetry. The PCS uses a white point of D50, so the XYZ 292 * values of the PCS are relative to D50. For example, white in the PCS 293 * will have the XYZ values of D50, which is defined to be X=.9642, 294 * Y=1.000, and Z=0.8249. This white point is commonly used for graphic 295 * arts applications, but others are often used in other applications. 296 * <p> 297 * To quantify the color characteristics of a device such as a printer 298 * or monitor, measurements of XYZ values for particular device colors 299 * are typically made. For purposes of this discussion, the term 300 * device XYZ values is used to mean the XYZ values that would be 301 * measured from device colors using current CIE recommended practices. 302 * <p> 303 * Converting between device XYZ values and the PCS XYZ values returned 304 * by this method corresponds to converting between the device's color 305 * space, as represented by CIE colorimetric values, and the PCS. There 306 * are many factors involved in this process, some of which are quite 307 * subtle. The most important, however, is the adjustment made to account 308 * for differences between the device's white point and the white point of 309 * the PCS. There are many techniques for doing this and it is the 310 * subject of much current research and controversy. Some commonly used 311 * methods are XYZ scaling, the von Kries transform, and the Bradford 312 * transform. The proper method to use depends upon each particular 313 * application. 314 * <p> 315 * The simplest method is XYZ scaling. In this method each device XYZ 316 * value is converted to a PCS XYZ value by multiplying it by the ratio 317 * of the PCS white point (D50) to the device white point. 318 * <pre> 319 * 320 * Xd, Yd, Zd are the device XYZ values 321 * Xdw, Ydw, Zdw are the device XYZ white point values 322 * Xp, Yp, Zp are the PCS XYZ values 323 * Xd50, Yd50, Zd50 are the PCS XYZ white point values 324 * 325 * Xp = Xd * (Xd50 / Xdw) 326 * Yp = Yd * (Yd50 / Ydw) 327 * Zp = Zd * (Zd50 / Zdw) 328 * 329 * </pre> 330 * <p> 331 * Conversion from the PCS to the device would be done by inverting these 332 * equations: 333 * <pre> 334 * 335 * Xd = Xp * (Xdw / Xd50) 336 * Yd = Yp * (Ydw / Yd50) 337 * Zd = Zp * (Zdw / Zd50) 338 * 339 * </pre> 340 * <p> 341 * Note that the media white point tag in an ICC profile is not the same 342 * as the device white point. The media white point tag is expressed in 343 * PCS values and is used to represent the difference between the XYZ of 344 * device illuminant and the XYZ of the device media when measured under 345 * that illuminant. The device white point is expressed as the device 346 * XYZ values corresponding to white displayed on the device. For 347 * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device 348 * will result in a measured device XYZ value of D65. This will not 349 * be the same as the media white point tag XYZ value in the ICC 350 * profile for an sRGB device. 351 * 352 * @param colorvalue a float array with length of at least the number 353 * of components in this ColorSpace. 354 * @return a float array of length 3. 355 * @throws ArrayIndexOutOfBoundsException if array length is not 356 * at least the number of components in this ColorSpace. 357 */ 358 public float[] toCIEXYZ(float[] colorvalue) { 359 360 if (this2xyz == null) { 361 ColorTransform[] transformList = new ColorTransform [2]; 362 ICC_ColorSpace xyzCS = 363 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ); 364 PCMM mdl = CMSManager.getModule(); 365 try { 366 transformList[0] = mdl.createTransform( 367 thisProfile, ICC_Profile.icRelativeColorimetric, 368 ColorTransform.In); 369 } catch (CMMException e) { 370 transformList[0] = mdl.createTransform( 371 thisProfile, ColorTransform.Any, ColorTransform.In); 372 } 373 transformList[1] = mdl.createTransform( 374 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 375 this2xyz = mdl.createTransform (transformList); 376 if (needScaleInit) { 377 setComponentScaling(); 378 } 379 } 380 381 int nc = this.getNumComponents(); 382 short tmp[] = new short[nc]; 383 for (int i = 0; i < nc; i++) { 384 tmp[i] = (short) 385 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f); 386 } 387 tmp = this2xyz.colorConvert(tmp, null); 388 float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f); 389 // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components 390 float[] result = new float [3]; 391 for (int i = 0; i < 3; i++) { 392 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO; 393 } 394 return result; 395 } 396 397 398 /** 399 * Transforms a color value assumed to be in the CS_CIEXYZ conversion 400 * color space into this ColorSpace. 401 * <p> 402 * This method transforms color values using relative colorimetry, 403 * as defined by the ICC Specification. This 404 * means that the XYZ argument values taken by this method are represented 405 * relative to the D50 white point of the CS_CIEXYZ color space. 406 * This representation is useful in a two-step color conversion 407 * process in which colors are transformed from an input color 408 * space to CS_CIEXYZ and then to an output color space. The color 409 * values returned by this method are not those that would produce 410 * the XYZ value passed to the method when measured by a colorimeter. 411 * If you have XYZ values corresponding to measurements made using 412 * current CIE recommended practices, they must be converted to D50 413 * relative values before being passed to this method. 414 * The paragraphs below explain this in more detail. 415 * <p> 416 * The ICC standard uses a device independent color space (DICS) as the 417 * mechanism for converting color from one device to another device. In 418 * this architecture, colors are converted from the source device's color 419 * space to the ICC DICS and then from the ICC DICS to the destination 420 * device's color space. The ICC standard defines device profiles which 421 * contain transforms which will convert between a device's color space 422 * and the ICC DICS. The overall conversion of colors from a source 423 * device to colors of a destination device is done by connecting the 424 * device-to-DICS transform of the profile for the source device to the 425 * DICS-to-device transform of the profile for the destination device. 426 * For this reason, the ICC DICS is commonly referred to as the profile 427 * connection space (PCS). The color space used in the methods 428 * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC 429 * Specification. This is also the color space represented by 430 * ColorSpace.CS_CIEXYZ. 431 * <p> 432 * The XYZ values of a color are often represented as relative to some 433 * white point, so the actual meaning of the XYZ values cannot be known 434 * without knowing the white point of those values. This is known as 435 * relative colorimetry. The PCS uses a white point of D50, so the XYZ 436 * values of the PCS are relative to D50. For example, white in the PCS 437 * will have the XYZ values of D50, which is defined to be X=.9642, 438 * Y=1.000, and Z=0.8249. This white point is commonly used for graphic 439 * arts applications, but others are often used in other applications. 440 * <p> 441 * To quantify the color characteristics of a device such as a printer 442 * or monitor, measurements of XYZ values for particular device colors 443 * are typically made. For purposes of this discussion, the term 444 * device XYZ values is used to mean the XYZ values that would be 445 * measured from device colors using current CIE recommended practices. 446 * <p> 447 * Converting between device XYZ values and the PCS XYZ values taken as 448 * arguments by this method corresponds to converting between the device's 449 * color space, as represented by CIE colorimetric values, and the PCS. 450 * There are many factors involved in this process, some of which are quite 451 * subtle. The most important, however, is the adjustment made to account 452 * for differences between the device's white point and the white point of 453 * the PCS. There are many techniques for doing this and it is the 454 * subject of much current research and controversy. Some commonly used 455 * methods are XYZ scaling, the von Kries transform, and the Bradford 456 * transform. The proper method to use depends upon each particular 457 * application. 458 * <p> 459 * The simplest method is XYZ scaling. In this method each device XYZ 460 * value is converted to a PCS XYZ value by multiplying it by the ratio 461 * of the PCS white point (D50) to the device white point. 462 * <pre> 463 * 464 * Xd, Yd, Zd are the device XYZ values 465 * Xdw, Ydw, Zdw are the device XYZ white point values 466 * Xp, Yp, Zp are the PCS XYZ values 467 * Xd50, Yd50, Zd50 are the PCS XYZ white point values 468 * 469 * Xp = Xd * (Xd50 / Xdw) 470 * Yp = Yd * (Yd50 / Ydw) 471 * Zp = Zd * (Zd50 / Zdw) 472 * 473 * </pre> 474 * <p> 475 * Conversion from the PCS to the device would be done by inverting these 476 * equations: 477 * <pre> 478 * 479 * Xd = Xp * (Xdw / Xd50) 480 * Yd = Yp * (Ydw / Yd50) 481 * Zd = Zp * (Zdw / Zd50) 482 * 483 * </pre> 484 * <p> 485 * Note that the media white point tag in an ICC profile is not the same 486 * as the device white point. The media white point tag is expressed in 487 * PCS values and is used to represent the difference between the XYZ of 488 * device illuminant and the XYZ of the device media when measured under 489 * that illuminant. The device white point is expressed as the device 490 * XYZ values corresponding to white displayed on the device. For 491 * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device 492 * will result in a measured device XYZ value of D65. This will not 493 * be the same as the media white point tag XYZ value in the ICC 494 * profile for an sRGB device. 495 * 496 * @param colorvalue a float array with length of at least 3. 497 * @return a float array with length equal to the number of 498 * components in this ColorSpace. 499 * @throws ArrayIndexOutOfBoundsException if array length is not 500 * at least 3. 501 */ 502 public float[] fromCIEXYZ(float[] colorvalue) { 503 504 if (xyz2this == null) { 505 ColorTransform[] transformList = new ColorTransform [2]; 506 ICC_ColorSpace xyzCS = 507 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ); 508 PCMM mdl = CMSManager.getModule(); 509 transformList[0] = mdl.createTransform ( 510 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In); 511 try { 512 transformList[1] = mdl.createTransform( 513 thisProfile, ICC_Profile.icRelativeColorimetric, 514 ColorTransform.Out); 515 } catch (CMMException e) { 516 transformList[1] = CMSManager.getModule().createTransform( 517 thisProfile, ColorTransform.Any, ColorTransform.Out); 518 } 519 xyz2this = mdl.createTransform(transformList); 520 if (needScaleInit) { 521 setComponentScaling(); 522 } 523 } 524 525 short tmp[] = new short[3]; 526 float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f); 527 float factor = 65535.0f / ALMOST_TWO; 528 // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components 529 for (int i = 0; i < 3; i++) { 530 tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f); 531 } 532 tmp = xyz2this.colorConvert(tmp, null); 533 int nc = this.getNumComponents(); 534 float[] result = new float [nc]; 535 for (int i = 0; i < nc; i++) { 536 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * 537 diffMinMax[i] + minVal[i]; 538 } 539 return result; 540 } 541 542 /** 543 * Returns the minimum normalized color component value for the 544 * specified component. For TYPE_XYZ spaces, this method returns 545 * minimum values of 0.0 for all components. For TYPE_Lab spaces, 546 * this method returns 0.0 for L and -128.0 for a and b components. 547 * This is consistent with the encoding of the XYZ and Lab Profile 548 * Connection Spaces in the ICC specification. For all other types, this 549 * method returns 0.0 for all components. When using an ICC_ColorSpace 550 * with a profile that requires different minimum component values, 551 * it is necessary to subclass this class and override this method. 552 * @param component The component index. 553 * @return The minimum normalized component value. 554 * @throws IllegalArgumentException if component is less than 0 or 555 * greater than numComponents - 1. 556 * @since 1.4 557 */ 558 public float getMinValue(int component) { 559 if ((component < 0) || (component > this.getNumComponents() - 1)) { 560 throw new IllegalArgumentException( 561 "Component index out of range: " + component); 562 } 563 return minVal[component]; 564 } 565 566 /** 567 * Returns the maximum normalized color component value for the 568 * specified component. For TYPE_XYZ spaces, this method returns 569 * maximum values of 1.0 + (32767.0 / 32768.0) for all components. 570 * For TYPE_Lab spaces, 571 * this method returns 100.0 for L and 127.0 for a and b components. 572 * This is consistent with the encoding of the XYZ and Lab Profile 573 * Connection Spaces in the ICC specification. For all other types, this 574 * method returns 1.0 for all components. When using an ICC_ColorSpace 575 * with a profile that requires different maximum component values, 576 * it is necessary to subclass this class and override this method. 577 * @param component The component index. 578 * @return The maximum normalized component value. 579 * @throws IllegalArgumentException if component is less than 0 or 580 * greater than numComponents - 1. 581 * @since 1.4 582 */ 583 public float getMaxValue(int component) { 584 if ((component < 0) || (component > this.getNumComponents() - 1)) { 585 throw new IllegalArgumentException( 586 "Component index out of range: " + component); 587 } 588 return maxVal[component]; 589 } 590 591 private void setMinMax() { 592 int nc = this.getNumComponents(); 593 int type = this.getType(); 594 minVal = new float[nc]; 595 maxVal = new float[nc]; 596 if (type == ColorSpace.TYPE_Lab) { 597 minVal[0] = 0.0f; // L 598 maxVal[0] = 100.0f; 599 minVal[1] = -128.0f; // a 600 maxVal[1] = 127.0f; 601 minVal[2] = -128.0f; // b 602 maxVal[2] = 127.0f; 603 } else if (type == ColorSpace.TYPE_XYZ) { 604 minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z 605 maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f); 606 } else { 607 for (int i = 0; i < nc; i++) { 608 minVal[i] = 0.0f; 609 maxVal[i] = 1.0f; 610 } 611 } 612 } 613 614 private void setComponentScaling() { 615 int nc = this.getNumComponents(); 616 diffMinMax = new float[nc]; 617 invDiffMinMax = new float[nc]; 618 for (int i = 0; i < nc; i++) { 619 minVal[i] = this.getMinValue(i); // in case getMinVal is overridden 620 maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden 621 diffMinMax[i] = maxVal[i] - minVal[i]; 622 invDiffMinMax[i] = 65535.0f / diffMinMax[i]; 623 } 624 needScaleInit = false; 625 } 626 627 }