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 * Returns the ICC_Profile for this ICC_ColorSpace. 132 * @return the ICC_Profile for this ICC_ColorSpace. 133 */ 134 public ICC_Profile getProfile() { 135 return thisProfile; 136 } 137 138 /** 139 * Transforms a color value assumed to be in this ColorSpace 140 * into a value in the default CS_sRGB color space. 141 * <p> 142 * This method transforms color values using algorithms designed 143 * to produce the best perceptual match between input and output 144 * colors. In order to do colorimetric conversion of color values, 145 * you should use the <code>toCIEXYZ</code> 146 * method of this color space to first convert from the input 147 * color space to the CS_CIEXYZ color space, and then use the 148 * <code>fromCIEXYZ</code> method of the CS_sRGB color space to 149 * convert from CS_CIEXYZ to the output color space. 150 * See {@link #toCIEXYZ(float[]) toCIEXYZ} and 151 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 152 * 153 * @param colorvalue a float array with length of at least the number 154 * of components in this ColorSpace. 155 * @return a float array of length 3. 156 * @throws ArrayIndexOutOfBoundsException if array length is not 157 * at least the number of components in this ColorSpace. 158 */ 159 public float[] toRGB (float[] colorvalue) { 160 161 if (this2srgb == null) { 162 ColorTransform[] transformList = new ColorTransform [2]; 163 ICC_ColorSpace srgbCS = 164 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB); 165 PCMM mdl = CMSManager.getModule(); 166 transformList[0] = mdl.createTransform( 167 thisProfile, ColorTransform.Any, ColorTransform.In); 168 transformList[1] = mdl.createTransform( 169 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 170 this2srgb = mdl.createTransform(transformList); 171 if (needScaleInit) { 172 setComponentScaling(); 173 } 174 } 175 176 int nc = this.getNumComponents(); 177 short tmp[] = new short[nc]; 178 for (int i = 0; i < nc; i++) { 179 tmp[i] = (short) 180 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f); 181 } 182 tmp = this2srgb.colorConvert(tmp, null); 183 float[] result = new float [3]; 184 for (int i = 0; i < 3; i++) { 185 result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f; 186 } 187 return result; 188 } 189 190 /** 191 * Transforms a color value assumed to be in the default CS_sRGB 192 * color space into this ColorSpace. 193 * <p> 194 * This method transforms color values using algorithms designed 195 * to produce the best perceptual match between input and output 196 * colors. In order to do colorimetric conversion of color values, 197 * you should use the <code>toCIEXYZ</code> 198 * method of the CS_sRGB color space to first convert from the input 199 * color space to the CS_CIEXYZ color space, and then use the 200 * <code>fromCIEXYZ</code> method of this color space to 201 * convert from CS_CIEXYZ to the output color space. 202 * See {@link #toCIEXYZ(float[]) toCIEXYZ} and 203 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 204 * 205 * @param rgbvalue a float array with length of at least 3. 206 * @return a float array with length equal to the number of 207 * components in this ColorSpace. 208 * @throws ArrayIndexOutOfBoundsException if array length is not 209 * at least 3. 210 */ 211 public float[] fromRGB(float[] rgbvalue) { 212 213 if (srgb2this == null) { 214 ColorTransform[] transformList = new ColorTransform [2]; 215 ICC_ColorSpace srgbCS = 216 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB); 217 PCMM mdl = CMSManager.getModule(); 218 transformList[0] = mdl.createTransform( 219 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In); 220 transformList[1] = mdl.createTransform( 221 thisProfile, ColorTransform.Any, ColorTransform.Out); 222 srgb2this = mdl.createTransform(transformList); 223 if (needScaleInit) { 224 setComponentScaling(); 225 } 226 } 227 228 short tmp[] = new short[3]; 229 for (int i = 0; i < 3; i++) { 230 tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f); 231 } 232 tmp = srgb2this.colorConvert(tmp, null); 233 int nc = this.getNumComponents(); 234 float[] result = new float [nc]; 235 for (int i = 0; i < nc; i++) { 236 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * 237 diffMinMax[i] + minVal[i]; 238 } 239 return result; 240 } 241 242 243 /** 244 * Transforms a color value assumed to be in this ColorSpace 245 * into the CS_CIEXYZ conversion color space. 246 * <p> 247 * This method transforms color values using relative colorimetry, 248 * as defined by the ICC Specification. This 249 * means that the XYZ values returned by this method are represented 250 * relative to the D50 white point of the CS_CIEXYZ color space. 251 * This representation is useful in a two-step color conversion 252 * process in which colors are transformed from an input color 253 * space to CS_CIEXYZ and then to an output color space. This 254 * representation is not the same as the XYZ values that would 255 * be measured from the given color value by a colorimeter. 256 * A further transformation is necessary to compute the XYZ values 257 * that would be measured using current CIE recommended practices. 258 * The paragraphs below 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 262 * this architecture, colors are converted from the source device's color 263 * space to the ICC DICS and then from the ICC DICS to the destination 264 * device's color space. The ICC standard defines device profiles which 265 * contain transforms which will convert between a device's color space 266 * and the ICC DICS. The overall conversion of colors from a source 267 * device to colors of a destination device is done by connecting the 268 * device-to-DICS transform of the profile for the source device to the 269 * DICS-to-device transform of the profile for the destination device. 270 * For this reason, the ICC DICS is commonly referred to as the profile 271 * connection space (PCS). The color space used in the methods 272 * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC 273 * Specification. This is also the color space represented by 274 * ColorSpace.CS_CIEXYZ. 275 * <p> 276 * The XYZ values of a color are often represented as relative to some 277 * white point, so the actual meaning of the XYZ values cannot be known 278 * without knowing the white point of those values. This is known as 279 * relative colorimetry. The PCS uses a white point of D50, so the XYZ 280 * values of the PCS are relative to D50. For example, white in the PCS 281 * will have the XYZ values of D50, which is defined to be X=.9642, 282 * Y=1.000, and Z=0.8249. This white point is commonly used for graphic 283 * arts applications, but others are often used in other applications. 284 * <p> 285 * To quantify the color characteristics of a device such as a printer 286 * or monitor, measurements of XYZ values for particular device colors 287 * are typically made. For purposes of this discussion, the term 288 * device XYZ values is used to mean the XYZ values that would be 289 * measured from device colors using current CIE recommended practices. 290 * <p> 291 * Converting between device XYZ values and the PCS XYZ values returned 292 * by this method corresponds to converting between the device's color 293 * space, as represented by CIE colorimetric values, and the PCS. There 294 * are many factors involved in this process, some of which are quite 295 * subtle. The most important, however, is the adjustment made to account 296 * for differences between the device's white point and the white point of 297 * the PCS. There are many techniques for doing this and it is the 298 * subject of much current research and controversy. Some commonly used 299 * methods are XYZ scaling, the von Kries transform, and the Bradford 300 * transform. The proper method to use depends upon each particular 301 * application. 302 * <p> 303 * The simplest method is XYZ scaling. In this method each device XYZ 304 * value is converted to a PCS XYZ value by multiplying it by the ratio 305 * of the PCS white point (D50) to the device white point. 306 * <pre> 307 * 308 * Xd, Yd, Zd are the device XYZ values 309 * Xdw, Ydw, Zdw are the device XYZ white point values 310 * Xp, Yp, Zp are the PCS XYZ values 311 * Xd50, Yd50, Zd50 are the PCS XYZ white point values 312 * 313 * Xp = Xd * (Xd50 / Xdw) 314 * Yp = Yd * (Yd50 / Ydw) 315 * Zp = Zd * (Zd50 / Zdw) 316 * 317 * </pre> 318 * <p> 319 * Conversion from the PCS to the device would be done by inverting these 320 * equations: 321 * <pre> 322 * 323 * Xd = Xp * (Xdw / Xd50) 324 * Yd = Yp * (Ydw / Yd50) 325 * Zd = Zp * (Zdw / Zd50) 326 * 327 * </pre> 328 * <p> 329 * Note that the media white point tag in an ICC profile is not the same 330 * as the device white point. The media white point tag is expressed in 331 * PCS values and is used to represent the difference between the XYZ of 332 * device illuminant and the XYZ of the device media when measured under 333 * that illuminant. The device white point is expressed as the device 334 * XYZ values corresponding to white displayed on the device. For 335 * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device 336 * will result in a measured device XYZ value of D65. This will not 337 * be the same as the media white point tag XYZ value in the ICC 338 * profile for an sRGB device. 339 * 340 * @param colorvalue a float array with length of at least the number 341 * of components in this ColorSpace. 342 * @return a float array of length 3. 343 * @throws ArrayIndexOutOfBoundsException if array length is not 344 * at least the number of components in this ColorSpace. 345 */ 346 public float[] toCIEXYZ(float[] colorvalue) { 347 348 if (this2xyz == null) { 349 ColorTransform[] transformList = new ColorTransform [2]; 350 ICC_ColorSpace xyzCS = 351 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ); 352 PCMM mdl = CMSManager.getModule(); 353 try { 354 transformList[0] = mdl.createTransform( 355 thisProfile, ICC_Profile.icRelativeColorimetric, 356 ColorTransform.In); 357 } catch (CMMException e) { 358 transformList[0] = mdl.createTransform( 359 thisProfile, ColorTransform.Any, ColorTransform.In); 360 } 361 transformList[1] = mdl.createTransform( 362 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out); 363 this2xyz = mdl.createTransform (transformList); 364 if (needScaleInit) { 365 setComponentScaling(); 366 } 367 } 368 369 int nc = this.getNumComponents(); 370 short tmp[] = new short[nc]; 371 for (int i = 0; i < nc; i++) { 372 tmp[i] = (short) 373 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f); 374 } 375 tmp = this2xyz.colorConvert(tmp, null); 376 float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f); 377 // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components 378 float[] result = new float [3]; 379 for (int i = 0; i < 3; i++) { 380 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO; 381 } 382 return result; 383 } 384 385 386 /** 387 * Transforms a color value assumed to be in the CS_CIEXYZ conversion 388 * color space into this ColorSpace. 389 * <p> 390 * This method transforms color values using relative colorimetry, 391 * as defined by the ICC Specification. This 392 * means that the XYZ argument values taken by this method are represented 393 * relative to the D50 white point of the CS_CIEXYZ color space. 394 * This representation is useful in a two-step color conversion 395 * process in which colors are transformed from an input color 396 * space to CS_CIEXYZ and then to an output color space. The color 397 * values returned by this method are not those that would produce 398 * the XYZ value passed to the method when measured by a colorimeter. 399 * If you have XYZ values corresponding to measurements made using 400 * current CIE recommended practices, they must be converted to D50 401 * relative values before being passed to this method. 402 * The paragraphs below explain this in more detail. 403 * <p> 404 * The ICC standard uses a device independent color space (DICS) as the 405 * mechanism for converting color from one device to another device. In 406 * this architecture, colors are converted from the source device's color 407 * space to the ICC DICS and then from the ICC DICS to the destination 408 * device's color space. The ICC standard defines device profiles which 409 * contain transforms which will convert between a device's color space 410 * and the ICC DICS. The overall conversion of colors from a source 411 * device to colors of a destination device is done by connecting the 412 * device-to-DICS transform of the profile for the source device to the 413 * DICS-to-device transform of the profile for the destination device. 414 * For this reason, the ICC DICS is commonly referred to as the profile 415 * connection space (PCS). The color space used in the methods 416 * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC 417 * Specification. This is also the color space represented by 418 * ColorSpace.CS_CIEXYZ. 419 * <p> 420 * The XYZ values of a color are often represented as relative to some 421 * white point, so the actual meaning of the XYZ values cannot be known 422 * without knowing the white point of those values. This is known as 423 * relative colorimetry. The PCS uses a white point of D50, so the XYZ 424 * values of the PCS are relative to D50. For example, white in the PCS 425 * will have the XYZ values of D50, which is defined to be X=.9642, 426 * Y=1.000, and Z=0.8249. This white point is commonly used for graphic 427 * arts applications, but others are often used in other applications. 428 * <p> 429 * To quantify the color characteristics of a device such as a printer 430 * or monitor, measurements of XYZ values for particular device colors 431 * are typically made. For purposes of this discussion, the term 432 * device XYZ values is used to mean the XYZ values that would be 433 * measured from device colors using current CIE recommended practices. 434 * <p> 435 * Converting between device XYZ values and the PCS XYZ values taken as 436 * arguments by this method corresponds to converting between the device's 437 * color space, as represented by CIE colorimetric values, and the PCS. 438 * There are many factors involved in this process, some of which are quite 439 * subtle. The most important, however, is the adjustment made to account 440 * for differences between the device's white point and the white point of 441 * the PCS. There are many techniques for doing this and it is the 442 * subject of much current research and controversy. Some commonly used 443 * methods are XYZ scaling, the von Kries transform, and the Bradford 444 * transform. The proper method to use depends upon each particular 445 * application. 446 * <p> 447 * The simplest method is XYZ scaling. In this method each device XYZ 448 * value is converted to a PCS XYZ value by multiplying it by the ratio 449 * of the PCS white point (D50) to the device white point. 450 * <pre> 451 * 452 * Xd, Yd, Zd are the device XYZ values 453 * Xdw, Ydw, Zdw are the device XYZ white point values 454 * Xp, Yp, Zp are the PCS XYZ values 455 * Xd50, Yd50, Zd50 are the PCS XYZ white point values 456 * 457 * Xp = Xd * (Xd50 / Xdw) 458 * Yp = Yd * (Yd50 / Ydw) 459 * Zp = Zd * (Zd50 / Zdw) 460 * 461 * </pre> 462 * <p> 463 * Conversion from the PCS to the device would be done by inverting these 464 * equations: 465 * <pre> 466 * 467 * Xd = Xp * (Xdw / Xd50) 468 * Yd = Yp * (Ydw / Yd50) 469 * Zd = Zp * (Zdw / Zd50) 470 * 471 * </pre> 472 * <p> 473 * Note that the media white point tag in an ICC profile is not the same 474 * as the device white point. The media white point tag is expressed in 475 * PCS values and is used to represent the difference between the XYZ of 476 * device illuminant and the XYZ of the device media when measured under 477 * that illuminant. The device white point is expressed as the device 478 * XYZ values corresponding to white displayed on the device. For 479 * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device 480 * will result in a measured device XYZ value of D65. This will not 481 * be the same as the media white point tag XYZ value in the ICC 482 * profile for an sRGB device. 483 * 484 * @param colorvalue a float array with length of at least 3. 485 * @return a float array with length equal to the number of 486 * components in this ColorSpace. 487 * @throws ArrayIndexOutOfBoundsException if array length is not 488 * at least 3. 489 */ 490 public float[] fromCIEXYZ(float[] colorvalue) { 491 492 if (xyz2this == null) { 493 ColorTransform[] transformList = new ColorTransform [2]; 494 ICC_ColorSpace xyzCS = 495 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ); 496 PCMM mdl = CMSManager.getModule(); 497 transformList[0] = mdl.createTransform ( 498 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In); 499 try { 500 transformList[1] = mdl.createTransform( 501 thisProfile, ICC_Profile.icRelativeColorimetric, 502 ColorTransform.Out); 503 } catch (CMMException e) { 504 transformList[1] = CMSManager.getModule().createTransform( 505 thisProfile, ColorTransform.Any, ColorTransform.Out); 506 } 507 xyz2this = mdl.createTransform(transformList); 508 if (needScaleInit) { 509 setComponentScaling(); 510 } 511 } 512 513 short tmp[] = new short[3]; 514 float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f); 515 float factor = 65535.0f / ALMOST_TWO; 516 // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components 517 for (int i = 0; i < 3; i++) { 518 tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f); 519 } 520 tmp = xyz2this.colorConvert(tmp, null); 521 int nc = this.getNumComponents(); 522 float[] result = new float [nc]; 523 for (int i = 0; i < nc; i++) { 524 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * 525 diffMinMax[i] + minVal[i]; 526 } 527 return result; 528 } 529 530 /** 531 * Returns the minimum normalized color component value for the 532 * specified component. For TYPE_XYZ spaces, this method returns 533 * minimum values of 0.0 for all components. For TYPE_Lab spaces, 534 * this method returns 0.0 for L and -128.0 for a and b components. 535 * This is consistent with the encoding of the XYZ and Lab Profile 536 * Connection Spaces in the ICC specification. For all other types, this 537 * method returns 0.0 for all components. When using an ICC_ColorSpace 538 * with a profile that requires different minimum component values, 539 * it is necessary to subclass this class and override this method. 540 * @param component The component index. 541 * @return The minimum normalized component value. 542 * @throws IllegalArgumentException if component is less than 0 or 543 * greater than numComponents - 1. 544 * @since 1.4 545 */ 546 public float getMinValue(int component) { 547 if ((component < 0) || (component > this.getNumComponents() - 1)) { 548 throw new IllegalArgumentException( 549 "Component index out of range: " + component); 550 } 551 return minVal[component]; 552 } 553 554 /** 555 * Returns the maximum normalized color component value for the 556 * specified component. For TYPE_XYZ spaces, this method returns 557 * maximum values of 1.0 + (32767.0 / 32768.0) for all components. 558 * For TYPE_Lab spaces, 559 * this method returns 100.0 for L and 127.0 for a and b components. 560 * This is consistent with the encoding of the XYZ and Lab Profile 561 * Connection Spaces in the ICC specification. For all other types, this 562 * method returns 1.0 for all components. When using an ICC_ColorSpace 563 * with a profile that requires different maximum component values, 564 * it is necessary to subclass this class and override this method. 565 * @param component The component index. 566 * @return The maximum normalized component value. 567 * @throws IllegalArgumentException if component is less than 0 or 568 * greater than numComponents - 1. 569 * @since 1.4 570 */ 571 public float getMaxValue(int component) { 572 if ((component < 0) || (component > this.getNumComponents() - 1)) { 573 throw new IllegalArgumentException( 574 "Component index out of range: " + component); 575 } 576 return maxVal[component]; 577 } 578 579 private void setMinMax() { 580 int nc = this.getNumComponents(); 581 int type = this.getType(); 582 minVal = new float[nc]; 583 maxVal = new float[nc]; 584 if (type == ColorSpace.TYPE_Lab) { 585 minVal[0] = 0.0f; // L 586 maxVal[0] = 100.0f; 587 minVal[1] = -128.0f; // a 588 maxVal[1] = 127.0f; 589 minVal[2] = -128.0f; // b 590 maxVal[2] = 127.0f; 591 } else if (type == ColorSpace.TYPE_XYZ) { 592 minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z 593 maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f); 594 } else { 595 for (int i = 0; i < nc; i++) { 596 minVal[i] = 0.0f; 597 maxVal[i] = 1.0f; 598 } 599 } 600 } 601 602 private void setComponentScaling() { 603 int nc = this.getNumComponents(); 604 diffMinMax = new float[nc]; 605 invDiffMinMax = new float[nc]; 606 for (int i = 0; i < nc; i++) { 607 minVal[i] = this.getMinValue(i); // in case getMinVal is overridden 608 maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden 609 diffMinMax[i] = maxVal[i] - minVal[i]; 610 invDiffMinMax[i] = 65535.0f / diffMinMax[i]; 611 } 612 needScaleInit = false; 613 } 614 615 }