FloatDoubleColorModel.java
上传用户:btjssb159
上传日期:2018-01-04
资源大小:241k
文件大小:41k
源码类别:

DNA

开发平台:

Java

  1. /*
  2.  * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without 
  5.  * modification, are permitted provided that the following conditions are met:
  6.  * 
  7.  * -Redistributions of source code must retain the above copyright notice, this 
  8.  * list of conditions and the following disclaimer.
  9.  *
  10.  * -Redistribution in binary form must reproduct the above copyright notice,
  11.  * this list of conditions and the following disclaimer in the documentation
  12.  * and/or other materials provided with the distribution.
  13.  * 
  14.  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
  15.  * be used to endorse or promote products derived from this software without
  16.  * specific prior written permission.
  17.  * 
  18.  * This software is provided "AS IS," without a warranty of any kind. ALL
  19.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  20.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  21.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  22.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  23.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  24.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  25.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  26.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  27.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  28.  * POSSIBILITY OF SUCH DAMAGES.
  29.  * 
  30.  * You acknowledge that Software is not designed,licensed or intended for use in 
  31.  * the design, construction, operation or maintenance of any nuclear facility.
  32.  */
  33. import java.awt.Point;
  34. import java.awt.Transparency;
  35. import java.awt.color.ColorSpace;
  36. import java.awt.image.ColorModel;
  37. import java.awt.image.ComponentColorModel;
  38. import java.awt.image.ComponentSampleModel;
  39. import java.awt.image.DataBuffer;
  40. import java.awt.image.Raster;
  41. import java.awt.image.SampleModel;
  42. import java.awt.image.WritableRaster;
  43. /**
  44.  * A <code>ColorModel</code> class that works with pixel values that
  45.  * represent color and alpha information as separate samples, using
  46.  * float or double elements.  This class can be used with an arbitrary
  47.  * <code>ColorSpace</code>.  The number of color samples in the pixel
  48.  * values must be same as the number of color components in the
  49.  * <code>ColorSpace</code>.  There may be a single alpha sample.
  50.  *
  51.  * <p> Sample values are taken as ranging from 0.0 to 1.0; that is,
  52.  * when converting to 8-bit RGB, a multiplication by 255 is performed
  53.  * and values outside of the range 0-255 are clamped at the closest
  54.  * endpoint.
  55.  *
  56.  * <p> For maximum efficiency, pixel data being interpreted by this
  57.  * class should be in the sRGB color space.  This will result in 
  58.  * only the trivial conversion (scaling by 255 and dividing by any
  59.  * premultiplied alpha) to be performed.  Other color spaces require
  60.  * more general conversions.
  61.  *
  62.  * <p> For those methods that use a primitive array pixel
  63.  * representation of type <code>transferType</code>, the array length
  64.  * is the same as the number of color and alpha samples.  Color
  65.  * samples are stored first in the array followed by the alpha sample,
  66.  * if present.  The order of the color samples is specified by the
  67.  * <code>ColorSpace</code>.  Typically, this order reflects the name
  68.  * of the color space type. For example, for <code>TYPE_RGB</code>,
  69.  * index 0 corresponds to red, index 1 to green, and index 2 to blue.
  70.  * The transfer types supported are
  71.  * <code>DataBuffer.TYPE_FLOAT</code>,
  72.  * <code>DataBuffer.TYPE_DOUBLE</code>.
  73.  *
  74.  * <p> The translation from pixel values to color/alpha components for
  75.  * display or processing purposes is a one-to-one correspondence of
  76.  * samples to components.
  77.  *
  78.  * <p> Methods that use a single int pixel representation throw an
  79.  * <code>IllegalArgumentException</code>.
  80.  *
  81.  * <p> A <code>FloatDoubleColorModel</code> can be used in
  82.  * conjunction with a <code>ComponentSampleModelJAI</code>.
  83.  *
  84.  * @see java.awt.image.ColorModel
  85.  * @see java.awt.color.ColorSpace
  86.  * @see java.awt.image.ComponentSampleModel
  87.  * @see ComponentSampleModelJAI
  88.  */
  89. public class FloatDoubleColorModel extends ComponentColorModel {
  90.     /**
  91.      * The associated <code>ColorSpace</code>.
  92.      *
  93.      */
  94.     protected ColorSpace colorSpace;
  95.     /**
  96.      * The type or family of the associated <code>ColorSpace</code>.
  97.      *
  98.      */
  99.     protected int colorSpaceType;
  100.     /**
  101.      * The number of components of the associated <code>ColorSpace</code>.
  102.      *
  103.      */
  104.     protected int numColorComponents;
  105.     /**
  106.      * The number of components represented by this <code>ColorModel</code>.
  107.      * This will differ from the number of components of the associated
  108.      * <code>ColorSpace</code> if there is an alpha channel.
  109.      *
  110.      */
  111.     protected int numComponents;
  112.     /**
  113.      * Specifies what alpha values can be represented by this
  114.      * <code>ColorModel</code>.
  115.      *
  116.      */
  117.     protected int transparency;
  118.     /**
  119.      * Whether this <code>ColorModel</code> supports alpha.
  120.      *
  121.      */
  122.     protected boolean hasAlpha;
  123.     /**
  124.      * Whether alpha is premultiplied.
  125.      *
  126.      */
  127.     protected boolean isAlphaPremultiplied;
  128.     private static int[] bitsHelper(int transferType,
  129.                                     ColorSpace colorSpace,
  130.                                     boolean hasAlpha) {
  131.         int numBits = (transferType == DataBuffer.TYPE_FLOAT) ? 32 : 64;
  132.         int numComponents = colorSpace.getNumComponents();
  133.         if (hasAlpha) {
  134.             ++numComponents;
  135.         }
  136.         int[] bits = new int[numComponents];
  137.         for (int i = 0; i < numComponents; i++) {
  138.             bits[i] = numBits;
  139.         }
  140.         return bits;
  141.     }
  142.     /**
  143.      * Constructs a <code>ComponentColorModel</code> from the
  144.      * specified parameters. Color components will be in the specified
  145.      * <code>ColorSpace</code>.  <code>hasAlpha</code> indicates
  146.      * whether alpha information is present.  If <code>hasAlpha</code>
  147.      * is true, then the boolean <code>isAlphaPremultiplied</code>
  148.      * specifies how to interpret color and alpha samples in pixel
  149.      * values.  If the boolean is <code>true</code>, color samples are
  150.      * assumed to have been multiplied by the alpha sample. The
  151.      * <code>transparency</code> specifies what alpha values can be
  152.      * represented by this color model.  The <code>transferType</code>
  153.      * is the type of primitive array used to represent pixel values.
  154.      *
  155.      * @param colorSpace       The <code>ColorSpace</code> associated with
  156.      *                         this color model.
  157.      * @param hasAlpha         If true, this color model supports alpha.
  158.      * @param isAlphaPremultiplied If true, alpha is premultiplied.
  159.      * @param transparency     Specifies what alpha values can be represented
  160.      *                         by this color model.
  161.      * @param transferType     Specifies the type of primitive array used to
  162.      *                         represent pixel values, one of
  163.      *                         DataBuffer.TYPE_FLOAT or TYPE_DOUBLE.
  164.      * @throws IllegalArgumentException If the transfer type is not
  165.      *         DataBuffer.TYPE_FLOAT or TYPE_DOUBLE.
  166.      *
  167.      * @see java.awt.color.ColorSpace
  168.      * @see java.awt.Transparency
  169.      */
  170.     public FloatDoubleColorModel(ColorSpace colorSpace,
  171.                                  boolean hasAlpha,
  172.                                  boolean isAlphaPremultiplied,
  173.                                  int transparency,
  174.                                  int transferType) {
  175.         super(colorSpace, bitsHelper(transferType, colorSpace, hasAlpha),
  176.               hasAlpha, isAlphaPremultiplied,
  177.               transparency,
  178.               transferType);
  179.         if (transferType != DataBuffer.TYPE_FLOAT &&
  180.             transferType != DataBuffer.TYPE_DOUBLE) {
  181.             throw new IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel0"));
  182.         }
  183.         this.colorSpace = colorSpace;
  184.         this.colorSpaceType = colorSpace.getType();
  185.         this.numComponents =
  186.             this.numColorComponents = colorSpace.getNumComponents();
  187.         if (hasAlpha) {
  188.             ++numComponents;
  189.         }
  190.         this.transparency = transparency;
  191.         this.hasAlpha = hasAlpha;
  192.         this.isAlphaPremultiplied = isAlphaPremultiplied;
  193.     }
  194.     /**
  195.      * Throws an <code>IllegalArgumentException</code>, since pixel
  196.      * values for this <code>ColorModel</code> are not conveniently
  197.      * representable as a single <code>int</code>.
  198.      */
  199.     public int getRed(int pixel) {
  200.         throw new IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel1"));
  201.     }
  202.     /**
  203.      * Throws an <code>IllegalArgumentException</code>, since pixel
  204.      * values for this <code>ColorModel</code> are not conveniently
  205.      * representable as a single <code>int</code>.
  206.      */
  207.     public int getGreen(int pixel) {
  208.         throw new IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel2"));
  209.     }
  210.     /**
  211.      * Throws an <code>IllegalArgumentException</code>, since pixel
  212.      * values for this <code>ColorModel</code> are not conveniently
  213.      * representable as a single <code>int</code>.
  214.      */
  215.     public int getBlue(int pixel) {
  216.         throw new IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel3"));
  217.     }
  218.     /**
  219.      * Throws an <code>IllegalArgumentException</code>, since pixel
  220.      * values for this <code>ColorModel</code> are not conveniently
  221.      * representable as a single <code>int</code>.
  222.      */
  223.     public int getAlpha(int pixel) {
  224.         throw new IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel4"));
  225.     }
  226.     /**
  227.      * Throws an <code>IllegalArgumentException</code>, since pixel
  228.      * values for this <code>ColorModel</code> are not conveniently
  229.      * representable as a single <code>int</code>.
  230.      */
  231.     public int getRGB(int pixel) {
  232.         throw new IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel5"));
  233.     }
  234.     private final int clamp(float value) {
  235.         // Ensure NaN maps to 0
  236.         return (value >= 0.0F) ? ((value > 255.0F) ? 255 : (int)value) : 0;
  237.     }
  238.     private final int clamp(double value) {
  239.         // Ensure NaN maps to 0
  240.         return (value >= 0.0) ? ((value > 255.0) ? 255 : (int)value) : 0;
  241.     }
  242.     private int getSample(Object inData, int sample) {
  243.         boolean needAlpha = (hasAlpha && isAlphaPremultiplied);
  244.         int type = colorSpaceType;
  245.         boolean is_sRGB = colorSpace.isCS_sRGB();
  246.         if (type == ColorSpace.TYPE_GRAY) {
  247.             sample = 0;
  248.             is_sRGB = true;
  249.         }
  250.   
  251.         if (is_sRGB) {
  252.             if (transferType == DataBuffer.TYPE_FLOAT) {
  253.                 float[] fdata = (float[])inData;
  254.                 float fsample = fdata[sample]*255;
  255.                 if (needAlpha) {
  256.                     float falp = fdata[numColorComponents];
  257.     if (falp == 0.0) return 0;
  258.     else
  259.       return clamp(fsample/falp);
  260.                 } else {
  261.                     return clamp(fsample);
  262.                 }
  263.             } else {
  264.                 double[] ddata = (double[])inData;
  265.                 double dsample = ddata[sample]*255.0;
  266.                 if (needAlpha) {
  267.                     double dalp = ddata[numColorComponents];
  268.     if (dalp == 0.0) return 0;
  269.     else 
  270.       return clamp(dsample/dalp);
  271.                 } else {
  272.                     return clamp(dsample);
  273.                 }
  274.             }
  275.         }
  276.         // Not TYPE_GRAY or TYPE_RGB ColorSpace
  277.         float[] norm;
  278.         float[] rgb;
  279.         if (transferType == DataBuffer.TYPE_FLOAT) {
  280.             float[] fdata = (float[])inData;
  281.             if (needAlpha) {
  282.                 float falp = fdata[numColorComponents];
  283. if (falp == 0.0) return 0;
  284.                 norm = new float[numColorComponents];
  285.                 for (int i = 0; i < numColorComponents; i++) {
  286.                     norm[i] = fdata[i]/falp;
  287.                 }
  288.                 rgb = colorSpace.toRGB(norm);
  289.             } else {
  290.                 rgb = colorSpace.toRGB(fdata);
  291.             }
  292.     return (int)(rgb[sample]*255); 
  293.         } else {
  294.             double[] ddata = (double[])inData;
  295.             norm = new float[numColorComponents];
  296.             if (needAlpha) {
  297.                 double dalp = ddata[numColorComponents];
  298. if (dalp == 0.0) return 0;
  299.                 for (int i = 0; i < numColorComponents; i++) {
  300.                     norm[i] = (float)(ddata[i]/dalp);
  301.                 }
  302.                 rgb = colorSpace.toRGB(norm);
  303.             } else {
  304.                 for (int i = 0; i < numColorComponents; i++) {
  305.                     norm[i] = (float)ddata[i];
  306.                 }
  307.                 rgb = colorSpace.toRGB(norm);
  308.             }
  309.     return (int)(rgb[sample]*255);
  310.         }
  311.     }
  312.     /**
  313.      * Returns the red color component for the specified pixel, scaled
  314.      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A color
  315.      * conversion is done if necessary.  The <code>pixel</code> value
  316.      * is specified by an array of data elements of type
  317.      * <code>transferType</code> passed in as an object reference. The
  318.      * returned value will be a non pre-multiplied value. If the alpha
  319.      * is premultiplied, this method divides it out before returning
  320.      * the value (if the alpha value is 0, the red value will be 0).
  321.      *
  322.      * @param inData The pixel from which to get the red
  323.      * color component, specified by an array of data elements of type
  324.      * <code>transferType</code>.
  325.      *
  326.      * @return The red color component for the specified pixel, as an
  327.      * int.
  328.      *
  329.      * @throws ClassCastException If <code>inData</code> is not a
  330.      * primitive array of type <code>transferType</code>.
  331.      * @throws ArrayIndexOutOfBoundsException if <code>inData</code>
  332.      * is not large enough to hold a pixel value for this
  333.      * <code>ColorModel</code>.
  334.      */
  335.     public int getRed(Object inData) {
  336.         return getSample(inData, 0);
  337.     }
  338.     /**
  339.      * Returns the green color component for the specified pixel, scaled
  340.      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A color
  341.      * conversion is done if necessary.  The <code>pixel</code> value
  342.      * is specified by an array of data elements of type
  343.      * <code>transferType</code> passed in as an object reference. The
  344.      * returned value will be a non pre-multiplied value. If the alpha
  345.      * is premultiplied, this method divides it out before returning
  346.      * the value (if the alpha value is 0, the green value will be 0).
  347.      *
  348.      * @param inData The pixel from which to get the green
  349.      * color component, specified by an array of data elements of type
  350.      * <code>transferType</code>.
  351.      *
  352.      * @return The green color component for the specified pixel, as an
  353.      * int.
  354.      *
  355.      * @throws ClassCastException If <code>inData</code> is not a
  356.      * primitive array of type <code>transferType</code>.
  357.      * @throws ArrayIndexOutOfBoundsException if <code>inData</code>
  358.      * is not large enough to hold a pixel value for this
  359.      * <code>ColorModel</code>.
  360.      */
  361.     public int getGreen(Object inData) {
  362.         return getSample(inData, 1);
  363.     }
  364.     /**
  365.      * Returns the blue color component for the specified pixel, scaled
  366.      * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A color
  367.      * conversion is done if necessary.  The <code>pixel</code> value
  368.      * is specified by an array of data elements of type
  369.      * <code>transferType</code> passed in as an object reference. The
  370.      * returned value will be a non pre-multiplied value. If the alpha
  371.      * is premultiplied, this method divides it out before returning
  372.      * the value (if the alpha value is 0, the blue value will be 0).
  373.      *
  374.      * @param inData The pixel from which to get the blue
  375.      * color component, specified by an array of data elements of type
  376.      * <code>transferType</code>.
  377.      *
  378.      * @return The blue color component for the specified pixel, as an
  379.      * int.
  380.      *
  381.      * @throws ClassCastException If <code>inData</code> is not a
  382.      * primitive array of type <code>transferType</code>.
  383.      * @throws ArrayIndexOutOfBoundsException if <code>inData</code>
  384.      * is not large enough to hold a pixel value for this
  385.      * <code>ColorModel</code>.
  386.      */
  387.     public int getBlue(Object inData) {
  388.         return getSample(inData, 2);
  389.     }
  390.     /**
  391.      * Returns the alpha component for the specified pixel, scaled
  392.      * from 0 to 255.  The pixel value is specified by an array of
  393.      * data elements of type <code>transferType</code> passed in as an
  394.      * object reference.  If the <code>ColorModel</code> does not have
  395.      * alpha, 255 is returned.
  396.      *
  397.      * @param inData The pixel from which to get the alpha
  398.      * component, specified by an array of data elements of type
  399.      * <code>transferType</code>.
  400.      *
  401.      * @return The alpha component for the specified pixel, as an int.
  402.      *
  403.      * @throws IllegalArgumentException if <code>inData</code> is
  404.      * <code>null</code> and the <code>colorModel</code> has alpha.
  405.      * @throws ClassCastException If <code>inData</code> is not a
  406.      * primitive array of type <code>transferType</code> and the
  407.      * <code>ColorModel</code> has alpha.
  408.      * @throws ArrayIndexOutOfBoundsException if <code>inData</code>
  409.      * is not large enough to hold a pixel value for this
  410.      * <code>ColorModel</code> and the <code>ColorModel</code> has
  411.      * alpha.
  412.      */
  413.     public int getAlpha(Object inData) {
  414.         if ( inData == null ) {
  415.             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
  416.         }
  417.         if (hasAlpha == false) {
  418.             return 255;
  419.         }
  420.         if (transferType == DataBuffer.TYPE_FLOAT) {
  421.             float[] fdata = (float[])inData;
  422.             return (int)(fdata[numColorComponents]*255.0F);
  423.         } else {
  424.             double[] ddata = (double[])inData;
  425.             return (int)(ddata[numColorComponents]*255.0);
  426.         }
  427.     }
  428.     /**
  429.      * Returns the color/alpha components for the specified pixel in
  430.      * the default RGB color model format.  A color conversion is done
  431.      * if necessary.  The pixel value is specified by an array of data
  432.      * elements of type <code>transferType</code> passed in as an
  433.      * object reference.  The returned value is in a non
  434.      * pre-multiplied format. If the alpha is premultiplied, this
  435.      * method divides it out of the color components (if the alpha
  436.      * value is 0, the color values will be 0).
  437.      *
  438.      * @param inData The pixel from which to get the
  439.      * color/alpha components, specified by an array of data elements
  440.      * of type <code>transferType</code>.
  441.      *
  442.      * @return The color/alpha components for the specified pixel, as an int.
  443.      *
  444.      * @throws ClassCastException If <code>inData</code> is not a
  445.      * primitive array of type <code>transferType</code>.
  446.      * @throws ArrayIndexOutOfBoundsException if <code>inData</code>
  447.      * is not large enough to hold a pixel value for this
  448.      * <code>ColorModel</code>.
  449.      */
  450.     public int getRGB(Object inData) {
  451.         boolean needAlpha = (hasAlpha && isAlphaPremultiplied);
  452. int alpha = 255;
  453. int red, green, blue;
  454. if (colorSpace.isCS_sRGB()) {
  455.             if (transferType == DataBuffer.TYPE_FLOAT) {
  456.                 float[] fdata = (float[])inData;
  457.                 float fred = fdata[0];
  458.                 float fgreen = fdata[1];
  459.                 float fblue = fdata[2];
  460.                 float fscale = 255.0F;
  461.                 if (needAlpha) {
  462.                     float falpha = fdata[3];
  463.                     fscale /= falpha;
  464.                     alpha = clamp(255.0F*falpha);
  465.                 }
  466. red = clamp(fred*fscale);
  467. green = clamp(fgreen*fscale);
  468. blue = clamp(fblue*fscale);
  469.             } else {
  470.                 double[] ddata = (double[])inData;
  471.                 double dred = ddata[0];
  472.                 double dgreen = ddata[1];
  473.                 double dblue = ddata[2];
  474.                 double dscale = 255.0;
  475.                 if (needAlpha) {
  476.                     double dalpha = ddata[3];
  477.                     dscale /= dalpha;
  478.                     alpha = clamp(255.0*dalpha);
  479.                 }
  480. red = clamp(dred*dscale);
  481. green = clamp(dgreen*dscale);
  482. blue = clamp(dblue*dscale);
  483.     }
  484. } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
  485.     if (transferType == DataBuffer.TYPE_FLOAT) {
  486.                 float[] fdata = (float[])inData;
  487. float fgray = fdata[0];
  488.                 if (needAlpha) {
  489.                     float falp = fdata[1];
  490.     red = green = blue = clamp(fgray*255.0F/falp);
  491.                     alpha = clamp(255.0F*falp);
  492. } else {
  493.     red = green = blue = clamp(fgray*255.0F);
  494. }
  495.     } else {
  496.                 double[] ddata = (double[])inData;
  497. double dgray = ddata[0];
  498.                 if (needAlpha) {
  499.                     double dalp = ddata[1];
  500.     red = green = blue = clamp(dgray*255.0/dalp);
  501.                     alpha = clamp(255.0*dalp);
  502. } else {
  503.     red = green = blue = clamp(dgray*255.0);
  504. }
  505.     }
  506.         } else {
  507.     // Not Gray or sRGB
  508.     float[] norm;
  509.     float[] rgb;
  510.     if (transferType == DataBuffer.TYPE_FLOAT) {
  511. float[] fdata = (float[])inData;
  512. if (needAlpha) {
  513.     float falp = fdata[numColorComponents];
  514.     float invfalp = 1.0F/falp;
  515.     norm = new float[numColorComponents];
  516.     for (int i = 0; i < numColorComponents; i++) {
  517. norm[i] = fdata[i]*invfalp;
  518.     }
  519.                     alpha = clamp(255.0F*falp);
  520. } else {
  521.     norm = fdata;
  522. }
  523.     } else {
  524.                 double[] ddata = (double[])inData;
  525. norm = new float[numColorComponents];
  526. if (needAlpha) {
  527.     double dalp = ddata[numColorComponents];
  528.     double invdalp = 1.0/dalp;
  529.     for (int i = 0; i < numColorComponents; i++) {
  530. norm[i] = (float)(ddata[i]*invdalp);
  531.     }
  532.                     alpha = clamp(255.0*dalp);
  533. } else {
  534.     for (int i = 0; i < numColorComponents; i++) {
  535. norm[i] = (float)ddata[i];
  536.     }
  537. }
  538.     }
  539.             
  540.             // Perform color conversion
  541.     rgb = colorSpace.toRGB(norm);
  542.     red = clamp(rgb[0]*255.0F);
  543.     green = clamp(rgb[1]*255.0F);
  544.     blue = clamp(rgb[2]*255.0F);
  545. }
  546. return (alpha << 24) | (red << 16) | (green << 8) | blue;
  547.     }
  548.     /**
  549.      * Returns a data element array representation of a pixel in this
  550.      * <code>ColorModel</code>, given an integer pixel representation
  551.      * in the default RGB color model.  This array can then be passed
  552.      * to the <code>setDataElements</code> method of a
  553.      * <code>WritableRaster</code> object.  If the <code>pixel</code>
  554.      * parameter is null, a new array is allocated.
  555.      * If the colorSpaceType is of TYPE_GRAY then the rgb components
  556.      * are converted to gray using appropriate weights
  557.      *
  558.      * @param rgb An ARGB value packed into an int.
  559.      * @param pixel The float or double array representation of the pixel.
  560.      *
  561.      * @throws ClassCastException If <code>pixel</code> is not null and 
  562.      * is not a primitive array of type <code>transferType</code>.  
  563.      *
  564.      * @throws ArrayIndexOutOfBoundsException If <code>pixel</code> is 
  565.      * not large enough to hold a pixel value for this
  566.      * <code>ColorModel</code>. 
  567.      */
  568.     public Object getDataElements(int rgb, Object pixel) {
  569.         if (transferType == DataBuffer.TYPE_FLOAT) {
  570.             float[] floatPixel;
  571.             if (pixel == null) {
  572.                 floatPixel = new float[numComponents];
  573.             } else {
  574.                 if (!(pixel instanceof float[])) {
  575.                     throw new ClassCastException(JaiI18N.getString("FloatDoubleColorModel7"));                
  576.                 }
  577.                 floatPixel = (float[])pixel;
  578.                 if (floatPixel.length < numComponents) {
  579.                     throw new ArrayIndexOutOfBoundsException(JaiI18N.getString("FloatDoubleColorModel8"));
  580.                 }
  581.             }
  582.             float inv255 = 1.0F/255.0F;
  583.             if (colorSpace.isCS_sRGB()) {
  584.                 int alp = (rgb >> 24) & 0xff;
  585.                 int red = (rgb >> 16) & 0xff;
  586.                 int grn = (rgb >>  8) & 0xff;
  587.                 int blu = (rgb      ) & 0xff;
  588.                 float norm = inv255;
  589.                 if (isAlphaPremultiplied) {
  590.                     norm *= alp;
  591.                 }
  592.                 floatPixel[0] = red*norm;
  593.                 floatPixel[1] = grn*norm;
  594.                 floatPixel[2] = blu*norm;
  595.                 if (hasAlpha) {
  596.                     floatPixel[3] = alp*inv255;
  597.                 }
  598.             } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
  599.                 float gray = ((((rgb>>16)&0xff)*(.299F*inv255)) +
  600.                               (((rgb>>8) &0xff)*(.587F*inv255)) +
  601.                               (((rgb)    &0xff)*(.114F*inv255)));
  602.                 
  603.                 floatPixel[0] = gray;
  604.                 
  605.                 if (hasAlpha) {
  606.                     int alpha = (rgb>>24) & 0xff;
  607.                     floatPixel[1] = alpha*inv255;
  608.                 }
  609.             } else {
  610.                 // Need to convert the color
  611.                 float[] norm = new float[3];
  612.                 norm[0] = ((rgb>>16) & 0xff)*inv255;
  613.                 norm[1] = ((rgb>>8)  & 0xff)*inv255;
  614.                 norm[2] = ((rgb)     & 0xff)*inv255;
  615.                 
  616.                 norm = colorSpace.fromRGB(norm);
  617.                 for (int i = 0; i < numColorComponents; i++) {
  618.                     floatPixel[i] = norm[i];
  619.                 }
  620.                 if (hasAlpha) {
  621.                     int alpha = (rgb>>24) & 0xff;
  622.                     floatPixel[numColorComponents] = alpha*inv255;
  623.                 }
  624.             }
  625.             return floatPixel;
  626.         } else { // transferType == DataBuffer.TYPE_DOUBLE
  627.             double[] doublePixel;
  628.             if (pixel == null) {
  629.                 doublePixel = new double[numComponents];
  630.             } else {
  631.                 if (!(pixel instanceof double[])) {
  632.                     throw new ClassCastException(JaiI18N.getString("FloatDoubleColorModel7"));                
  633.                 }
  634.                 doublePixel = (double[])pixel;
  635.                 if (doublePixel.length < numComponents) {
  636.                     throw new ArrayIndexOutOfBoundsException(JaiI18N.getString("FloatDoubleColorModel8"));
  637.                 }
  638.             }
  639.             double inv255 = 1.0/255.0;
  640.             if (colorSpace.isCS_sRGB()) {
  641.                 int alp = (rgb>>24) & 0xff;
  642.                 int red = (rgb>>16) & 0xff;
  643.                 int grn = (rgb>>8)  & 0xff;
  644.                 int blu = (rgb)     & 0xff;
  645.                 double norm = inv255;
  646.                 if (isAlphaPremultiplied) {
  647.                     norm *= alp;
  648.                 }
  649.                 doublePixel[0] = red*norm;
  650.                 doublePixel[1] = grn*norm;
  651.                 doublePixel[2] = blu*norm;
  652.                 if (hasAlpha) {
  653.                     doublePixel[3] = alp*inv255;
  654.                 }
  655.             } else if (colorSpaceType == ColorSpace.TYPE_GRAY) {
  656.                 double gray = ((((rgb>>16) & 0xff)*(.299*inv255)) +
  657.                                (((rgb>>8)  & 0xff)*(.587*inv255)) +
  658.                                (((rgb)     & 0xff)*(.114*inv255)));
  659.                 
  660.                 doublePixel[0] = gray;
  661.                 
  662.                 if (hasAlpha) {
  663.                     int alpha = (rgb>>24) & 0xff;
  664.                     doublePixel[1] = alpha*inv255;
  665.                 }
  666.             } else {
  667.                 float inv255F = 1.0F/255.0F;
  668.                 
  669.                 // Need to convert the color, need data in float form
  670.                 float[] norm = new float[3];
  671.                 norm[0] = ((rgb>>16) & 0xff)*inv255F;
  672.                 norm[1] = ((rgb>>8)  & 0xff)*inv255F;
  673.                 norm[2] = ((rgb)     & 0xff)*inv255F;
  674.                 
  675.                 norm = colorSpace.fromRGB(norm);
  676.                 for (int i = 0; i < numColorComponents; i++) {
  677.                     doublePixel[i] = (double)norm[i];
  678.                 }
  679.                 if (hasAlpha) {
  680.                     int alpha = (rgb>>24) & 0xff;
  681.                     doublePixel[numColorComponents] = alpha*inv255;
  682.                 }
  683.             }
  684.             return doublePixel;
  685.         }
  686.     }
  687.     /**
  688.      * Throws an <code>IllegalArgumentException</code>, since pixel
  689.      * values for this <code>ColorModel</code> are not conveniently
  690.      * representable as a single <code>int</code>.
  691.      */
  692.     public int[] getComponents(int pixel, int[] components, int offset) {
  693.         throw new
  694.    IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel9"));
  695.     }
  696.     
  697.     /**
  698.      * Throws an <code>IllegalArgumentException</code> since
  699.      * the pixel values cannot be placed into an <code>int</code> array.
  700.      */
  701.     public int[] getComponents(Object pixel, int[] components, int offset) {
  702.         throw new 
  703.    IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel9"));
  704.     }
  705.     
  706.     /**
  707.      * Throws an <code>IllegalArgumentException</code>, since pixel
  708.      * values for this <code>ColorModel</code> are not conveniently
  709.      * representable as a single <code>int</code>.
  710.      */
  711.     public int getDataElement(int[] components, int offset) {
  712.         throw new
  713.    IllegalArgumentException(JaiI18N.getString("FloatDoubleColorModel9"));
  714.     }
  715.     
  716.     /**
  717.      * Returns a data element array representation of a pixel in this
  718.      * <code>ColorModel</code>, given an array of unnormalized
  719.      * color/alpha components. This array can then be passed to the
  720.      * <code>setDataElements</code> method of a
  721.      * <code>WritableRaster</code> object.
  722.      * 
  723.      * @param components An array of unnormalized color/alpha
  724.      * components.
  725.      * @param offset The integer offset into the
  726.      * <code>components</code> array.
  727.      * @param obj The object in which to store the data element array
  728.      * representation of the pixel. If <code>obj</code> variable is
  729.      * null, a new array is allocated.  If <code>obj</code> is not
  730.      * null, it must be a primitive array of type
  731.      * <code>transferType</code>. An
  732.      * <code>ArrayIndexOutOfBoundsException</code> is thrown if
  733.      * <code>obj</code> is not large enough to hold a pixel value for
  734.      * this <code>ColorModel</code>.
  735.      *
  736.      * @return The data element array representation of a pixel 
  737.      * in this <code>ColorModel</code>.
  738.      *
  739.      * @throws IllegalArgumentException If the components array
  740.      * is not large enough to hold all the color and alpha components
  741.      * (starting at offset).
  742.      * @throws ClassCastException If <code>obj</code> is not null and
  743.      * is not a primitive array of type <code>transferType</code>.
  744.      * @throws ArrayIndexOutOfBoundsException If <code>obj</code> is
  745.      * not large enough to hold a pixel value for this
  746.      * <code>ColorModel</code>.
  747.      */
  748.     public Object getDataElements(int[] components, int offset, Object obj) {
  749.         if ((components.length-offset) < numComponents) {
  750.             throw new IllegalArgumentException(numComponents + " " + 
  751.    JaiI18N.getString("FloatDoubleColorModel10"));
  752.         }
  753.         if (transferType == DataBuffer.TYPE_FLOAT) {
  754.             float[] pixel;
  755.             if (obj == null) {
  756.                 pixel = new float[components.length];
  757.             } else {
  758.                 pixel = (float[])obj;
  759.             }
  760.             for (int i=0; i < numComponents; i++) {
  761.                 pixel[i] = (float)(components[offset + i]);
  762.             }
  763.             return pixel;
  764.         } else {
  765.             double[] pixel;
  766.             if (obj == null) {
  767.                 pixel = new double[components.length];
  768.             } else {
  769.                 pixel = (double[])obj;
  770.             }
  771.             for (int i=0; i < numComponents; i++) {
  772.                 pixel[i] = (double)(components[offset + i]);
  773.             }
  774.             
  775.             return pixel;
  776.         }
  777.     }
  778.     /**
  779.      * Forces the <code>raster</code> data to match the state specified in the
  780.      * <code>isAlphaPremultiplied</code> variable, assuming the data 
  781.      * is currently correctly described by this <code>ColorModel</code>.  
  782.      * It may multiply or divide the color <code>raster</code> data by alpha, or 
  783.      * do nothing if the data is in the correct state.  If the data needs 
  784.      * to be coerced, this method also returns an instance of 
  785.      * <code>FloatDoubleColorModel</code> with
  786.      * the <code>isAlphaPremultiplied</code> flag set appropriately.
  787.      *
  788.      * @throws IllegalArgumentException if transfer type of
  789.      * <code>raster</code> is not the same as that of this
  790.      * <code>FloatDoubleColorModel</code>.
  791.      */
  792.     public ColorModel coerceData (WritableRaster raster, 
  793.                                   boolean isAlphaPremultiplied) {
  794.         if ((hasAlpha == false) ||
  795.             (this.isAlphaPremultiplied == isAlphaPremultiplied))
  796.         {
  797.             // Nothing to do
  798.             return this;
  799.         }
  800.         
  801.         int w = raster.getWidth();
  802.         int h = raster.getHeight();
  803.         int aIdx = raster.getNumBands() - 1;
  804.         int rminX = raster.getMinX();
  805.         int rY = raster.getMinY();
  806.         int rX;
  807.         if (raster.getTransferType() != transferType) {
  808.             throw new IllegalArgumentException(
  809.     JaiI18N.getString("FloatDoubleColorModel6"));
  810.         }
  811.         if (isAlphaPremultiplied) {
  812.             switch (transferType) {
  813.                 case DataBuffer.TYPE_FLOAT: {
  814.                     float pixel[] = null;
  815.                     for (int y = 0; y < h; y++, rY++) {
  816.                         rX = rminX;
  817.                         for (int x = 0; x < w; x++, rX++) {
  818.                             pixel = (float[])raster.getDataElements(rX, rY,
  819.                                                                     pixel);
  820.                             float fAlpha = pixel[aIdx];
  821.                             if (fAlpha != 0) {
  822.                                 for (int c=0; c < aIdx; c++) {
  823.                                     pixel[c] *= fAlpha;
  824.                                 }
  825.                                 raster.setDataElements(rX, rY, pixel);
  826.                             }
  827.                         }
  828.                     }
  829.                 }
  830.                 break;
  831.                
  832.     case DataBuffer.TYPE_DOUBLE: {
  833.                     double pixel[] = null;
  834.                     for (int y = 0; y < h; y++, rY++) {
  835.                         rX = rminX;
  836.                         for (int x = 0; x < w; x++, rX++) {
  837.                             pixel = (double[])raster.getDataElements(rX, rY,
  838.                                                                      pixel);
  839.                             double dAlpha = pixel[aIdx];
  840.                             if (dAlpha != 0) {
  841.                                 for (int c=0; c < aIdx; c++) {
  842.                                     pixel[c] *= dAlpha;
  843.                                 }
  844.                                 raster.setDataElements(rX, rY, pixel);
  845.                             }
  846.                         }
  847.                     }
  848.                 }
  849. break;
  850.     
  851.     default:
  852.       throw new RuntimeException(JaiI18N.getString("FloatDoubleColorModel0"));
  853.         }
  854.         if (isAlphaPremultiplied) {
  855.             }
  856.         }
  857.         else {
  858.             // We are premultiplied and want to divide it out
  859.             switch (transferType) {
  860.                 case DataBuffer.TYPE_FLOAT: {
  861.                     for (int y = 0; y < h; y++, rY++) {
  862.                         rX = rminX;
  863.                         for (int x = 0; x < w; x++, rX++) {
  864.                             float pixel[] = null;
  865.                             pixel = (float[])raster.getDataElements(rX, rY,
  866.                                                                     pixel);
  867.                             float fAlpha = pixel[aIdx];
  868.                             if (fAlpha != 0) {
  869.                                 float invFAlpha = 1.0F/fAlpha;
  870.                                 for (int c=0; c < aIdx; c++) {
  871.                                     pixel[c] *= invFAlpha;
  872.                                 }
  873.                             }
  874.                             raster.setDataElements(rX, rY, pixel);
  875.                         }
  876.                     }
  877.                 }
  878.                 break;
  879.                 
  880.     case DataBuffer.TYPE_DOUBLE: {
  881.                     for (int y = 0; y < h; y++, rY++) {
  882.                         rX = rminX;
  883.                         for (int x = 0; x < w; x++, rX++) {
  884.                             double pixel[] = null;
  885.                             pixel = (double[])raster.getDataElements(rX, rY,
  886.                                                                      pixel);
  887.                             double dAlpha = pixel[aIdx];
  888.                             if (dAlpha != 0) {
  889.                                 double invDAlpha = 1.0/dAlpha;
  890.                                 for (int c=0; c < aIdx; c++) {
  891.                                     pixel[c] *= invDAlpha;
  892.                                 }
  893.                             }
  894.                             raster.setDataElements(rX, rY, pixel);
  895.                         }
  896.                     }
  897.                 }
  898.                 break;
  899.     default:
  900.       throw new RuntimeException(JaiI18N.getString("FloatDoubleColorModel0"));
  901.             }
  902.         }
  903.         // Return a new color model
  904.         return new FloatDoubleColorModel(colorSpace, hasAlpha,
  905.                                          isAlphaPremultiplied, transparency,
  906.                                          transferType);
  907.     }
  908.     /**
  909.      * Returns <code>true</code> if the supplied <code>Raster</code>'s
  910.      * <code>SampleModel</code> is compatible with this
  911.      * <code>FloatDoubleColorModel</code>.
  912.      *
  913.      * @param raster a <code>Raster</code>to be checked for compatibility.
  914.      */
  915.     public boolean isCompatibleRaster(Raster raster) {
  916.         SampleModel sm = raster.getSampleModel();
  917.         return isCompatibleSampleModel(sm);
  918.     }
  919.     
  920.     /**
  921.      * Creates a <code>WritableRaster</code> with the specified width
  922.      * and height, that has a data layout (<code>SampleModel</code>)
  923.      * compatible with this <code>ColorModel</code>.  The returned
  924.      * <code>WritableRaster</code>'s <code>SampleModel</code> will be
  925.      * an instance of <code>ComponentSampleModel</code>.
  926.      *
  927.      * @param w The width of the <code>WritableRaster</code>
  928.      * @param h The height of the <code>WritableRaster</code> 
  929.      *
  930.      * @return A <code>WritableRaster</code> that is compatible with
  931.      * this <code>ColorModel</code>.
  932.      *
  933.      * @see java.awt.image.WritableRaster
  934.      * @see java.awt.image.SampleModel
  935.      */
  936.     public WritableRaster createCompatibleWritableRaster(int w, int h) {
  937.         SampleModel sm = createCompatibleSampleModel(w, h);
  938.         return RasterFactory.createWritableRaster(sm, new Point(0, 0));
  939.     }
  940.     /**
  941.      * Creates a <code>SampleModel</code> with the specified width and
  942.      * height that has a data layout compatible with this
  943.      * <code>ColorModel</code>.  The returned <code>SampleModel</code>
  944.      * will be an instance of <code>ComponentSampleModel</code>.
  945.      *
  946.      * @param w The width of the <code>SampleModel</code>.
  947.      * @param h The height of the <code>SampleModel</code>.
  948.      *
  949.      * @return A <code>SampleModel</code> that is compatible with this
  950.      * <code>ColorModel</code>.
  951.      *
  952.      * @see java.awt.image.SampleModel  
  953.      * @see java.awt.image.ComponentSampleModel  
  954.      */
  955.     public SampleModel createCompatibleSampleModel(int w, int h) {
  956.         int[] bandOffsets = new int[numComponents];
  957.         for (int i = 0; i < numComponents; i++) {
  958.             bandOffsets[i] = i;
  959.         }
  960.         return new ComponentSampleModelJAI(transferType,
  961.                                            w, h,
  962.                                            numComponents,
  963.                                            w*numComponents,
  964.                                            bandOffsets);
  965.     }
  966.     
  967.     /** 
  968.      * Checks whether or not the specified <code>SampleModel</code> is
  969.      * compatible with this <code>ColorModel</code>.  A
  970.      * <code>SampleModel</code> is compatible if it is an instance of
  971.      * <code>ComponentSampleModel</code>, has the sample number of
  972.      * bands as the total number of components (including alpha) in
  973.      * the <code>ColorSpace</code> used by this
  974.      * <code>ColorModel</code>, and has the same data type (float or
  975.      * double) as this <code>ColorModel</code>.
  976.      *
  977.      * @param sm The <code>SampleModel</code> to test for compatibility.
  978.      *
  979.      * @return <code>true</code> if the <code>SampleModel</code> is
  980.      * compatible with this <code>ColorModel</code>,
  981.      * <code>false</code> if it is not.
  982.      *
  983.      * @see java.awt.image.SampleModel
  984.      * @see java.awt.image.ComponentSampleModel
  985.      */
  986.     public boolean isCompatibleSampleModel(SampleModel sm) {
  987.         if (sm instanceof ComponentSampleModel) {
  988.             if (sm.getNumBands() != getNumComponents()) {
  989.                 return false;
  990.             }
  991.             if (sm.getDataType() != transferType) {
  992.                 return false;
  993.             }
  994.             return true;
  995.         } else {
  996.             return false;
  997.         }
  998.     }
  999.     /** Returns a <code>String</code> containing the values of all valid fields. */
  1000.     public String toString() {
  1001.         return "FloatDoubleColorModel: " + super.toString();
  1002.     }
  1003. }