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) { 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; | 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) { 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; |