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