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  * &nbsp;   CIEXYZ
  76  * &nbsp;   viewing illuminance: 200 lux
  77  * &nbsp;   viewing white point: CIE D50
  78  * &nbsp;   media white point: "that of a perfectly reflecting diffuser" -- D50
  79  * &nbsp;   media black point: 0 lux or 0 Reflectance
  80  * &nbsp;   flare: 1 percent
  81  * &nbsp;   surround: 20percent of the media white point
  82  * &nbsp;   media description: reflection print (i.e., RLAB, Hunt viewing media)
  83  * &nbsp;   note: For developers creating an ICC profile for this conversion
  84  * &nbsp;         space, the following is applicable. Use a simple Von Kries
  85  * &nbsp;         white point adaptation folded into the 3X3 matrix parameters
  86  * &nbsp;         and fold the flare and surround effects into the three
  87  * &nbsp;         one-dimensional lookup tables (assuming one uses the minimal
  88  * &nbsp;         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      */
 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!
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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 cspace is the XYZspace.
 593      */
 594     static boolean isCS_CIEXYZ(ColorSpace cspace) {
 595         return (cspace == XYZspace);
 596     }
 597 }