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