< prev index next >

src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java

Print this page




   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 sun.java2d.cmm.ColorTransform;
  40 import sun.java2d.cmm.CMSManager;

  41 import sun.java2d.cmm.PCMM;
  42 
  43 
  44 /**































  45  *
  46  * The ICC_ColorSpace class is an implementation of the abstract
  47  * ColorSpace class.  This representation of
  48  * device independent and device dependent color spaces is based on the
  49  * International Color Consortium Specification ICC.1:2001-12, File Format for
  50  * Color Profiles (see <A href="http://www.color.org">http://www.color.org</A>).
  51  * <p>
  52  * Typically, a Color or ColorModel would be associated with an ICC
  53  * Profile which is either an input, display, or output profile (see
  54  * the ICC specification).  There are other types of ICC Profiles, e.g.
  55  * abstract profiles, device link profiles, and named color profiles,
  56  * which do not contain information appropriate for representing the color
  57  * space of a color, image, or device (see ICC_Profile).
  58  * Attempting to create an ICC_ColorSpace object from an inappropriate ICC
  59  * Profile is an error.
  60  * <p>
  61  * ICC Profiles represent transformations from the color space of
  62  * the profile (e.g. a monitor) to a Profile Connection Space (PCS).
  63  * Profiles of interest for tagging images or colors have a
  64  * PCS which is one of the device independent
  65  * spaces (one CIEXYZ space and two CIELab spaces) defined in the
  66  * ICC Profile Format Specification.  Most profiles of interest
  67  * either have invertible transformations or explicitly specify
  68  * transformations going both directions.  Should an ICC_ColorSpace
  69  * object be used in a way requiring a conversion from PCS to
  70  * the profile's native space and there is inadequate data to
  71  * correctly perform the conversion, the ICC_ColorSpace object will
  72  * produce output in the specified type of color space (e.g. TYPE_RGB,
  73  * TYPE_CMYK, etc.), but the specific color values of the output data
  74  * will be undefined.
  75  * <p>
  76  * The details of this class are not important for simple applets,
  77  * which draw in a default color space or manipulate and display
  78  * imported images with a known color space.  At most, such applets
  79  * would need to get one of the default color spaces via
  80  * ColorSpace.getInstance().
  81  * @see ColorSpace
  82  * @see ICC_Profile
  83  */
  84 
  85 
  86 
  87 public class ICC_ColorSpace extends ColorSpace {
  88 
  89     static final long serialVersionUID = 3455889114070431483L;
  90 
  91     private ICC_Profile    thisProfile;
  92     private float[] minVal;
  93     private float[] maxVal;
  94     private float[] diffMinMax;
  95     private float[] invDiffMinMax;
  96     private boolean needScaleInit = true;
  97 
  98     // {to,from}{RGB,CIEXYZ} methods create and cache these when needed
  99     private transient ColorTransform this2srgb;
 100     private transient ColorTransform srgb2this;
 101     private transient ColorTransform this2xyz;
 102     private transient ColorTransform xyz2this;
 103 
 104 
 105     /**
 106     * Constructs a new ICC_ColorSpace from an ICC_Profile object.
 107     * @param profile the specified ICC_Profile object
 108     * @exception IllegalArgumentException if profile is inappropriate for
 109     *            representing a ColorSpace.


 110     */
 111     public ICC_ColorSpace (ICC_Profile profile) {
 112         super (profile.getColorSpaceType(), profile.getNumComponents());
 113 
 114         int profileClass = profile.getProfileClass();
 115 
 116         /* REMIND - is NAMEDCOLOR OK? */
 117         if ((profileClass != ICC_Profile.CLASS_INPUT) &&
 118             (profileClass != ICC_Profile.CLASS_DISPLAY) &&
 119             (profileClass != ICC_Profile.CLASS_OUTPUT) &&
 120             (profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) &&
 121             (profileClass != ICC_Profile.CLASS_NAMEDCOLOR) &&
 122             (profileClass != ICC_Profile.CLASS_ABSTRACT)) {
 123             throw new IllegalArgumentException("Invalid profile type");
 124         }
 125 
 126         thisProfile = profile;
 127         setMinMax();
 128     }
 129 
 130     /**
 131      * Validate an ICC_ColorSpace read from an object input stream
 132      */
 133     private void readObject(java.io.ObjectInputStream s)
 134         throws ClassNotFoundException, java.io.IOException {
 135 
 136         s.defaultReadObject();
 137         if (thisProfile == null) {
 138             thisProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
 139         }
 140     }
 141 
 142     /**
 143     * Returns the ICC_Profile for this ICC_ColorSpace.
 144     * @return the ICC_Profile for this ICC_ColorSpace.

 145     */
 146     public ICC_Profile getProfile() {
 147         return thisProfile;
 148     }
 149 
 150     /**
 151      * Transforms a color value assumed to be in this ColorSpace
 152      * into a value in the default CS_sRGB color space.
 153      * <p>
 154      * This method transforms color values using algorithms designed
 155      * to produce the best perceptual match between input and output
 156      * colors.  In order to do colorimetric conversion of color values,
 157      * you should use the {@code toCIEXYZ}
 158      * method of this color space to first convert from the input
 159      * color space to the CS_CIEXYZ color space, and then use the
 160      * {@code fromCIEXYZ} method of the CS_sRGB color space to
 161      * convert from CS_CIEXYZ to the output color space.
 162      * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
 163      * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
 164      *
 165      * @param colorvalue a float array with length of at least the number
 166      *      of components in this ColorSpace.
 167      * @return a float array of length 3.
 168      * @throws ArrayIndexOutOfBoundsException if array length is not
 169      * at least the number of components in this ColorSpace.
 170      */
 171     public float[]    toRGB (float[] colorvalue) {
 172 
 173         if (this2srgb == null) {
 174             ColorTransform[] transformList = new ColorTransform [2];
 175             ICC_ColorSpace srgbCS =
 176                 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
 177             PCMM mdl = CMSManager.getModule();
 178             transformList[0] = mdl.createTransform(
 179                 thisProfile, ColorTransform.Any, ColorTransform.In);
 180             transformList[1] = mdl.createTransform(
 181                 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
 182             this2srgb = mdl.createTransform(transformList);
 183             if (needScaleInit) {
 184                 setComponentScaling();
 185             }
 186         }
 187 
 188         int nc = this.getNumComponents();
 189         short[] tmp = new short[nc];
 190         for (int i = 0; i < nc; i++) {
 191             tmp[i] = (short)
 192                 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
 193         }
 194         tmp = this2srgb.colorConvert(tmp, null);
 195         float[] result = new float [3];
 196         for (int i = 0; i < 3; i++) {
 197             result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f;
 198         }
 199         return result;
 200     }
 201 
 202     /**
 203      * Transforms a color value assumed to be in the default CS_sRGB
 204      * color space into this ColorSpace.
 205      * <p>
 206      * This method transforms color values using algorithms designed
 207      * to produce the best perceptual match between input and output
 208      * colors.  In order to do colorimetric conversion of color values,
 209      * you should use the {@code toCIEXYZ}
 210      * method of the CS_sRGB color space to first convert from the input
 211      * color space to the CS_CIEXYZ color space, and then use the
 212      * {@code fromCIEXYZ} method of this color space to
 213      * convert from CS_CIEXYZ to the output color space.
 214      * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
 215      * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
 216      *
 217      * @param rgbvalue a float array with length of at least 3.
 218      * @return a float array with length equal to the number of
 219      *       components in this ColorSpace.
 220      * @throws ArrayIndexOutOfBoundsException if array length is not
 221      * at least 3.
 222      */
 223     public float[]    fromRGB(float[] rgbvalue) {
 224 
 225         if (srgb2this == null) {
 226             ColorTransform[] transformList = new ColorTransform [2];
 227             ICC_ColorSpace srgbCS =
 228                 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
 229             PCMM mdl = CMSManager.getModule();
 230             transformList[0] = mdl.createTransform(
 231                 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In);
 232             transformList[1] = mdl.createTransform(
 233                 thisProfile, ColorTransform.Any, ColorTransform.Out);
 234             srgb2this = mdl.createTransform(transformList);
 235             if (needScaleInit) {
 236                 setComponentScaling();
 237             }
 238         }
 239 
 240         short[] tmp = new short[3];
 241         for (int i = 0; i < 3; i++) {
 242             tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f);
 243         }
 244         tmp = srgb2this.colorConvert(tmp, null);
 245         int nc = this.getNumComponents();
 246         float[] result = new float [nc];
 247         for (int i = 0; i < nc; i++) {
 248             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
 249                         diffMinMax[i] + minVal[i];
 250         }
 251         return result;
 252     }
 253 
 254 
 255     /**
 256      * Transforms a color value assumed to be in this ColorSpace
 257      * into the CS_CIEXYZ conversion color space.
 258      * <p>
 259      * This method transforms color values using relative colorimetry,
 260      * as defined by the ICC Specification.  This
 261      * means that the XYZ values returned by this method are represented
 262      * relative to the D50 white point of the CS_CIEXYZ color space.
 263      * This representation is useful in a two-step color conversion
 264      * process in which colors are transformed from an input color
 265      * space to CS_CIEXYZ and then to an output color space.  This
 266      * representation is not the same as the XYZ values that would
 267      * be measured from the given color value by a colorimeter.
 268      * A further transformation is necessary to compute the XYZ values
 269      * that would be measured using current CIE recommended practices.
 270      * The paragraphs below explain this in more detail.
 271      * <p>
 272      * The ICC standard uses a device independent color space (DICS) as the
 273      * mechanism for converting color from one device to another device.  In
 274      * this architecture, colors are converted from the source device's color
 275      * space to the ICC DICS and then from the ICC DICS to the destination
 276      * device's color space.  The ICC standard defines device profiles which
 277      * contain transforms which will convert between a device's color space
 278      * and the ICC DICS.  The overall conversion of colors from a source
 279      * device to colors of a destination device is done by connecting the
 280      * device-to-DICS transform of the profile for the source device to the
 281      * DICS-to-device transform of the profile for the destination device.
 282      * For this reason, the ICC DICS is commonly referred to as the profile
 283      * connection space (PCS).  The color space used in the methods
 284      * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
 285      * Specification.  This is also the color space represented by
 286      * ColorSpace.CS_CIEXYZ.
 287      * <p>
 288      * The XYZ values of a color are often represented as relative to some
 289      * white point, so the actual meaning of the XYZ values cannot be known
 290      * without knowing the white point of those values.  This is known as
 291      * relative colorimetry.  The PCS uses a white point of D50, so the XYZ
 292      * values of the PCS are relative to D50.  For example, white in the PCS
 293      * will have the XYZ values of D50, which is defined to be X=.9642,
 294      * Y=1.000, and Z=0.8249.  This white point is commonly used for graphic
 295      * arts applications, but others are often used in other applications.
 296      * <p>
 297      * To quantify the color characteristics of a device such as a printer
 298      * or monitor, measurements of XYZ values for particular device colors
 299      * are typically made.  For purposes of this discussion, the term
 300      * device XYZ values is used to mean the XYZ values that would be
 301      * measured from device colors using current CIE recommended practices.
 302      * <p>
 303      * Converting between device XYZ values and the PCS XYZ values returned
 304      * by this method corresponds to converting between the device's color
 305      * space, as represented by CIE colorimetric values, and the PCS.  There
 306      * are many factors involved in this process, some of which are quite
 307      * subtle.  The most important, however, is the adjustment made to account
 308      * for differences between the device's white point and the white point of
 309      * the PCS.  There are many techniques for doing this and it is the
 310      * subject of much current research and controversy.  Some commonly used
 311      * methods are XYZ scaling, the von Kries transform, and the Bradford
 312      * transform.  The proper method to use depends upon each particular
 313      * application.
 314      * <p>
 315      * The simplest method is XYZ scaling.  In this method each device XYZ
 316      * value is  converted to a PCS XYZ value by multiplying it by the ratio
 317      * of the PCS white point (D50) to the device white point.
 318      * <pre>
 319      *
 320      * Xd, Yd, Zd are the device XYZ values
 321      * Xdw, Ydw, Zdw are the device XYZ white point values
 322      * Xp, Yp, Zp are the PCS XYZ values
 323      * Xd50, Yd50, Zd50 are the PCS XYZ white point values
 324      *
 325      * Xp = Xd * (Xd50 / Xdw)
 326      * Yp = Yd * (Yd50 / Ydw)
 327      * Zp = Zd * (Zd50 / Zdw)
 328      *
 329      * </pre>
 330      * <p>
 331      * Conversion from the PCS to the device would be done by inverting these
 332      * equations:
 333      * <pre>
 334      *
 335      * Xd = Xp * (Xdw / Xd50)
 336      * Yd = Yp * (Ydw / Yd50)
 337      * Zd = Zp * (Zdw / Zd50)
 338      *
 339      * </pre>
 340      * <p>
 341      * Note that the media white point tag in an ICC profile is not the same
 342      * as the device white point.  The media white point tag is expressed in
 343      * PCS values and is used to represent the difference between the XYZ of
 344      * device illuminant and the XYZ of the device media when measured under
 345      * that illuminant.  The device white point is expressed as the device
 346      * XYZ values corresponding to white displayed on the device.  For
 347      * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
 348      * will result in a measured device XYZ value of D65.  This will not
 349      * be the same as the media white point tag XYZ value in the ICC
 350      * profile for an sRGB device.
 351      *
 352      * @param colorvalue a float array with length of at least the number
 353      *        of components in this ColorSpace.
 354      * @return a float array of length 3.
 355      * @throws ArrayIndexOutOfBoundsException if array length is not
 356      * at least the number of components in this ColorSpace.
 357      */
 358     public float[]    toCIEXYZ(float[] colorvalue) {
 359 
 360         if (this2xyz == null) {
 361             ColorTransform[] transformList = new ColorTransform [2];
 362             ICC_ColorSpace xyzCS =
 363                 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
 364             PCMM mdl = CMSManager.getModule();
 365             try {
 366                 transformList[0] = mdl.createTransform(
 367                     thisProfile, ICC_Profile.icRelativeColorimetric,
 368                     ColorTransform.In);
 369             } catch (CMMException e) {
 370                 transformList[0] = mdl.createTransform(
 371                     thisProfile, ColorTransform.Any, ColorTransform.In);
 372             }
 373             transformList[1] = mdl.createTransform(
 374                 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
 375             this2xyz = mdl.createTransform (transformList);
 376             if (needScaleInit) {
 377                 setComponentScaling();
 378             }
 379         }
 380 
 381         int nc = this.getNumComponents();
 382         short[] tmp = new short[nc];
 383         for (int i = 0; i < nc; i++) {
 384             tmp[i] = (short)
 385                 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
 386         }
 387         tmp = this2xyz.colorConvert(tmp, null);
 388         float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
 389         // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
 390         float[] result = new float [3];
 391         for (int i = 0; i < 3; i++) {
 392             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO;
 393         }
 394         return result;
 395     }
 396 
 397 
 398     /**
 399      * Transforms a color value assumed to be in the CS_CIEXYZ conversion
 400      * color space into this ColorSpace.
 401      * <p>
 402      * This method transforms color values using relative colorimetry,
 403      * as defined by the ICC Specification.  This
 404      * means that the XYZ argument values taken by this method are represented
 405      * relative to the D50 white point of the CS_CIEXYZ color space.
 406      * This representation is useful in a two-step color conversion
 407      * process in which colors are transformed from an input color
 408      * space to CS_CIEXYZ and then to an output color space.  The color
 409      * values returned by this method are not those that would produce
 410      * the XYZ value passed to the method when measured by a colorimeter.
 411      * If you have XYZ values corresponding to measurements made using
 412      * current CIE recommended practices, they must be converted to D50
 413      * relative values before being passed to this method.
 414      * The paragraphs below explain this in more detail.
 415      * <p>
 416      * The ICC standard uses a device independent color space (DICS) as the
 417      * mechanism for converting color from one device to another device.  In
 418      * this architecture, colors are converted from the source device's color
 419      * space to the ICC DICS and then from the ICC DICS to the destination
 420      * device's color space.  The ICC standard defines device profiles which
 421      * contain transforms which will convert between a device's color space
 422      * and the ICC DICS.  The overall conversion of colors from a source
 423      * device to colors of a destination device is done by connecting the
 424      * device-to-DICS transform of the profile for the source device to the
 425      * DICS-to-device transform of the profile for the destination device.
 426      * For this reason, the ICC DICS is commonly referred to as the profile
 427      * connection space (PCS).  The color space used in the methods
 428      * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
 429      * Specification.  This is also the color space represented by
 430      * ColorSpace.CS_CIEXYZ.
 431      * <p>
 432      * The XYZ values of a color are often represented as relative to some
 433      * white point, so the actual meaning of the XYZ values cannot be known
 434      * without knowing the white point of those values.  This is known as
 435      * relative colorimetry.  The PCS uses a white point of D50, so the XYZ
 436      * values of the PCS are relative to D50.  For example, white in the PCS
 437      * will have the XYZ values of D50, which is defined to be X=.9642,
 438      * Y=1.000, and Z=0.8249.  This white point is commonly used for graphic
 439      * arts applications, but others are often used in other applications.
 440      * <p>
 441      * To quantify the color characteristics of a device such as a printer
 442      * or monitor, measurements of XYZ values for particular device colors
 443      * are typically made.  For purposes of this discussion, the term
 444      * device XYZ values is used to mean the XYZ values that would be
 445      * measured from device colors using current CIE recommended practices.
 446      * <p>
 447      * Converting between device XYZ values and the PCS XYZ values taken as
 448      * arguments by this method corresponds to converting between the device's
 449      * color space, as represented by CIE colorimetric values, and the PCS.
 450      * There are many factors involved in this process, some of which are quite
 451      * subtle.  The most important, however, is the adjustment made to account
 452      * for differences between the device's white point and the white point of
 453      * the PCS.  There are many techniques for doing this and it is the
 454      * subject of much current research and controversy.  Some commonly used
 455      * methods are XYZ scaling, the von Kries transform, and the Bradford
 456      * transform.  The proper method to use depends upon each particular
 457      * application.
 458      * <p>
 459      * The simplest method is XYZ scaling.  In this method each device XYZ
 460      * value is  converted to a PCS XYZ value by multiplying it by the ratio
 461      * of the PCS white point (D50) to the device white point.
 462      * <pre>
 463      *
 464      * Xd, Yd, Zd are the device XYZ values
 465      * Xdw, Ydw, Zdw are the device XYZ white point values
 466      * Xp, Yp, Zp are the PCS XYZ values
 467      * Xd50, Yd50, Zd50 are the PCS XYZ white point values
 468      *
 469      * Xp = Xd * (Xd50 / Xdw)
 470      * Yp = Yd * (Yd50 / Ydw)
 471      * Zp = Zd * (Zd50 / Zdw)
 472      *
 473      * </pre>
 474      * <p>
 475      * Conversion from the PCS to the device would be done by inverting these
 476      * equations:
 477      * <pre>
 478      *
 479      * Xd = Xp * (Xdw / Xd50)
 480      * Yd = Yp * (Ydw / Yd50)
 481      * Zd = Zp * (Zdw / Zd50)
 482      *
 483      * </pre>
 484      * <p>
 485      * Note that the media white point tag in an ICC profile is not the same
 486      * as the device white point.  The media white point tag is expressed in
 487      * PCS values and is used to represent the difference between the XYZ of
 488      * device illuminant and the XYZ of the device media when measured under
 489      * that illuminant.  The device white point is expressed as the device
 490      * XYZ values corresponding to white displayed on the device.  For
 491      * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
 492      * will result in a measured device XYZ value of D65.  This will not
 493      * be the same as the media white point tag XYZ value in the ICC
 494      * profile for an sRGB device.
 495      *
 496      * @param colorvalue a float array with length of at least 3.
 497      * @return a float array with length equal to the number of
 498      *         components in this ColorSpace.
 499      * @throws ArrayIndexOutOfBoundsException if array length is not
 500      * at least 3.
 501      */
 502     public float[]    fromCIEXYZ(float[] colorvalue) {
 503 
 504         if (xyz2this == null) {
 505             ColorTransform[] transformList = new ColorTransform [2];
 506             ICC_ColorSpace xyzCS =
 507                 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
 508             PCMM mdl = CMSManager.getModule();
 509             transformList[0] = mdl.createTransform (
 510                 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In);
 511             try {
 512                 transformList[1] = mdl.createTransform(
 513                     thisProfile, ICC_Profile.icRelativeColorimetric,
 514                     ColorTransform.Out);
 515             } catch (CMMException e) {
 516                 transformList[1] = CMSManager.getModule().createTransform(
 517                 thisProfile, ColorTransform.Any, ColorTransform.Out);
 518             }
 519             xyz2this = mdl.createTransform(transformList);
 520             if (needScaleInit) {


 523         }
 524 
 525         short[] tmp = new short[3];
 526         float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
 527         float factor = 65535.0f / ALMOST_TWO;
 528         // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
 529         for (int i = 0; i < 3; i++) {
 530             tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f);
 531         }
 532         tmp = xyz2this.colorConvert(tmp, null);
 533         int nc = this.getNumComponents();
 534         float[] result = new float [nc];
 535         for (int i = 0; i < nc; i++) {
 536             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
 537                         diffMinMax[i] + minVal[i];
 538         }
 539         return result;
 540     }
 541 
 542     /**
 543      * Returns the minimum normalized color component value for the
 544      * specified component.  For TYPE_XYZ spaces, this method returns
 545      * minimum values of 0.0 for all components.  For TYPE_Lab spaces,
 546      * this method returns 0.0 for L and -128.0 for a and b components.
 547      * This is consistent with the encoding of the XYZ and Lab Profile
 548      * Connection Spaces in the ICC specification.  For all other types, this
 549      * method returns 0.0 for all components.  When using an ICC_ColorSpace
 550      * with a profile that requires different minimum component values,
 551      * it is necessary to subclass this class and override this method.
 552      * @param component The component index.
 553      * @return The minimum normalized component value.
 554      * @throws IllegalArgumentException if component is less than 0 or
 555      *         greater than numComponents - 1.

 556      * @since 1.4
 557      */
 558     public float getMinValue(int component) {
 559         if ((component < 0) || (component > this.getNumComponents() - 1)) {
 560             throw new IllegalArgumentException(
 561                 "Component index out of range: " + component);
 562         }
 563         return minVal[component];
 564     }
 565 
 566     /**
 567      * Returns the maximum normalized color component value for the
 568      * specified component.  For TYPE_XYZ spaces, this method returns
 569      * maximum values of 1.0 + (32767.0 / 32768.0) for all components.
 570      * For TYPE_Lab spaces,
 571      * this method returns 100.0 for L and 127.0 for a and b components.
 572      * This is consistent with the encoding of the XYZ and Lab Profile
 573      * Connection Spaces in the ICC specification.  For all other types, this
 574      * method returns 1.0 for all components.  When using an ICC_ColorSpace
 575      * with a profile that requires different maximum component values,
 576      * it is necessary to subclass this class and override this method.
 577      * @param component The component index.
 578      * @return The maximum normalized component value.
 579      * @throws IllegalArgumentException if component is less than 0 or
 580      *         greater than numComponents - 1.

 581      * @since 1.4
 582      */
 583     public float getMaxValue(int component) {
 584         if ((component < 0) || (component > this.getNumComponents() - 1)) {
 585             throw new IllegalArgumentException(
 586                 "Component index out of range: " + component);
 587         }
 588         return maxVal[component];
 589     }
 590 
 591     private void setMinMax() {
 592         int nc = this.getNumComponents();
 593         int type = this.getType();
 594         minVal = new float[nc];
 595         maxVal = new float[nc];
 596         if (type == ColorSpace.TYPE_Lab) {
 597             minVal[0] = 0.0f;    // L
 598             maxVal[0] = 100.0f;
 599             minVal[1] = -128.0f; // a
 600             maxVal[1] = 127.0f;




   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 sun.java2d.cmm.CMSManager;
  39 import sun.java2d.cmm.ColorTransform;
  40 import sun.java2d.cmm.PCMM;
  41 

  42 /**
  43  * The {@code ICC_ColorSpace} class is an implementation of the abstract
  44  * {@code ColorSpace} class. This representation of device independent and
  45  * device dependent color spaces is based on the International Color Consortium
  46  * Specification ICC.1:2001-12, File Format for Color Profiles (see
  47  * <a href="http://www.color.org">http://www.color.org</a>).
  48  * <p>
  49  * Typically, a {@code Color} or {@code ColorModel} would be associated with an
  50  * ICC Profile which is either an input, display, or output profile (see the ICC
  51  * specification). There are other types of ICC Profiles, e.g. abstract
  52  * profiles, device link profiles, and named color profiles, which do not
  53  * contain information appropriate for representing the color space of a color,
  54  * image, or device (see {@code ICC_Profile}). Attempting to create an
  55  * {@code ICC_ColorSpace} object from an inappropriate ICC Profile is an error.
  56  * <p>
  57  * ICC Profiles represent transformations from the color space of the profile
  58  * (e.g. a monitor) to a Profile Connection Space (PCS). Profiles of interest
  59  * for tagging images or colors have a PCS which is one of the device
  60  * independent spaces (one CIEXYZ space and two CIELab spaces) defined in the
  61  * ICC Profile Format Specification. Most profiles of interest either have
  62  * invertible transformations or explicitly specify transformations going both
  63  * directions. Should an {@code ICC_ColorSpace} object be used in a way
  64  * requiring a conversion from PCS to the profile's native space and there is
  65  * inadequate data to correctly perform the conversion, the
  66  * {@code ICC_ColorSpace} object will produce output in the specified type of
  67  * color space (e.g. {@code TYPE_RGB}, {@code TYPE_CMYK}, etc.), but the
  68  * specific color values of the output data will be undefined.
  69  * <p>
  70  * The details of this class are not important for simple applets, which draw in
  71  * a default color space or manipulate and display imported images with a known
  72  * color space. At most, such applets would need to get one of the default color
  73  * spaces via {@link ColorSpace#getInstance}.
  74  *



































  75  * @see ColorSpace
  76  * @see ICC_Profile
  77  */



  78 public class ICC_ColorSpace extends ColorSpace {
  79 
  80     static final long serialVersionUID = 3455889114070431483L;
  81 
  82     private ICC_Profile    thisProfile;
  83     private float[] minVal;
  84     private float[] maxVal;
  85     private float[] diffMinMax;
  86     private float[] invDiffMinMax;
  87     private boolean needScaleInit = true;
  88 
  89     // {to,from}{RGB,CIEXYZ} methods create and cache these when needed
  90     private transient ColorTransform this2srgb;
  91     private transient ColorTransform srgb2this;
  92     private transient ColorTransform this2xyz;
  93     private transient ColorTransform xyz2this;
  94 

  95     /**
  96      * Constructs a new {@code ICC_ColorSpace} from an {@code ICC_Profile}
  97      * object.
  98      *
  99      * @param  profile the specified {@code ICC_Profile} object
 100      * @throws IllegalArgumentException if profile is inappropriate for
 101      *         representing a {@code ColorSpace}
 102      */
 103     public ICC_ColorSpace (ICC_Profile profile) {
 104         super (profile.getColorSpaceType(), profile.getNumComponents());
 105 
 106         int profileClass = profile.getProfileClass();
 107 
 108         /* REMIND - is NAMEDCOLOR OK? */
 109         if ((profileClass != ICC_Profile.CLASS_INPUT) &&
 110             (profileClass != ICC_Profile.CLASS_DISPLAY) &&
 111             (profileClass != ICC_Profile.CLASS_OUTPUT) &&
 112             (profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) &&
 113             (profileClass != ICC_Profile.CLASS_NAMEDCOLOR) &&
 114             (profileClass != ICC_Profile.CLASS_ABSTRACT)) {
 115             throw new IllegalArgumentException("Invalid profile type");
 116         }
 117 
 118         thisProfile = profile;
 119         setMinMax();
 120     }
 121 
 122     /**
 123      * Validate an ICC_ColorSpace read from an object input stream
 124      */
 125     private void readObject(java.io.ObjectInputStream s)
 126         throws ClassNotFoundException, java.io.IOException {
 127 
 128         s.defaultReadObject();
 129         if (thisProfile == null) {
 130             thisProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB);
 131         }
 132     }
 133 
 134     /**
 135      * Returns the {@code ICC_Profile} for this {@code ICC_ColorSpace}.
 136      *
 137      * @return the {@code ICC_Profile} for this {@code ICC_ColorSpace}
 138      */
 139     public ICC_Profile getProfile() {
 140         return thisProfile;
 141     }
 142 
 143     /**
 144      * Transforms a color value assumed to be in this {@code ColorSpace} into a
 145      * value in the default {@code CS_sRGB} color space.
 146      * <p>
 147      * This method transforms color values using algorithms designed to produce
 148      * the best perceptual match between input and output colors. In order to do
 149      * colorimetric conversion of color values, you should use the
 150      * {@code toCIEXYZ} method of this color space to first convert from the
 151      * input color space to the {@code CS_CIEXYZ} color space, and then use the
 152      * {@code fromCIEXYZ} method of the {@code CS_sRGB} color space to convert
 153      * from {@code CS_CIEXYZ} to the output color space. See
 154      * {@link #toCIEXYZ(float[]) toCIEXYZ} and

 155      * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
 156      *
 157      * @param  colorvalue a float array with length of at least the number of
 158      *         components in this {@code ColorSpace}
 159      * @return a float array of length 3
 160      * @throws ArrayIndexOutOfBoundsException if array length is not at least
 161      *         the number of components in this {@code ColorSpace}
 162      */
 163     public float[]    toRGB (float[] colorvalue) {
 164 
 165         if (this2srgb == null) {
 166             ColorTransform[] transformList = new ColorTransform [2];
 167             ICC_ColorSpace srgbCS =
 168                 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
 169             PCMM mdl = CMSManager.getModule();
 170             transformList[0] = mdl.createTransform(
 171                 thisProfile, ColorTransform.Any, ColorTransform.In);
 172             transformList[1] = mdl.createTransform(
 173                 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
 174             this2srgb = mdl.createTransform(transformList);
 175             if (needScaleInit) {
 176                 setComponentScaling();
 177             }
 178         }
 179 
 180         int nc = this.getNumComponents();
 181         short[] tmp = new short[nc];
 182         for (int i = 0; i < nc; i++) {
 183             tmp[i] = (short)
 184                 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
 185         }
 186         tmp = this2srgb.colorConvert(tmp, null);
 187         float[] result = new float [3];
 188         for (int i = 0; i < 3; i++) {
 189             result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f;
 190         }
 191         return result;
 192     }
 193 
 194     /**
 195      * Transforms a color value assumed to be in the default {@code CS_sRGB}
 196      * color space into this {@code ColorSpace}.
 197      * <p>
 198      * This method transforms color values using algorithms designed to produce
 199      * the best perceptual match between input and output colors. In order to do
 200      * colorimetric conversion of color values, you should use the
 201      * {@code toCIEXYZ} method of the {@code CS_sRGB} color space to first
 202      * convert from the input color space to the {@code CS_CIEXYZ} color space,
 203      * and then use the {@code fromCIEXYZ} method of this color space to convert
 204      * from {@code CS_CIEXYZ} to the output color space. See
 205      * {@link #toCIEXYZ(float[]) toCIEXYZ} and

 206      * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
 207      *
 208      * @param  rgbvalue a float array with length of at least 3
 209      * @return a float array with length equal to the number of components in
 210      *         this {@code ColorSpace}
 211      * @throws ArrayIndexOutOfBoundsException if array length is not at least 3

 212      */
 213     public float[]    fromRGB(float[] rgbvalue) {
 214 
 215         if (srgb2this == null) {
 216             ColorTransform[] transformList = new ColorTransform [2];
 217             ICC_ColorSpace srgbCS =
 218                 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
 219             PCMM mdl = CMSManager.getModule();
 220             transformList[0] = mdl.createTransform(
 221                 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In);
 222             transformList[1] = mdl.createTransform(
 223                 thisProfile, ColorTransform.Any, ColorTransform.Out);
 224             srgb2this = mdl.createTransform(transformList);
 225             if (needScaleInit) {
 226                 setComponentScaling();
 227             }
 228         }
 229 
 230         short[] tmp = new short[3];
 231         for (int i = 0; i < 3; i++) {
 232             tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f);
 233         }
 234         tmp = srgb2this.colorConvert(tmp, null);
 235         int nc = this.getNumComponents();
 236         float[] result = new float [nc];
 237         for (int i = 0; i < nc; i++) {
 238             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
 239                         diffMinMax[i] + minVal[i];
 240         }
 241         return result;
 242     }
 243 

 244     /**
 245      * Transforms a color value assumed to be in this {@code ColorSpace} into
 246      * the {@code CS_CIEXYZ} conversion color space.
 247      * <p>
 248      * This method transforms color values using relative colorimetry, as
 249      * defined by the ICC Specification. This means that the XYZ values returned
 250      * by this method are represented relative to the D50 white point of the
 251      * {@code CS_CIEXYZ} color space. This representation is useful in a
 252      * two-step color conversion process in which colors are transformed from an
 253      * input color space to {@code CS_CIEXYZ} and then to an output color space.
 254      * This representation is not the same as the XYZ values that would be
 255      * measured from the given color value by a colorimeter. A further
 256      * transformation is necessary to compute the XYZ values that would be
 257      * measured using current CIE recommended practices. The paragraphs below
 258      * explain this in more detail.

 259      * <p>
 260      * The ICC standard uses a device independent color space (DICS) as the
 261      * mechanism for converting color from one device to another device. In this
 262      * architecture, colors are converted from the source device's color space
 263      * to the ICC DICS and then from the ICC DICS to the destination device's
 264      * color space. The ICC standard defines device profiles which contain
 265      * transforms which will convert between a device's color space and the ICC
 266      * DICS. The overall conversion of colors from a source device to colors of
 267      * a destination device is done by connecting the device-to-DICS transform
 268      * of the profile for the source device to the DICS-to-device transform of
 269      * the profile for the destination device. For this reason, the ICC DICS is
 270      * commonly referred to as the profile connection space (PCS). The color
 271      * space used in the methods {@code toCIEXYZ} and {@code fromCIEXYZ} is the
 272      * CIEXYZ PCS defined by the ICC Specification. This is also the color space
 273      * represented by {@code ColorSpace.CS_CIEXYZ}.
 274      * <p>
 275      * The XYZ values of a color are often represented as relative to some white
 276      * point, so the actual meaning of the XYZ values cannot be known without
 277      * knowing the white point of those values. This is known as relative
 278      * colorimetry. The PCS uses a white point of D50, so the XYZ values of the
 279      * PCS are relative to D50. For example, white in the PCS will have the XYZ
 280      * values of D50, which is defined to be X=.9642, Y=1.000, and Z=0.8249.
 281      * This white point is commonly used for graphic arts applications, but
 282      * others are often used in other applications.
 283      * <p>
 284      * To quantify the color characteristics of a device such as a printer or
 285      * monitor, measurements of XYZ values for particular device colors are
 286      * typically made. For purposes of this discussion, the term device XYZ
 287      * values is used to mean the XYZ values that would be measured from device
 288      * colors using current CIE recommended practices.
 289      * <p>
 290      * Converting between device XYZ values and the PCS XYZ values returned by
 291      * this method corresponds to converting between the device's color space,
 292      * as represented by CIE colorimetric values, and the PCS. There are many
 293      * factors involved in this process, some of which are quite subtle. The
 294      * most important, however, is the adjustment made to account for
 295      * differences between the device's white point and the white point of the
 296      * PCS. There are many techniques for doing this and it is the subject of
 297      * much current research and controversy. Some commonly used methods are XYZ
 298      * scaling, the von Kries transform, and the Bradford transform. The proper
 299      * method to use depends upon each particular application.
 300      * <p>
 301      * The simplest method is XYZ scaling. In this method each device XYZ value
 302      * is converted to a PCS XYZ value by multiplying it by the ratio of the PCS
 303      * white point (D50) to the device white point.


 304      * <pre>
 305      *
 306      * Xd, Yd, Zd are the device XYZ values
 307      * Xdw, Ydw, Zdw are the device XYZ white point values
 308      * Xp, Yp, Zp are the PCS XYZ values
 309      * Xd50, Yd50, Zd50 are the PCS XYZ white point values
 310      *
 311      * Xp = Xd * (Xd50 / Xdw)
 312      * Yp = Yd * (Yd50 / Ydw)
 313      * Zp = Zd * (Zd50 / Zdw)
 314      *
 315      * </pre>
 316      * <p>
 317      * Conversion from the PCS to the device would be done by inverting these
 318      * equations:
 319      * <pre>
 320      *
 321      * Xd = Xp * (Xdw / Xd50)
 322      * Yd = Yp * (Ydw / Yd50)
 323      * Zd = Zp * (Zdw / Zd50)
 324      *
 325      * </pre>
 326      * <p>
 327      * Note that the media white point tag in an ICC profile is not the same as
 328      * the device white point. The media white point tag is expressed in PCS
 329      * values and is used to represent the difference between the XYZ of device
 330      * illuminant and the XYZ of the device media when measured under that
 331      * illuminant. The device white point is expressed as the device XYZ values
 332      * corresponding to white displayed on the device. For example, displaying
 333      * the RGB color (1.0, 1.0, 1.0) on an sRGB device will result in a measured
 334      * device XYZ value of D65. This will not be the same as the media white
 335      * point tag XYZ value in the ICC profile for an sRGB device.
 336      *
 337      * @param  colorvalue a float array with length of at least the number of
 338      *         components in this {@code ColorSpace}
 339      * @return a float array of length 3
 340      * @throws ArrayIndexOutOfBoundsException if array length is not at least
 341      *         the number of components in this {@code ColorSpace}

 342      */
 343     public float[]    toCIEXYZ(float[] colorvalue) {
 344 
 345         if (this2xyz == null) {
 346             ColorTransform[] transformList = new ColorTransform [2];
 347             ICC_ColorSpace xyzCS =
 348                 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
 349             PCMM mdl = CMSManager.getModule();
 350             try {
 351                 transformList[0] = mdl.createTransform(
 352                     thisProfile, ICC_Profile.icRelativeColorimetric,
 353                     ColorTransform.In);
 354             } catch (CMMException e) {
 355                 transformList[0] = mdl.createTransform(
 356                     thisProfile, ColorTransform.Any, ColorTransform.In);
 357             }
 358             transformList[1] = mdl.createTransform(
 359                 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
 360             this2xyz = mdl.createTransform (transformList);
 361             if (needScaleInit) {
 362                 setComponentScaling();
 363             }
 364         }
 365 
 366         int nc = this.getNumComponents();
 367         short[] tmp = new short[nc];
 368         for (int i = 0; i < nc; i++) {
 369             tmp[i] = (short)
 370                 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
 371         }
 372         tmp = this2xyz.colorConvert(tmp, null);
 373         float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
 374         // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
 375         float[] result = new float [3];
 376         for (int i = 0; i < 3; i++) {
 377             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO;
 378         }
 379         return result;
 380     }
 381 

 382     /**
 383      * Transforms a color value assumed to be in the {@code CS_CIEXYZ}
 384      * conversion color space into this ColorSpace.
 385      * <p>
 386      * This method transforms color values using relative colorimetry, as
 387      * defined by the ICC Specification. This means that the XYZ argument values
 388      * taken by this method are represented relative to the D50 white point of
 389      * the {@code CS_CIEXYZ} color space. This representation is useful in a
 390      * two-step color conversion process in which colors are transformed from an
 391      * input color space to {@code CS_CIEXYZ} and then to an output color space.
 392      * The color values returned by this method are not those that would produce
 393      * the XYZ value passed to the method when measured by a colorimeter. If you
 394      * have XYZ values corresponding to measurements made using current CIE
 395      * recommended practices, they must be converted to D50 relative values
 396      * before being passed to this method. The paragraphs below explain this in
 397      * more detail.

 398      * <p>
 399      * The ICC standard uses a device independent color space (DICS) as the
 400      * mechanism for converting color from one device to another device. In this
 401      * architecture, colors are converted from the source device's color space
 402      * to the ICC DICS and then from the ICC DICS to the destination device's
 403      * color space. The ICC standard defines device profiles which contain
 404      * transforms which will convert between a device's color space and the ICC
 405      * DICS. The overall conversion of colors from a source device to colors of
 406      * a destination device is done by connecting the device-to-DICS transform
 407      * of the profile for the source device to the DICS-to-device transform of
 408      * the profile for the destination device. For this reason, the ICC DICS is
 409      * commonly referred to as the profile connection space (PCS). The color
 410      * space used in the methods {@code toCIEXYZ} and {@code fromCIEXYZ} is the
 411      * CIEXYZ PCS defined by the ICC Specification. This is also the color space
 412      * represented by {@code ColorSpace.CS_CIEXYZ}.
 413      * <p>
 414      * The XYZ values of a color are often represented as relative to some white
 415      * point, so the actual meaning of the XYZ values cannot be known without
 416      * knowing the white point of those values. This is known as relative
 417      * colorimetry. The PCS uses a white point of D50, so the XYZ values of the
 418      * PCS are relative to D50. For example, white in the PCS will have the XYZ
 419      * values of D50, which is defined to be X=.9642, Y=1.000, and Z=0.8249.
 420      * This white point is commonly used for graphic arts applications, but
 421      * others are often used in other applications.
 422      * <p>
 423      * To quantify the color characteristics of a device such as a printer or
 424      * monitor, measurements of XYZ values for particular device colors are
 425      * typically made. For purposes of this discussion, the term device XYZ
 426      * values is used to mean the XYZ values that would be measured from device
 427      * colors using current CIE recommended practices.

 428      * <p>
 429      * Converting between device XYZ values and the PCS XYZ values taken as
 430      * arguments by this method corresponds to converting between the device's
 431      * color space, as represented by CIE colorimetric values, and the PCS.
 432      * There are many factors involved in this process, some of which are quite
 433      * subtle. The most important, however, is the adjustment made to account
 434      * for differences between the device's white point and the white point of
 435      * the PCS. There are many techniques for doing this and it is the subject
 436      * of much current research and controversy. Some commonly used methods are
 437      * XYZ scaling, the von Kries transform, and the Bradford transform. The
 438      * proper method to use depends upon each particular application.
 439      * <p>
 440      * The simplest method is XYZ scaling. In this method each device XYZ value
 441      * is converted to a PCS XYZ value by multiplying it by the ratio of the PCS
 442      * white point (D50) to the device white point.

 443      * <pre>
 444      *
 445      * Xd, Yd, Zd are the device XYZ values
 446      * Xdw, Ydw, Zdw are the device XYZ white point values
 447      * Xp, Yp, Zp are the PCS XYZ values
 448      * Xd50, Yd50, Zd50 are the PCS XYZ white point values
 449      *
 450      * Xp = Xd * (Xd50 / Xdw)
 451      * Yp = Yd * (Yd50 / Ydw)
 452      * Zp = Zd * (Zd50 / Zdw)
 453      *
 454      * </pre>
 455      * <p>
 456      * Conversion from the PCS to the device would be done by inverting these
 457      * equations:
 458      * <pre>
 459      *
 460      * Xd = Xp * (Xdw / Xd50)
 461      * Yd = Yp * (Ydw / Yd50)
 462      * Zd = Zp * (Zdw / Zd50)
 463      *
 464      * </pre>
 465      * <p>
 466      * Note that the media white point tag in an ICC profile is not the same as
 467      * the device white point. The media white point tag is expressed in PCS
 468      * values and is used to represent the difference between the XYZ of device
 469      * illuminant and the XYZ of the device media when measured under that
 470      * illuminant. The device white point is expressed as the device XYZ values
 471      * corresponding to white displayed on the device. For example, displaying
 472      * the RGB color (1.0, 1.0, 1.0) on an sRGB device will result in a measured
 473      * device XYZ value of D65. This will not be the same as the media white
 474      * point tag XYZ value in the ICC profile for an sRGB device.
 475      *
 476      * @param  colorvalue a float array with length of at least 3
 477      * @return a float array with length equal to the number of components in
 478      *         this {@code ColorSpace}
 479      * @throws ArrayIndexOutOfBoundsException if array length is not at least 3


 480      */
 481     public float[]    fromCIEXYZ(float[] colorvalue) {
 482 
 483         if (xyz2this == null) {
 484             ColorTransform[] transformList = new ColorTransform [2];
 485             ICC_ColorSpace xyzCS =
 486                 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
 487             PCMM mdl = CMSManager.getModule();
 488             transformList[0] = mdl.createTransform (
 489                 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In);
 490             try {
 491                 transformList[1] = mdl.createTransform(
 492                     thisProfile, ICC_Profile.icRelativeColorimetric,
 493                     ColorTransform.Out);
 494             } catch (CMMException e) {
 495                 transformList[1] = CMSManager.getModule().createTransform(
 496                 thisProfile, ColorTransform.Any, ColorTransform.Out);
 497             }
 498             xyz2this = mdl.createTransform(transformList);
 499             if (needScaleInit) {


 502         }
 503 
 504         short[] tmp = new short[3];
 505         float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
 506         float factor = 65535.0f / ALMOST_TWO;
 507         // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
 508         for (int i = 0; i < 3; i++) {
 509             tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f);
 510         }
 511         tmp = xyz2this.colorConvert(tmp, null);
 512         int nc = this.getNumComponents();
 513         float[] result = new float [nc];
 514         for (int i = 0; i < nc; i++) {
 515             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
 516                         diffMinMax[i] + minVal[i];
 517         }
 518         return result;
 519     }
 520 
 521     /**
 522      * Returns the minimum normalized color component value for the specified
 523      * component. For {@code TYPE_XYZ} spaces, this method returns minimum
 524      * values of 0.0 for all components. For {@code TYPE_Lab} spaces, this
 525      * method returns 0.0 for L and -128.0 for a and b components. This is
 526      * consistent with the encoding of the XYZ and Lab Profile Connection Spaces
 527      * in the ICC specification. For all other types, this method returns 0.0
 528      * for all components. When using an {@code ICC_ColorSpace} with a profile
 529      * that requires different minimum component values, it is necessary to
 530      * subclass this class and override this method.
 531      *
 532      * @param  component the component index
 533      * @return the minimum normalized component value
 534      * @throws IllegalArgumentException if component is less than 0 or greater
 535      *         than {@code numComponents - 1}
 536      * @since 1.4
 537      */
 538     public float getMinValue(int component) {
 539         if ((component < 0) || (component > this.getNumComponents() - 1)) {
 540             throw new IllegalArgumentException(
 541                 "Component index out of range: " + component);
 542         }
 543         return minVal[component];
 544     }
 545 
 546     /**
 547      * Returns the maximum normalized color component value for the specified
 548      * component. For {@code TYPE_XYZ} spaces, this method returns maximum
 549      * values of 1.0 + (32767.0 / 32768.0) for all components. For
 550      * {@code TYPE_Lab} spaces, this method returns 100.0 for L and 127.0 for a
 551      * and b components. This is consistent with the encoding of the XYZ and Lab
 552      * Profile Connection Spaces in the ICC specification. For all other types,
 553      * this method returns 1.0 for all components. When using an
 554      * {@code ICC_ColorSpace} with a profile that requires different maximum
 555      * component values, it is necessary to subclass this class and override
 556      * this method.
 557      *
 558      * @param  component the component index
 559      * @return the maximum 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 getMaxValue(int component) {
 565         if ((component < 0) || (component > this.getNumComponents() - 1)) {
 566             throw new IllegalArgumentException(
 567                 "Component index out of range: " + component);
 568         }
 569         return maxVal[component];
 570     }
 571 
 572     private void setMinMax() {
 573         int nc = this.getNumComponents();
 574         int type = this.getType();
 575         minVal = new float[nc];
 576         maxVal = new float[nc];
 577         if (type == ColorSpace.TYPE_Lab) {
 578             minVal[0] = 0.0f;    // L
 579             maxVal[0] = 100.0f;
 580             minVal[1] = -128.0f; // a
 581             maxVal[1] = 127.0f;


< prev index next >