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