home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Internet / Javadraw / DATA.Z / Color.java < prev    next >
Text File  |  1997-08-30  |  21KB  |  604 lines

  1. /*
  2.  * @(#)Color.java    1.31 97/06/24
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22. package java.awt;
  23.  
  24. import java.io.*;
  25. import java.lang.*;
  26.  
  27. /**
  28.  * This class encapsulates colors using the RGB format. In RGB 
  29.  * format, the red, blue, and green components of a color are each 
  30.  * represented by an integer in the range 0-255. The value 0 
  31.  * indicates no contribution from this primary color. The value 255 
  32.  * indicates the maximum intensity of this color component. 
  33.  * <p>
  34.  * Although the <code>Color</code> class is based on the 
  35.  * three-component RGB model, the class provides a set of convenience 
  36.  * methods for converting between RGB and HSB colors. For a 
  37.  * definition of the RGB and HSB color models, see Foley, van Dam, 
  38.  * Feiner, and Hughes, <cite>Computer Graphics: Principles 
  39.  * and Practice</cite>.
  40.  *
  41.  * @version     1.31, 06/24/97
  42.  * @author     Sami Shaio
  43.  * @author     Arthur van Hoff
  44.  * @since       JDK1.0
  45.  */
  46. public class Color implements java.io.Serializable {
  47.     
  48.     /**
  49.      * The color white.
  50.      */
  51.     public final static Color white     = new Color(255, 255, 255);
  52.  
  53.     /**
  54.      * The color light gray.
  55.      */
  56.     public final static Color lightGray = new Color(192, 192, 192);
  57.  
  58.     /**
  59.      * The color gray.
  60.      */
  61.     public final static Color gray     = new Color(128, 128, 128);
  62.  
  63.     /**
  64.      * The color dark gray.
  65.      */
  66.     public final static Color darkGray     = new Color(64, 64, 64);
  67.  
  68.     /**
  69.      * The color black.
  70.      */
  71.     public final static Color black     = new Color(0, 0, 0);
  72.     
  73.     /**
  74.      * The color red.
  75.      */
  76.     public final static Color red     = new Color(255, 0, 0);
  77.  
  78.     /**
  79.      * The color pink.
  80.      */
  81.     public final static Color pink     = new Color(255, 175, 175);
  82.  
  83.     /**
  84.      * The color orange.
  85.      */
  86.     public final static Color orange     = new Color(255, 200, 0);
  87.  
  88.     /**
  89.      * The color yellow.
  90.      */
  91.     public final static Color yellow     = new Color(255, 255, 0);
  92.  
  93.     /**
  94.      * The color green.
  95.      */
  96.     public final static Color green     = new Color(0, 255, 0);
  97.  
  98.     /**
  99.      * The color magneta.
  100.      */
  101.     public final static Color magenta    = new Color(255, 0, 255);
  102.  
  103.     /**
  104.      * The color cyan.
  105.      */
  106.     public final static Color cyan     = new Color(0, 255, 255);
  107.  
  108.     /**
  109.      * The color blue.
  110.      */
  111.     public final static Color blue     = new Color(0, 0, 255);
  112.  
  113.     /**
  114.      * Private data.
  115.      */
  116.     transient private int pData;
  117.  
  118.     /**
  119.      * The color value.
  120.      */
  121.     int value;
  122.  
  123.     /*
  124.      * JDK 1.1 serialVersionUID 
  125.      */
  126.      private static final long serialVersionUID = 118526816881161077L;
  127.  
  128.     /**
  129.      * Checks the color integer components supplied for validity.
  130.      * Throws an IllegalArgumentException if the value is out of range.
  131.      * @param r the Red component
  132.      * @param g the Green component
  133.      * @param b the Blue component
  134.      **/
  135.     private static void testColorValueRange(int r, int g, int b) {
  136.         boolean rangeError = false;
  137.     String badComponentString = "";
  138.     if ( r < 0 || r > 255) {
  139.         rangeError = true;
  140.         badComponentString = badComponentString + " Red";
  141.     }
  142.     if ( g < 0 || g > 255) {
  143.         rangeError = true;
  144.         badComponentString = badComponentString + " Green";
  145.     }
  146.     if ( b < 0 || b > 255) {
  147.         rangeError = true;
  148.         badComponentString = badComponentString + " Blue";
  149.     }
  150.     if ( rangeError == true ) {
  151.     throw new IllegalArgumentException("Color parameter outside of expected range:"
  152.                        + badComponentString);
  153.     }
  154.     }
  155.  
  156.     /**
  157.      * Checks the color float components supplied for validity.
  158.      * Throws an IllegalArgumentException if the value is out of range.
  159.      * @param r the Red component
  160.      * @param g the Green component
  161.      * @param b the Blue component
  162.      **/
  163.     private static void testColorValueRange(float r, float g, float b) {
  164.         boolean rangeError = false;
  165.     String badComponentString = "";
  166.     if ( r < 0.0 || r > 1.0) {
  167.         rangeError = true;
  168.         badComponentString = badComponentString + " Red";
  169.     }
  170.     if ( g < 0.0 || g > 1.0) {
  171.         rangeError = true;
  172.         badComponentString = badComponentString + " Green";
  173.     }
  174.     if ( b < 0.0 || b > 1.0) {
  175.         rangeError = true;
  176.         badComponentString = badComponentString + " Blue";
  177.     }
  178.     if ( rangeError == true ) {
  179.     throw new IllegalArgumentException("Color parameter outside of expected range:"
  180.                        + badComponentString);
  181.     }
  182.     }
  183.  
  184.     /**
  185.      * Creates a color with the specified red, green, and blue 
  186.      * components. The three arguments must each be in the range 
  187.      * 0-255. 
  188.      * <p>
  189.      * The actual color used in rendering depends on finding the best 
  190.      * match given the color space available for a given output device. 
  191.      * @param       r the red component.
  192.      * @param       g the green component.
  193.      * @param       b the blue component.
  194.      * @see         java.awt.Color#getRed.
  195.      * @see         java.awt.Color#getGreen.
  196.      * @see         java.awt.Color#getBlue.
  197.      * @see         java.awt.Color#getRGB.
  198.      * @since       JDK1.0
  199.      */
  200.     public Color(int r, int g, int b) {
  201.         this(((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0));
  202.     testColorValueRange(r,g,b);
  203.     }
  204.  
  205.     /**
  206.      * Creates a color with the specified RGB value, where the red 
  207.      * component is in bits 16-23 of the argument, the green 
  208.      * component is in bits 8-15 of the argument, and the blue 
  209.      * component is in bits 0-7. The value zero indicates no 
  210.      * contribution from the primary color component. 
  211.      * <p>
  212.      * The actual color used in rendering depends on finding the best 
  213.      * match given the color space available for a given output device. 
  214.      * @param       rgb   an integer giving the red, green, and blue components.
  215.      * @see         java.awt.image.ColorModel#getRGBdefault
  216.      * @see         java.awt.Color#getRed.
  217.      * @see         java.awt.Color#getGreen.
  218.      * @see         java.awt.Color#getBlue.
  219.      * @see         java.awt.Color#getRGB.
  220.      * @since       JDK1.0
  221.      */
  222.     public Color(int rgb) {
  223.       value = 0xff000000 | rgb;
  224.     }
  225.  
  226.     /**
  227.      * Creates a color with the specified red, green, and blue values, 
  228.      * where each of the values is in the range 0.0-1.0. The value 
  229.      * 0.0 indicates no contribution from the primary color component. 
  230.      * The value 1.0 indicates the maximum intensity of the primary color 
  231.      * component. 
  232.      * <p>
  233.      * The actual color used in rendering depends on finding the best 
  234.      * match given the color space available for a given output device. 
  235.      * @param       r the red component
  236.      * @param       g the red component
  237.      * @param       b the red component
  238.      * @see         java.awt.Color#getRed.
  239.      * @see         java.awt.Color#getGreen.
  240.      * @see         java.awt.Color#getBlue.
  241.      * @see         java.awt.Color#getRGB.
  242.      * @since       JDK1.0
  243.      */
  244.     public Color(float r, float g, float b) {
  245.       this( (int) (r * 255), (int) (g * 255), (int) (b * 255));
  246.       testColorValueRange(r,g,b);
  247.     }
  248.  
  249.     /**
  250.      * Gets the red component of this color. The result is 
  251.      * an integer in the range 0 to 255. 
  252.      * @return        the red component of this color.
  253.      * @see           java.awt.Color#getRGB
  254.      * @since         JDK1.0
  255.      */
  256.     public int getRed() {
  257.     return (getRGB() >> 16) & 0xFF;
  258.     }
  259.  
  260.     /**
  261.      * Gets the green component of this color. The result is 
  262.      * an integer in the range 0 to 255. 
  263.      * @return        the green component of this color.
  264.      * @see           java.awt.Color#getRGB
  265.      * @since         JDK1.0
  266.      */
  267.     public int getGreen() {
  268.     return (getRGB() >> 8) & 0xFF;
  269.     }
  270.  
  271.     /**
  272.      * Gets the blue component of this color. The result is 
  273.      * an integer in the range 0 to 255. 
  274.      * @return        the blue component of this color.
  275.      * @see           java.awt.Color#getRGB
  276.      * @since         JDK1.0
  277.      */
  278.     public int getBlue() {
  279.     return (getRGB() >> 0) & 0xFF;
  280.     }
  281.  
  282.     /**
  283.      * Gets the RGB value representing the color in the default RGB ColorModel. 
  284.      * The red, green, and blue components of the color are each scaled to be 
  285.      * a value between 0 (abscence of the color) and 255 (complete saturation). 
  286.      * Bits 24-31 of the returned integer are 0xff, bits 16-23 are the red 
  287.      * value, bit 8-15 are the green value, and bits 0-7 are the blue value.
  288.      * @see java.awt.image.ColorModel#getRGBdefault
  289.      * @see #getRed
  290.      * @see #getGreen
  291.      * @see #getBlue
  292.      * @since JDK1.0
  293.      */
  294.     public int getRGB() {
  295.     return value;
  296.     }
  297.  
  298.     private static final double FACTOR = 0.7;
  299.  
  300.     /**
  301.      * Creates a brighter version of this color.
  302.      * <p>
  303.      * This method applies an arbitrary scale factor to each of the three RGB 
  304.      * components of the color to create a brighter version of the same 
  305.      * color. Although <code>brighter</code> and <code>darker</code> are 
  306.      * inverse operations, the results of a series of invocations of 
  307.      * these two methods may be inconsistent because of rounding errors. 
  308.      * @return     a new <code>Color</code> object, 
  309.      *                            a brighter version of this color.
  310.      * @see        java.awt.Color#darker
  311.      * @since      JDK1.0
  312.      */
  313.     public Color brighter() {
  314.     return new Color(Math.min((int)(getRed()  *(1/FACTOR)), 255), 
  315.              Math.min((int)(getGreen()*(1/FACTOR)), 255),
  316.              Math.min((int)(getBlue() *(1/FACTOR)), 255));
  317.     }
  318.  
  319.     /**
  320.      * Creates a darker version of this color.
  321.      * <p>
  322.      * This method applies an arbitrary scale factor to each of the three RGB 
  323.      * components of the color to create a darker version of the same 
  324.      * color. Although <code>brighter</code> and <code>darker</code> are 
  325.      * inverse operations, the results of a series of invocations of 
  326.      * these two methods may be inconsistent because of rounding errors. 
  327.      * @return  a new <code>Color</code> object, 
  328.      *                              a darker version of this color.
  329.      * @see        java.awt.Color#brighter
  330.      * @since      JDK1.0
  331.      */
  332.     public Color darker() {
  333.     return new Color(Math.max((int)(getRed()  *FACTOR), 0), 
  334.              Math.max((int)(getGreen()*FACTOR), 0),
  335.              Math.max((int)(getBlue() *FACTOR), 0));
  336.     }
  337.  
  338.     /**
  339.      * Computes the hash code for this color.
  340.      * @return     a hash code value for this object.
  341.      * @since      JDK1.0
  342.      */
  343.     public int hashCode() {
  344.     return value;
  345.     }
  346.  
  347.     /**
  348.      * Determines whether another object is equal to this color.
  349.      * <p>
  350.      * The result is <code>true</code> if and only if the argument is not 
  351.      * <code>null</code> and is a <code>Color</code> object that has the same 
  352.      * red, green, and blue values as this object. 
  353.      * @param       obj   the object to compare with.
  354.      * @return      <code>true</code> if the objects are the same; 
  355.      *                             <code>false</code> otherwise.
  356.      * @since   JDK1.0
  357.      */
  358.     public boolean equals(Object obj) {
  359.         return obj instanceof Color && ((Color)obj).value == this.value;
  360.     }
  361.  
  362.     /**
  363.      * Creates a string that represents this color and indicates the 
  364.      * values of its RGB components. 
  365.      * @return     a representation of this color as a 
  366.      *                           <code>String</code> object.
  367.      * @since      JDK1.0
  368.      */
  369.     public String toString() {
  370.         return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]";
  371.     }
  372.  
  373.     /**
  374.      * Converts a string to an integer and returns the 
  375.      * specified color. This method handles string formats that 
  376.      * are used to represent octal and hexidecimal numbers.
  377.      * @param      nm a string that represents 
  378.      *                            a color as a 24-bit integer.
  379.      * @return     the new color
  380.      * @see        java.lang.Integer#decode
  381.      * @exception  NumberFormatException  if the specified string cannot
  382.      *                      be interpreted as a decimal, 
  383.      *                      octal, or hexidecimal integer.
  384.      * @since      JDK1.1
  385.      */
  386.     public static Color decode(String nm) throws NumberFormatException {
  387.     Integer intval = Integer.decode(nm);
  388.     int i = intval.intValue();
  389.     return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  390.     }
  391.  
  392.     /**
  393.      * Finds a color in the system properties. 
  394.      * <p>
  395.      * The argument is treated as the name of a system property to 
  396.      * be obtained. The string value of this property is then interpreted 
  397.      * as an integer which is then converted to a color. 
  398.      * <p>
  399.      * If the specified property is not found, or could not be parsed as 
  400.      * an integer, then <code>null</code> is returned. 
  401.      * @param    nm the name of the color property
  402.      * @return   the color value of the property.
  403.      * @see      java.lang.System#getProperty(java.lang.String)
  404.      * @see      java.lang.Integer#getInteger(java.lang.String)
  405.      * @see      java.awt.Color#Color(int)
  406.      * @since    JDK1.0
  407.      */
  408.     public static Color getColor(String nm) {
  409.     return getColor(nm, null);
  410.     }
  411.  
  412.     /**
  413.      * Finds a color in the system properties. 
  414.      * <p>
  415.      * The first argument is treated as the name of a system property to 
  416.      * be obtained. The string value of this property is then interpreted 
  417.      * as an integer which is then converted to a color. 
  418.      * <p>
  419.      * If the specified property is not found, or cannot be parsed as 
  420.      * an integer, then the color specified by the second argument is 
  421.      * returned instead. 
  422.      * @param    nm the name of the color property
  423.      * @param    v    the default color value.
  424.      * @return   the color value of the property.
  425.      * @see      java.lang.System#getProperty(java.lang.String)
  426.      * @see      java.lang.Integer#getInteger(java.lang.String)
  427.      * @see      java.awt.Color#Color(int)
  428.      * @since    JDK1.0
  429.      */
  430.     public static Color getColor(String nm, Color v) {
  431.     Integer intval = Integer.getInteger(nm);
  432.     if (intval == null) {
  433.         return v;
  434.     }
  435.     int i = intval.intValue();
  436.     return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  437.     }
  438.  
  439.     /**
  440.      * Finds a color in the system properties. 
  441.      * <p>
  442.      * The first argument is treated as the name of a system property to 
  443.      * be obtained. The string value of this property is then interpreted 
  444.      * as an integer which is then converted to a color. 
  445.      * <p>
  446.      * If the specified property is not found, or could not be parsed as 
  447.      * an integer, then the integer value <code>v</code> is used instead, 
  448.      * and is converted to a color.
  449.      * @param    nm  the name of the color property.
  450.      * @param    v   the default color value, as an integer.
  451.      * @return   the color value of the property.
  452.      * @see      java.lang.System#getProperty(java.lang.String)
  453.      * @see      java.lang.Integer#getInteger(java.lang.String)
  454.      * @see      java.awt.Color#Color(int)
  455.      * @since    JDK1.0
  456.      */
  457.     public static Color getColor(String nm, int v) {
  458.     Integer intval = Integer.getInteger(nm);
  459.     int i = (intval != null) ? intval.intValue() : v;
  460.     return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF);
  461.     }
  462.  
  463.     /**
  464.      * Converts the components of a color, as specified by the HSB 
  465.      * model, to an equivalent set of values for the RGB model. 
  466.      * <p>
  467.      * The integer that is returned by <code>HSBtoRGB</code> encodes the 
  468.      * value of a color in bits 0&endash;23 of an integer value, the same 
  469.      * format used by the method <code>getRGB</code>. This integer can be 
  470.      * supplied as an argument to the <code>Color</code> constructor that 
  471.      * takes a single integer argument. 
  472.      * @param     hue   the hue component of the color.
  473.      * @param     saturation   the saturation of the color.
  474.      * @param     brightness   the brightness of the color.
  475.      * @return    the RGB value of the color with the indicated hue, 
  476.      *                            saturation, and brightness.
  477.      * @see       java.awt.Color#getRGB()
  478.      * @see       java.awt.Color#Color(int)
  479.      * @since     JDK1.0
  480.      */
  481.     public static int HSBtoRGB(float hue, float saturation, float brightness) {
  482.     int r = 0, g = 0, b = 0;
  483.         if (saturation == 0) {
  484.         r = g = b = (int) (brightness * 255);
  485.     } else {
  486.         double h = (hue - Math.floor(hue)) * 6.0;
  487.         double f = h - java.lang.Math.floor(h);
  488.         double p = brightness * (1.0 - saturation);
  489.         double q = brightness * (1.0 - saturation * f);
  490.         double t = brightness * (1.0 - (saturation * (1.0 - f)));
  491.         switch ((int) h) {
  492.         case 0:
  493.         r = (int) (brightness * 255);
  494.         g = (int) (t * 255);
  495.         b = (int) (p * 255);
  496.         break;
  497.         case 1:
  498.         r = (int) (q * 255);
  499.         g = (int) (brightness * 255);
  500.         b = (int) (p * 255);
  501.         break;
  502.         case 2:
  503.         r = (int) (p * 255);
  504.         g = (int) (brightness * 255);
  505.         b = (int) (t * 255);
  506.         break;
  507.         case 3:
  508.         r = (int) (p * 255);
  509.         g = (int) (q * 255);
  510.         b = (int) (brightness * 255);
  511.         break;
  512.         case 4:
  513.         r = (int) (t * 255);
  514.         g = (int) (p * 255);
  515.         b = (int) (brightness * 255);
  516.         break;
  517.         case 5:
  518.         r = (int) (brightness * 255);
  519.         g = (int) (p * 255);
  520.         b = (int) (q * 255);
  521.         break;
  522.         }
  523.     }
  524.     return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
  525.     }
  526.  
  527.     /**
  528.      * Converts the components of a color, as specified by the RGB 
  529.      * model, to an equivalent set of values for hue, saturation, and 
  530.      * brightness, the three components of the HSB model. 
  531.      * <p>
  532.      * If the <code>hsbvals</code> argument is <code>null</code>, then a 
  533.      * new array is allocated to return the result. Otherwise, the method 
  534.      * returns the array <code>hsbvals</code>, with the values put into 
  535.      * that array. 
  536.      * @param     r   the red component of the color.
  537.      * @param     g   the green component of the color.
  538.      * @param     b   the blue component of the color.
  539.      * @param     hsbvals  the array to be used to return the 
  540.      *                     three HSB values, or <code>null</code>.
  541.      * @return    an array of three elements containing the hue, saturation, 
  542.      *                     and brightness (in that order), of the color with 
  543.      *                     the indicated red, green, and blue components.
  544.      * @see       java.awt.Color#getRGB()
  545.      * @see       java.awt.Color#Color(int)
  546.      * @since     JDK1.0
  547.      */
  548.     public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
  549.     float hue, saturation, brightness;
  550.     if (hsbvals == null) {
  551.         hsbvals = new float[3];
  552.     }
  553.         int cmax = (r > g) ? r : g;
  554.     if (b > cmax) cmax = b;
  555.     int cmin = (r < g) ? r : g;
  556.     if (b < cmin) cmin = b;
  557.  
  558.     brightness = ((float) cmax) / 255.0f;
  559.     if (cmax != 0)
  560.         saturation = ((float) (cmax - cmin)) / ((float) cmax);
  561.     else
  562.         saturation = 0;
  563.     if (saturation == 0)
  564.         hue = 0;
  565.     else {
  566.         float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
  567.         float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
  568.         float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
  569.         if (r == cmax)
  570.         hue = bluec - greenc;
  571.         else if (g == cmax)
  572.             hue = 2.0f + redc - bluec;
  573.             else
  574.         hue = 4.0f + greenc - redc;
  575.         hue = hue / 6.0f;
  576.         if (hue < 0)
  577.         hue = hue + 1.0f;
  578.     }
  579.     hsbvals[0] = hue;
  580.     hsbvals[1] = saturation;
  581.     hsbvals[2] = brightness;
  582.     return hsbvals;
  583.     }
  584.  
  585.     /**
  586.      * Creates a <code>Color</code> object based on values supplied 
  587.      * for the HSB color model. 
  588.      * <p>
  589.      * Each of the three components should be a floating-point 
  590.      * value between zero and one (a number in the range 
  591.      * <code>0.0</code> ≤ <code>h</code>, <code>s</code>, 
  592.      * <code>b</code> ≤ <code>1.0). </code> 
  593.      * @param  h   the hue component.
  594.      * @param  s   the saturation of the color.
  595.      * @param  b   the brightness of the color.
  596.      * @return  a <code>Color</code> object with the specified hue, 
  597.      *                                 saturation, and brightness.
  598.      * @since   JDK1.0
  599.      */
  600.     public static Color getHSBColor(float h, float s, float b) {
  601.     return new Color(HSBtoRGB(h, s, b));
  602.     }
  603. }
  604.