1 /* 2 * Copyright (c) 1997, 2020, 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 java.io.Serializable; 39 import java.lang.annotation.Native; 40 41 import sun.java2d.cmm.CMSManager; 42 43 /** 44 * This abstract class is used to serve as a color space tag to identify the 45 * specific color space of a {@code Color} object or, via a {@code ColorModel} 46 * object, of an {@code Image}, a {@code BufferedImage}, or a 47 * {@code GraphicsDevice}. It contains methods that transform colors in a 48 * specific color space to/from sRGB and to/from a well-defined CIEXYZ color 49 * space. 50 * <p> 51 * For purposes of the methods in this class, colors are represented as arrays 52 * of color components represented as floats in a normalized range defined by 53 * each {@code ColorSpace}. For many {@code ColorSpaces} (e.g. sRGB), this range 54 * is 0.0 to 1.0. However, some {@code ColorSpaces} have components whose values 55 * have a different range. Methods are provided to inquire per component minimum 56 * and maximum normalized values. 57 * <p> 58 * Several variables are defined for purposes of referring to color space types 59 * (e.g. {@code TYPE_RGB}, {@code TYPE_XYZ}, etc.) and to refer to specific 60 * color spaces (e.g. {@code CS_sRGB} and {@code CS_CIEXYZ}). sRGB is a proposed 61 * standard RGB color space. For more information, see 62 * <a href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html"> 63 * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html</a>. 64 * <p> 65 * The purpose of the methods to transform to/from the well-defined CIEXYZ color 66 * space is to support conversions between any two color spaces at a reasonably 67 * high degree of accuracy. It is expected that particular implementations of 68 * subclasses of {@code ColorSpace} (e.g. {@code ICC_ColorSpace}) will support 69 * high performance conversion based on underlying platform color management 70 * systems. 71 * <p> 72 * The {@code CS_CIEXYZ} space used by the {@code toCIEXYZ/fromCIEXYZ} methods 73 * can be described as follows: 74 * <pre> 75 * 76 * CIEXYZ 77 * viewing illuminance: 200 lux 78 * viewing white point: CIE D50 79 * media white point: "that of a perfectly reflecting diffuser" -- D50 80 * media black point: 0 lux or 0 Reflectance 81 * flare: 1 percent 82 * surround: 20percent of the media white point 83 * media description: reflection print (i.e., RLAB, Hunt viewing media) 84 * note: For developers creating an ICC profile for this conversion 85 * space, the following is applicable. Use a simple Von Kries 86 * white point adaptation folded into the 3X3 matrix parameters 87 * and fold the flare and surround effects into the three 88 * one-dimensional lookup tables (assuming one uses the minimal 89 * model for monitors). 90 * 91 * </pre> 92 * 93 * @see ICC_ColorSpace 94 */ 95 public abstract class ColorSpace implements Serializable { 96 97 /** 98 * Use serialVersionUID from JDK 1.2 for interoperability. 99 */ 100 private static final long serialVersionUID = -409452704308689724L; 101 102 /** 103 * One of the {@code ColorSpace} type constants. 104 */ 105 private final int type; 106 107 /** 108 * The number of components in the color space. 109 */ 110 private final int numComponents; 111 private transient String [] compName = null; 112 113 // Cache of singletons for the predefined color spaces. 114 private static ColorSpace sRGBspace; 115 private static ColorSpace XYZspace; 116 private static ColorSpace PYCCspace; 117 private static ColorSpace GRAYspace; 118 private static ColorSpace LINEAR_RGBspace; 119 120 /** 121 * Any of the family of XYZ color spaces. 122 */ 123 @Native public static final int TYPE_XYZ = 0; 124 125 /** 126 * Any of the family of Lab color spaces. 127 */ 128 @Native public static final int TYPE_Lab = 1; 129 130 /** 131 * Any of the family of Luv color spaces. 132 */ 133 @Native public static final int TYPE_Luv = 2; 134 135 /** 136 * Any of the family of YCbCr color spaces. 137 */ 138 @Native public static final int TYPE_YCbCr = 3; 139 140 /** 141 * Any of the family of Yxy color spaces. 142 */ 143 @Native public static final int TYPE_Yxy = 4; 144 145 /** 146 * Any of the family of RGB color spaces. 147 */ 148 @Native public static final int TYPE_RGB = 5; 149 150 /** 151 * Any of the family of GRAY color spaces. 152 */ 153 @Native public static final int TYPE_GRAY = 6; 154 155 /** 156 * Any of the family of HSV color spaces. 157 */ 158 @Native public static final int TYPE_HSV = 7; 159 160 /** 161 * Any of the family of HLS color spaces. 162 */ 163 @Native public static final int TYPE_HLS = 8; 164 165 /** 166 * Any of the family of CMYK color spaces. 167 */ 168 @Native public static final int TYPE_CMYK = 9; 169 170 /** 171 * Any of the family of CMY color spaces. 172 */ 173 @Native public static final int TYPE_CMY = 11; 174 175 /** 176 * Generic 2 component color spaces. 177 */ 178 @Native public static final int TYPE_2CLR = 12; 179 180 /** 181 * Generic 3 component color spaces. 182 */ 183 @Native public static final int TYPE_3CLR = 13; 184 185 /** 186 * Generic 4 component color spaces. 187 */ 188 @Native public static final int TYPE_4CLR = 14; 189 190 /** 191 * Generic 5 component color spaces. 192 */ 193 @Native public static final int TYPE_5CLR = 15; 194 195 /** 196 * Generic 6 component color spaces. 197 */ 198 @Native public static final int TYPE_6CLR = 16; 199 200 /** 201 * Generic 7 component color spaces. 202 */ 203 @Native public static final int TYPE_7CLR = 17; 204 205 /** 206 * Generic 8 component color spaces. 207 */ 208 @Native public static final int TYPE_8CLR = 18; 209 210 /** 211 * Generic 9 component color spaces. 212 */ 213 @Native public static final int TYPE_9CLR = 19; 214 215 /** 216 * Generic 10 component color spaces. 217 */ 218 @Native public static final int TYPE_ACLR = 20; 219 220 /** 221 * Generic 11 component color spaces. 222 */ 223 @Native public static final int TYPE_BCLR = 21; 224 225 /** 226 * Generic 12 component color spaces. 227 */ 228 @Native public static final int TYPE_CCLR = 22; 229 230 /** 231 * Generic 13 component color spaces. 232 */ 233 @Native public static final int TYPE_DCLR = 23; 234 235 /** 236 * Generic 14 component color spaces. 237 */ 238 @Native public static final int TYPE_ECLR = 24; 239 240 /** 241 * Generic 15 component color spaces. 242 */ 243 @Native public static final int TYPE_FCLR = 25; 244 245 246 /** 247 * The built-in sRGB color space defined at 248 * <a href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html"> 249 * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html</a>. 250 */ 251 @Native public static final int CS_sRGB = 1000; 252 253 /** 254 * The built-in linear RGB color space. This space is based on the same RGB 255 * primaries as {@code CS_sRGB}, but has a linear tone reproduction curve. 256 */ 257 @Native public static final int CS_LINEAR_RGB = 1004; 258 259 /** 260 * The built-in CIEXYZ conversion color space defined above. 261 */ 262 @Native public static final int CS_CIEXYZ = 1001; 263 264 /** 265 * The built-in Photo YCC conversion color space. 266 */ 267 @Native public static final int CS_PYCC = 1002; 268 269 /** 270 * The built-in linear gray scale color space. 271 */ 272 @Native public static final int CS_GRAY = 1003; 273 274 /** 275 * Constructs a {@code ColorSpace} object given a color space type and the 276 * number of components. 277 * 278 * @param type one of the {@code ColorSpace} type constants 279 * @param numComponents the number of components in the color space 280 */ ColorSpace(int type, int numComponents)281 protected ColorSpace(int type, int numComponents) { 282 this.type = type; 283 this.numComponents = numComponents; 284 } 285 286 /** 287 * Returns a {@code ColorSpace} representing one of the specific predefined 288 * color spaces. 289 * 290 * @param colorspace a specific color space identified by one of the 291 * predefined class constants (e.g. {@code CS_sRGB}, 292 * {@code CS_LINEAR_RGB}, {@code CS_CIEXYZ}, {@code CS_GRAY}, or 293 * {@code CS_PYCC}) 294 * @return the requested {@code ColorSpace} object 295 */ 296 // NOTE: This method may be called by privileged threads. 297 // DO NOT INVOKE CLIENT CODE ON THIS THREAD! getInstance(int colorspace)298 public static ColorSpace getInstance (int colorspace) 299 { 300 ColorSpace theColorSpace; 301 302 switch (colorspace) { 303 case CS_sRGB: 304 synchronized(ColorSpace.class) { 305 if (sRGBspace == null) { 306 ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB); 307 sRGBspace = new ICC_ColorSpace (theProfile); 308 } 309 310 theColorSpace = sRGBspace; 311 } 312 break; 313 314 case CS_CIEXYZ: 315 synchronized(ColorSpace.class) { 316 if (XYZspace == null) { 317 ICC_Profile theProfile = 318 ICC_Profile.getInstance (CS_CIEXYZ); 319 XYZspace = new ICC_ColorSpace (theProfile); 320 } 321 322 theColorSpace = XYZspace; 323 } 324 break; 325 326 case CS_PYCC: 327 synchronized(ColorSpace.class) { 328 if (PYCCspace == null) { 329 ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC); 330 PYCCspace = new ICC_ColorSpace (theProfile); 331 } 332 333 theColorSpace = PYCCspace; 334 } 335 break; 336 337 338 case CS_GRAY: 339 synchronized(ColorSpace.class) { 340 if (GRAYspace == null) { 341 ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY); 342 GRAYspace = new ICC_ColorSpace (theProfile); 343 /* to allow access from java.awt.ColorModel */ 344 CMSManager.GRAYspace = GRAYspace; 345 } 346 347 theColorSpace = GRAYspace; 348 } 349 break; 350 351 352 case CS_LINEAR_RGB: 353 synchronized(ColorSpace.class) { 354 if (LINEAR_RGBspace == null) { 355 ICC_Profile theProfile = 356 ICC_Profile.getInstance(CS_LINEAR_RGB); 357 LINEAR_RGBspace = new ICC_ColorSpace (theProfile); 358 /* to allow access from java.awt.ColorModel */ 359 CMSManager.LINEAR_RGBspace = LINEAR_RGBspace; 360 } 361 362 theColorSpace = LINEAR_RGBspace; 363 } 364 break; 365 366 367 default: 368 throw new IllegalArgumentException ("Unknown color space"); 369 } 370 371 return theColorSpace; 372 } 373 374 /** 375 * Returns true if the {@code ColorSpace} is {@code CS_sRGB}. 376 * 377 * @return {@code true} if this is a {@code CS_sRGB} color space, 378 * {@code false} if it is not 379 */ isCS_sRGB()380 public boolean isCS_sRGB () { 381 /* REMIND - make sure we know sRGBspace exists already */ 382 return (this == sRGBspace); 383 } 384 385 /** 386 * Transforms a color value assumed to be in this {@code ColorSpace} into a 387 * value in the default {@code CS_sRGB} color space. 388 * <p> 389 * This method transforms color values using algorithms designed to produce 390 * the best perceptual match between input and output colors. In order to do 391 * colorimetric conversion of color values, you should use the 392 * {@code toCIEXYZ} method of this color space to first convert from the 393 * input color space to the CS_CIEXYZ color space, and then use the 394 * {@code fromCIEXYZ} method of the {@code CS_sRGB} color space to convert 395 * from {@code CS_CIEXYZ} to the output color space. See 396 * {@link #toCIEXYZ(float[]) toCIEXYZ} and 397 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 398 * 399 * @param colorvalue a float array with length of at least the number of 400 * components in this {@code ColorSpace} 401 * @return a float array of length 3 402 * @throws ArrayIndexOutOfBoundsException if array length is not at least 403 * the number of components in this {@code ColorSpace} 404 */ toRGB(float[] colorvalue)405 public abstract float[] toRGB(float[] colorvalue); 406 407 /** 408 * Transforms a color value assumed to be in the default {@code CS_sRGB} 409 * color space into this {@code ColorSpace}. 410 * <p> 411 * This method transforms color values using algorithms designed to produce 412 * the best perceptual match between input and output colors. In order to do 413 * colorimetric conversion of color values, you should use the 414 * {@code toCIEXYZ} method of the {@code CS_sRGB} color space to first 415 * convert from the input color space to the {@code CS_CIEXYZ} color space, 416 * and then use the {@code fromCIEXYZ} method of this color space to convert 417 * from {@code CS_CIEXYZ} to the output color space. See 418 * {@link #toCIEXYZ(float[]) toCIEXYZ} and 419 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. 420 * 421 * @param rgbvalue a float array with length of at least 3 422 * @return a float array with length equal to the number of components in 423 * this {@code ColorSpace} 424 * @throws ArrayIndexOutOfBoundsException if array length is not at least 3 425 */ fromRGB(float[] rgbvalue)426 public abstract float[] fromRGB(float[] rgbvalue); 427 428 /** 429 * Transforms a color value assumed to be in this {@code ColorSpace} into 430 * the {@code CS_CIEXYZ} conversion color space. 431 * <p> 432 * This method transforms color values using relative colorimetry, as 433 * defined by the International Color Consortium standard. This means that 434 * the XYZ values returned by this method are represented relative to the 435 * D50 white point of the {@code CS_CIEXYZ} color space. This representation 436 * is useful in a two-step color conversion process in which colors are 437 * transformed from an input color space to {@code CS_CIEXYZ} and then to an 438 * output color space. This representation is not the same as the XYZ values 439 * that would be measured from the given color value by a colorimeter. A 440 * further transformation is necessary to compute the XYZ values that would 441 * be measured using current CIE recommended practices. See the 442 * {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of 443 * {@code ICC_ColorSpace} for further information. 444 * 445 * @param colorvalue a float array with length of at least the number of 446 * components in this {@code ColorSpace} 447 * @return a float array of length 3 448 * @throws ArrayIndexOutOfBoundsException if array length is not at least 449 * the number of components in this {@code ColorSpace}. 450 */ toCIEXYZ(float[] colorvalue)451 public abstract float[] toCIEXYZ(float[] colorvalue); 452 453 /** 454 * Transforms a color value assumed to be in the {@code CS_CIEXYZ} 455 * conversion color space into this {@code ColorSpace}. 456 * <p> 457 * This method transforms color values using relative colorimetry, as 458 * defined by the International Color Consortium standard. This means that 459 * the XYZ argument values taken by this method are represented relative to 460 * the D50 white point of the {@code CS_CIEXYZ} color space. This 461 * representation is useful in a two-step color conversion process in which 462 * colors are transformed from an input color space to {@code CS_CIEXYZ} and 463 * then to an output color space. The color values returned by this method 464 * are not those that would produce the XYZ value passed to the method when 465 * measured by a colorimeter. If you have XYZ values corresponding to 466 * measurements made using current CIE recommended practices, they must be 467 * converted to D50 relative values before being passed to this method. See 468 * the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of 469 * {@code ICC_ColorSpace} for further information. 470 * 471 * @param colorvalue a float array with length of at least 3 472 * @return a float array with length equal to the number of components in 473 * this {@code ColorSpace} 474 * @throws ArrayIndexOutOfBoundsException if array length is not at least 3 475 */ fromCIEXYZ(float[] colorvalue)476 public abstract float[] fromCIEXYZ(float[] colorvalue); 477 478 /** 479 * Returns the color space type of this {@code ColorSpace} (for example 480 * {@code TYPE_RGB}, {@code TYPE_XYZ}, ...). The type defines the number of 481 * components of the color space and the interpretation, e.g. 482 * {@code TYPE_RGB} identifies a color space with three components - red, 483 * green, and blue. It does not define the particular color characteristics 484 * of the space, e.g. the chromaticities of the primaries. 485 * 486 * @return the type constant that represents the type of this 487 * {@code ColorSpace} 488 */ getType()489 public int getType() { 490 return type; 491 } 492 493 /** 494 * Returns the number of components of this ColorSpace. 495 * 496 * @return the number of components in this {@code ColorSpace} 497 */ getNumComponents()498 public int getNumComponents() { 499 return numComponents; 500 } 501 502 /** 503 * Returns the name of the component given the component index. 504 * 505 * @param idx the component index 506 * @return the name of the component at the specified index 507 * @throws IllegalArgumentException if {@code idx} is less than 0 or greater 508 * than {@code numComponents - 1} 509 */ getName(int idx)510 public String getName (int idx) { 511 /* REMIND - handle common cases here */ 512 rangeCheck(idx); 513 if (compName == null) { 514 switch (type) { 515 case ColorSpace.TYPE_XYZ: 516 compName = new String[] {"X", "Y", "Z"}; 517 break; 518 case ColorSpace.TYPE_Lab: 519 compName = new String[] {"L", "a", "b"}; 520 break; 521 case ColorSpace.TYPE_Luv: 522 compName = new String[] {"L", "u", "v"}; 523 break; 524 case ColorSpace.TYPE_YCbCr: 525 compName = new String[] {"Y", "Cb", "Cr"}; 526 break; 527 case ColorSpace.TYPE_Yxy: 528 compName = new String[] {"Y", "x", "y"}; 529 break; 530 case ColorSpace.TYPE_RGB: 531 compName = new String[] {"Red", "Green", "Blue"}; 532 break; 533 case ColorSpace.TYPE_GRAY: 534 compName = new String[] {"Gray"}; 535 break; 536 case ColorSpace.TYPE_HSV: 537 compName = new String[] {"Hue", "Saturation", "Value"}; 538 break; 539 case ColorSpace.TYPE_HLS: 540 compName = new String[] {"Hue", "Lightness", 541 "Saturation"}; 542 break; 543 case ColorSpace.TYPE_CMYK: 544 compName = new String[] {"Cyan", "Magenta", "Yellow", 545 "Black"}; 546 break; 547 case ColorSpace.TYPE_CMY: 548 compName = new String[] {"Cyan", "Magenta", "Yellow"}; 549 break; 550 default: 551 String [] tmp = new String[numComponents]; 552 for (int i = 0; i < tmp.length; i++) { 553 tmp[i] = "Unnamed color component(" + i + ")"; 554 } 555 compName = tmp; 556 } 557 } 558 return compName[idx]; 559 } 560 561 /** 562 * Returns the minimum normalized color component value for the specified 563 * component. The default implementation in this abstract class returns 0.0 564 * for all components. Subclasses should override this method if necessary. 565 * 566 * @param component the component index 567 * @return the minimum normalized component value 568 * @throws IllegalArgumentException if component is less than 0 or greater 569 * than {@code numComponents - 1} 570 * @since 1.4 571 */ getMinValue(int component)572 public float getMinValue(int component) { 573 rangeCheck(component); 574 return 0.0f; 575 } 576 577 /** 578 * Returns the maximum normalized color component value for the specified 579 * component. The default implementation in this abstract class returns 1.0 580 * for all components. Subclasses should override this method if necessary. 581 * 582 * @param component the component index 583 * @return the maximum normalized component value 584 * @throws IllegalArgumentException if component is less than 0 or greater 585 * than {@code numComponents - 1} 586 * @since 1.4 587 */ getMaxValue(int component)588 public float getMaxValue(int component) { 589 rangeCheck(component); 590 return 1.0f; 591 } 592 593 /** 594 * Checks that {@code component} is in range of the number of components. 595 * 596 * @param component the component index 597 * @throws IllegalArgumentException if component is less than 0 or greater 598 * than {@code numComponents - 1} 599 */ rangeCheck(int component)600 final void rangeCheck(int component) { 601 if (component < 0 || component > getNumComponents() - 1) { 602 throw new IllegalArgumentException( 603 "Component index out of range: " + component); 604 } 605 } 606 } 607