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