Source for gnu.java.awt.color.SrgbConverter

   1: /* SrgbConverter.java -- sRGB conversion class
   2:    Copyright (C) 2004 Free Software Foundation
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.awt.color;
  39: 
  40: 
  41: /**
  42:  * SrgbConverter - conversion routines for the sRGB colorspace
  43:  * sRGB is a standard for RGB colorspaces, adopted by the w3c.
  44:  *
  45:  * The specification is available at:
  46:  * http://www.w3.org/Graphics/Color/sRGB.html
  47:  *
  48:  * @author Sven de Marothy
  49:  */
  50: /**
  51:  *
  52:  * Note the matrix numbers used here are NOT identical to those in the
  53:  * w3 spec, as those numbers are CIE XYZ relative a D65 white point.
  54:  * The CIE XYZ we use is relative a D50 white point, so therefore a
  55:  * linear Bradford transform matrix for D65->D50 mapping has been applied.
  56:  * (The ICC documents describe this transform)
  57:  *
  58:  *   Linearized Bradford transform:
  59:  *    0.8951    0.2664   -0.1614
  60:  *   -0.7502    1.7135    0.0367
  61:  *    0.0389   -0.0685    1.0296
  62:  *
  63:  *   Inverse:
  64:  *   0.9870   -0.1471    0.1600
  65:  *   0.4323    0.5184    0.0493
  66:  *  -0.00853   0.0400    0.9685
  67:  */
  68: public class SrgbConverter implements ColorSpaceConverter
  69: {
  70:   public float[] fromCIEXYZ(float[] in)
  71:   {
  72:     return XYZtoRGB(in);
  73:   }
  74: 
  75:   public float[] toCIEXYZ(float[] in)
  76:   {
  77:     return RGBtoXYZ(in);
  78:   }
  79: 
  80:   public float[] toRGB(float[] in)
  81:   {
  82:     float[] out = new float[3];
  83:     System.arraycopy(in, 0, out, 0, 3);
  84:     return out;
  85:   }
  86: 
  87:   public float[] fromRGB(float[] in)
  88:   {
  89:     float[] out = new float[3];
  90:     System.arraycopy(in, 0, out, 0, 3);
  91:     return out;
  92:   }
  93: 
  94:   /**
  95:    * CIE XYZ (D50 relative) --> sRGB
  96:    *
  97:    * Static as it's used by other ColorSpaceConverters to
  98:    * convert to sRGB if the color space is defined in XYZ.
  99:    */
 100:   public static float[] XYZtoRGB(float[] in)
 101:   {
 102:     float[] temp = new float[3];
 103:     temp[0] = 3.1338f * in[0] - 1.6171f * in[1] - 0.4907f * in[2];
 104:     temp[1] = -0.9785f * in[0] + 1.9160f * in[1] + 0.0334f * in[2];
 105:     temp[2] = 0.0720f * in[0] - 0.2290f * in[1] + 1.4056f * in[2];
 106: 
 107:     float[] out = new float[3];
 108:     for (int i = 0; i < 3; i++)
 109:       {
 110:         if (temp[i] < 0)
 111:           temp[i] = 0.0f;
 112:         if (temp[i] > 1)
 113:           temp[i] = 1.0f;
 114:         if (temp[i] <= 0.00304f)
 115:           out[i] = temp[i] * 12.92f;
 116:         else
 117:           out[i] = 1.055f * ((float) Math.exp((1 / 2.4) * Math.log(temp[i])))
 118:                    - 0.055f;
 119:       }
 120:     return out;
 121:   }
 122: 
 123:   /**
 124:    * sRGB --> CIE XYZ (D50 relative)
 125:    *
 126:    * Static as it's used by other ColorSpaceConverters to
 127:    * convert to XYZ if the color space is defined in RGB.
 128:    */
 129:   public static float[] RGBtoXYZ(float[] in)
 130:   {
 131:     float[] temp = new float[3];
 132:     float[] out = new float[3];
 133:     for (int i = 0; i < 3; i++)
 134:       if (in[i] <= 0.03928f)
 135:         temp[i] = in[i] / 12.92f;
 136:       else
 137:         temp[i] = (float) Math.exp(2.4 * Math.log((in[i] + 0.055) / 1.055));
 138: 
 139:     /*
 140:      * Note: The numbers which were used to calculate this only had four
 141:      * digits of accuracy. So don't be fooled by the number of digits here.
 142:      * If someone has more accurate source, feel free to update this.
 143:      */
 144:     out[0] = (float) (0.436063750222 * temp[0] + 0.385149601465 * temp[1]
 145:              + 0.143086418888 * temp[2]);
 146:     out[1] = (float) (0.222450894035 * temp[0] + 0.71692584775 * temp[1]
 147:              + 0.060624511256 * temp[2]);
 148:     out[2] = (float) (0.0138985186 * temp[0] + 0.097079690112 * temp[1]
 149:              + 0.713996045725 * temp[2]);
 150:     return out;
 151:   }
 152: }