Home » openjdk-7 » java » awt » image » [javadoc | source]

    1   /*
    2    * Copyright (c) 1995, 2001, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.awt.image;
   27   
   28   import java.awt.color.ColorSpace;
   29   import java.awt.Transparency;
   30   
   31   /**
   32    * The <code>DirectColorModel</code> class is a <code>ColorModel</code>
   33    * class that works with pixel values that represent RGB
   34    * color and alpha information as separate samples and that pack all
   35    * samples for a single pixel into a single int, short, or byte quantity.
   36    * This class can be used only with ColorSpaces of type ColorSpace.TYPE_RGB.
   37    * In addition, for each component of the ColorSpace, the minimum
   38    * normalized component value obtained via the <code>getMinValue()</code>
   39    * method of ColorSpace must be 0.0, and the maximum value obtained via
   40    * the <code>getMaxValue()</code> method must be 1.0 (these min/max
   41    * values are typical for RGB spaces).
   42    * There must be three color samples in the pixel values and there can
   43    * be a single alpha sample.  For those methods that use a primitive array
   44    * pixel representation of type <code>transferType</code>, the array
   45    * length is always one.  The transfer
   46    * types supported are DataBuffer.TYPE_BYTE,
   47    * DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT.
   48    * Color and alpha samples are stored in the single
   49    * element of the array in bits indicated by bit masks.  Each bit mask
   50    * must be contiguous and masks must not overlap.  The same masks apply to
   51    * the single int pixel representation used by other methods.  The
   52    * correspondence of masks and color/alpha samples is as follows:
   53    * <ul>
   54    * <li> Masks are identified by indices running from 0 through 2
   55    * if no alpha is present, or 3 if an alpha is present.
   56    * <li> The first three indices refer to color samples;
   57    * index 0 corresponds to red, index 1 to green, and index 2 to blue.
   58    * <li> Index 3 corresponds to the alpha sample, if present.
   59    * </ul>
   60    * <p>
   61    * The translation from pixel values to color/alpha components for
   62    * display or processing purposes is a one-to-one correspondence of
   63    * samples to components.  A <code>DirectColorModel</code> is
   64    * typically used with image data which uses masks to define packed
   65    * samples.  For example, a <code>DirectColorModel</code> can be used in
   66    * conjunction with a <code>SinglePixelPackedSampleModel</code> to
   67    * construct a {@link BufferedImage}.  Normally the masks used by the
   68    * {@link SampleModel} and the <code>ColorModel</code> would be the
   69    * same.  However, if they are different, the color interpretation
   70    * of pixel data will be done according to the masks of the
   71    * <code>ColorModel</code>.
   72    * <p>
   73    * A single int pixel representation is valid for all objects of this
   74    * class, since it is always possible to represent pixel values used with
   75    * this class in a single int.  Therefore, methods which use this
   76    * representation will not throw an <code>IllegalArgumentException</code>
   77    * due to an invalid pixel value.
   78    * <p>
   79    * This color model is similar to an X11 TrueColor visual.
   80    * The default RGB ColorModel specified by the
   81    * {@link ColorModel#getRGBdefault() getRGBdefault} method is a
   82    * <code>DirectColorModel</code> with the following parameters:
   83    * <pre>
   84    * Number of bits:        32
   85    * Red mask:              0x00ff0000
   86    * Green mask:            0x0000ff00
   87    * Blue mask:             0x000000ff
   88    * Alpha mask:            0xff000000
   89    * Color space:           sRGB
   90    * isAlphaPremultiplied:  False
   91    * Transparency:          Transparency.TRANSLUCENT
   92    * transferType:          DataBuffer.TYPE_INT
   93    * </pre>
   94    * <p>
   95    * Many of the methods in this class are final. This is because the
   96    * underlying native graphics code makes assumptions about the layout
   97    * and operation of this class and those assumptions are reflected in
   98    * the implementations of the methods here that are marked final.  You
   99    * can subclass this class for other reasons, but you cannot override
  100    * or modify the behavior of those methods.
  101    *
  102    * @see ColorModel
  103    * @see ColorSpace
  104    * @see SinglePixelPackedSampleModel
  105    * @see BufferedImage
  106    * @see ColorModel#getRGBdefault
  107    *
  108    */
  109   public class DirectColorModel extends PackedColorModel {
  110       private int red_mask;
  111       private int green_mask;
  112       private int blue_mask;
  113       private int alpha_mask;
  114       private int red_offset;
  115       private int green_offset;
  116       private int blue_offset;
  117       private int alpha_offset;
  118       private int red_scale;
  119       private int green_scale;
  120       private int blue_scale;
  121       private int alpha_scale;
  122       private boolean is_LinearRGB;
  123       private int lRGBprecision;
  124       private byte[] tosRGB8LUT;
  125       private byte[] fromsRGB8LUT8;
  126       private short[] fromsRGB8LUT16;
  127   
  128       /**
  129        * Constructs a <code>DirectColorModel</code> from the specified masks
  130        * that indicate which bits in an <code>int</code> pixel representation
  131        * contain the red, green and blue color samples.  As pixel values do not
  132        * contain alpha information, all pixels are treated as opaque, which
  133        * means that alpha&nbsp;=&nbsp;1.0.  All of the bits
  134        * in each mask must be contiguous and fit in the specified number
  135        * of least significant bits of an <code>int</code> pixel representation.
  136        *  The <code>ColorSpace</code> is the default sRGB space. The
  137        * transparency value is Transparency.OPAQUE.  The transfer type
  138        * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  139        * or DataBuffer.TYPE_INT that can hold a single pixel.
  140        * @param bits the number of bits in the pixel values; for example,
  141        *         the sum of the number of bits in the masks.
  142        * @param rmask specifies a mask indicating which bits in an
  143        *         integer pixel contain the red component
  144        * @param gmask specifies a mask indicating which bits in an
  145        *         integer pixel contain the green component
  146        * @param bmask specifies a mask indicating which bits in an
  147        *         integer pixel contain the blue component
  148        *
  149        */
  150       public DirectColorModel(int bits,
  151                               int rmask, int gmask, int bmask) {
  152           this(bits, rmask, gmask, bmask, 0);
  153       }
  154   
  155       /**
  156        * Constructs a <code>DirectColorModel</code> from the specified masks
  157        * that indicate which bits in an <code>int</code> pixel representation
  158        * contain the red, green and blue color samples and the alpha sample,
  159        * if present.  If <code>amask</code> is 0, pixel values do not contain
  160        * alpha information and all pixels are treated as opaque, which means
  161        * that alpha&nbsp;=&nbsp;1.0.  All of the bits in each mask must
  162        * be contiguous and fit in the specified number of least significant bits
  163        * of an <code>int</code> pixel representation.  Alpha, if present, is not
  164        * premultiplied.  The <code>ColorSpace</code> is the default sRGB space.
  165        * The transparency value is Transparency.OPAQUE if no alpha is
  166        * present, or Transparency.TRANSLUCENT otherwise.  The transfer type
  167        * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
  168        * or DataBuffer.TYPE_INT that can hold a single pixel.
  169        * @param bits the number of bits in the pixel values; for example,
  170        *         the sum of the number of bits in the masks.
  171        * @param rmask specifies a mask indicating which bits in an
  172        *         integer pixel contain the red component
  173        * @param gmask specifies a mask indicating which bits in an
  174        *         integer pixel contain the green component
  175        * @param bmask specifies a mask indicating which bits in an
  176        *         integer pixel contain the blue component
  177        * @param amask specifies a mask indicating which bits in an
  178        *         integer pixel contain the alpha component
  179        */
  180       public DirectColorModel(int bits, int rmask, int gmask,
  181                               int bmask, int amask) {
  182           super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
  183                  bits, rmask, gmask, bmask, amask, false,
  184                  amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
  185                  ColorModel.getDefaultTransferType(bits));
  186           setFields();
  187       }
  188   
  189       /**
  190        * Constructs a <code>DirectColorModel</code> from the specified
  191        * parameters.  Color components are in the specified
  192        * <code>ColorSpace</code>, which must be of type ColorSpace.TYPE_RGB
  193        * and have minimum normalized component values which are all 0.0
  194        * and maximum values which are all 1.0.
  195        * The masks specify which bits in an <code>int</code> pixel
  196        * representation contain the red, green and blue color samples and
  197        * the alpha sample, if present.  If <code>amask</code> is 0, pixel
  198        * values do not contain alpha information and all pixels are treated
  199        * as opaque, which means that alpha&nbsp;=&nbsp;1.0.  All of the
  200        * bits in each mask must be contiguous and fit in the specified number
  201        * of least significant bits of an <code>int</code> pixel
  202        * representation.  If there is alpha, the <code>boolean</code>
  203        * <code>isAlphaPremultiplied</code> specifies how to interpret
  204        * color and alpha samples in pixel values.  If the <code>boolean</code>
  205        * is <code>true</code>, color samples are assumed to have been
  206        * multiplied by the alpha sample.  The transparency value is
  207        * Transparency.OPAQUE, if no alpha is present, or
  208        * Transparency.TRANSLUCENT otherwise.  The transfer type
  209        * is the type of primitive array used to represent pixel values and
  210        * must be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
  211        * DataBuffer.TYPE_INT.
  212        * @param space the specified <code>ColorSpace</code>
  213        * @param bits the number of bits in the pixel values; for example,
  214        *         the sum of the number of bits in the masks.
  215        * @param rmask specifies a mask indicating which bits in an
  216        *         integer pixel contain the red component
  217        * @param gmask specifies a mask indicating which bits in an
  218        *         integer pixel contain the green component
  219        * @param bmask specifies a mask indicating which bits in an
  220        *         integer pixel contain the blue component
  221        * @param amask specifies a mask indicating which bits in an
  222        *         integer pixel contain the alpha component
  223        * @param isAlphaPremultiplied <code>true</code> if color samples are
  224        *        premultiplied by the alpha sample; <code>false</code> otherwise
  225        * @param transferType the type of array used to represent pixel values
  226        * @throws IllegalArgumentException if <code>space</code> is not a
  227        *         TYPE_RGB space or if the min/max normalized component
  228        *         values are not 0.0/1.0.
  229        */
  230       public DirectColorModel(ColorSpace space, int bits, int rmask,
  231                               int gmask, int bmask, int amask,
  232                               boolean isAlphaPremultiplied,
  233                               int transferType) {
  234           super (space, bits, rmask, gmask, bmask, amask,
  235                  isAlphaPremultiplied,
  236                  amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
  237                  transferType);
  238           if (ColorModel.isLinearRGBspace(colorSpace)) {
  239               is_LinearRGB = true;
  240               if (maxBits <= 8) {
  241                   lRGBprecision = 8;
  242                   tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT();
  243                   fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT();
  244               } else {
  245                   lRGBprecision = 16;
  246                   tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT();
  247                   fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT();
  248               }
  249           } else if (!is_sRGB) {
  250               for (int i = 0; i < 3; i++) {
  251                   // super constructor checks that space is TYPE_RGB
  252                   // check here that min/max are all 0.0/1.0
  253                   if ((space.getMinValue(i) != 0.0f) ||
  254                       (space.getMaxValue(i) != 1.0f)) {
  255                       throw new IllegalArgumentException(
  256                           "Illegal min/max RGB component value");
  257                   }
  258               }
  259           }
  260           setFields();
  261       }
  262   
  263       /**
  264        * Returns the mask indicating which bits in an <code>int</code> pixel
  265        * representation contain the red color component.
  266        * @return the mask, which indicates which bits of the <code>int</code>
  267        *         pixel representation contain the red color sample.
  268        */
  269       final public int getRedMask() {
  270           return maskArray[0];
  271       }
  272   
  273       /**
  274        * Returns the mask indicating which bits in an <code>int</code> pixel
  275        * representation contain the green color component.
  276        * @return the mask, which indicates which bits of the <code>int</code>
  277        *         pixel representation contain the green color sample.
  278        */
  279       final public int getGreenMask() {
  280           return maskArray[1];
  281       }
  282   
  283       /**
  284        * Returns the mask indicating which bits in an <code>int</code> pixel
  285        * representation contain the blue color component.
  286        * @return the mask, which indicates which bits of the <code>int</code>
  287        *         pixel representation contain the blue color sample.
  288        */
  289       final public int getBlueMask() {
  290           return maskArray[2];
  291       }
  292   
  293       /**
  294        * Returns the mask indicating which bits in an <code>int</code> pixel
  295        * representation contain the alpha component.
  296        * @return the mask, which indicates which bits of the <code>int</code>
  297        *         pixel representation contain the alpha sample.
  298        */
  299       final public int getAlphaMask() {
  300           if (supportsAlpha) {
  301               return maskArray[3];
  302           } else {
  303               return 0;
  304           }
  305       }
  306   
  307   
  308       /*
  309        * Given an int pixel in this ColorModel's ColorSpace, converts
  310        * it to the default sRGB ColorSpace and returns the R, G, and B
  311        * components as float values between 0.0 and 1.0.
  312        */
  313       private float[] getDefaultRGBComponents(int pixel) {
  314           int components[] = getComponents(pixel, null, 0);
  315           float norm[] = getNormalizedComponents(components, 0, null, 0);
  316           // Note that getNormalizedComponents returns non-premultiplied values
  317           return colorSpace.toRGB(norm);
  318       }
  319   
  320   
  321       private int getsRGBComponentFromsRGB(int pixel, int idx) {
  322           int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
  323           if (isAlphaPremultiplied) {
  324               int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  325               c = (a == 0) ? 0 :
  326                            (int) (((c * scaleFactors[idx]) * 255.0f /
  327                                    (a * scaleFactors[3])) + 0.5f);
  328           } else if (scaleFactors[idx] != 1.0f) {
  329               c = (int) ((c * scaleFactors[idx]) + 0.5f);
  330           }
  331           return c;
  332       }
  333   
  334   
  335       private int getsRGBComponentFromLinearRGB(int pixel, int idx) {
  336           int c = ((pixel & maskArray[idx]) >>> maskOffsets[idx]);
  337           if (isAlphaPremultiplied) {
  338               float factor = (float) ((1 << lRGBprecision) - 1);
  339               int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  340               c = (a == 0) ? 0 :
  341                            (int) (((c * scaleFactors[idx]) * factor /
  342                                    (a * scaleFactors[3])) + 0.5f);
  343           } else if (nBits[idx] != lRGBprecision) {
  344               if (lRGBprecision == 16) {
  345                   c = (int) ((c * scaleFactors[idx] * 257.0f) + 0.5f);
  346               } else {
  347                   c = (int) ((c * scaleFactors[idx]) + 0.5f);
  348               }
  349           }
  350           // now range of c is 0-255 or 0-65535, depending on lRGBprecision
  351           return tosRGB8LUT[c] & 0xff;
  352       }
  353   
  354   
  355       /**
  356        * Returns the red color component for the specified pixel, scaled
  357        * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
  358        * color conversion is done if necessary.  The pixel value is specified
  359        * as an <code>int</code>.
  360        * The returned value is a non pre-multiplied value.  Thus, if the
  361        * alpha is premultiplied, this method divides it out before returning
  362        * the value.  If the alpha value is 0, for example, the red value
  363        * is 0.
  364        * @param pixel the specified pixel
  365        * @return the red color component for the specified pixel, from
  366        *         0 to 255 in the sRGB <code>ColorSpace</code>.
  367        */
  368       final public int getRed(int pixel) {
  369           if (is_sRGB) {
  370               return getsRGBComponentFromsRGB(pixel, 0);
  371           } else if (is_LinearRGB) {
  372               return getsRGBComponentFromLinearRGB(pixel, 0);
  373           }
  374           float rgb[] = getDefaultRGBComponents(pixel);
  375           return (int) (rgb[0] * 255.0f + 0.5f);
  376       }
  377   
  378       /**
  379        * Returns the green color component for the specified pixel, scaled
  380        * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
  381        * color conversion is done if necessary.  The pixel value is specified
  382        * as an <code>int</code>.
  383        * The returned value is a non pre-multiplied value.  Thus, if the
  384        * alpha is premultiplied, this method divides it out before returning
  385        * the value.  If the alpha value is 0, for example, the green value
  386        * is 0.
  387        * @param pixel the specified pixel
  388        * @return the green color component for the specified pixel, from
  389        *         0 to 255 in the sRGB <code>ColorSpace</code>.
  390        */
  391       final public int getGreen(int pixel) {
  392           if (is_sRGB) {
  393               return getsRGBComponentFromsRGB(pixel, 1);
  394           } else if (is_LinearRGB) {
  395               return getsRGBComponentFromLinearRGB(pixel, 1);
  396           }
  397           float rgb[] = getDefaultRGBComponents(pixel);
  398           return (int) (rgb[1] * 255.0f + 0.5f);
  399       }
  400   
  401       /**
  402        * Returns the blue color component for the specified pixel, scaled
  403        * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
  404        * color conversion is done if necessary.  The pixel value is specified
  405        * as an <code>int</code>.
  406        * The returned value is a non pre-multiplied value.  Thus, if the
  407        * alpha is premultiplied, this method divides it out before returning
  408        * the value.  If the alpha value is 0, for example, the blue value
  409        * is 0.
  410        * @param pixel the specified pixel
  411        * @return the blue color component for the specified pixel, from
  412        *         0 to 255 in the sRGB <code>ColorSpace</code>.
  413        */
  414       final public int getBlue(int pixel) {
  415           if (is_sRGB) {
  416               return getsRGBComponentFromsRGB(pixel, 2);
  417           } else if (is_LinearRGB) {
  418               return getsRGBComponentFromLinearRGB(pixel, 2);
  419           }
  420           float rgb[] = getDefaultRGBComponents(pixel);
  421           return (int) (rgb[2] * 255.0f + 0.5f);
  422       }
  423   
  424       /**
  425        * Returns the alpha component for the specified pixel, scaled
  426        * from 0 to 255.  The pixel value is specified as an <code>int</code>.
  427        * @param pixel the specified pixel
  428        * @return the value of the alpha component of <code>pixel</code>
  429        *         from 0 to 255.
  430        */
  431       final public int getAlpha(int pixel) {
  432           if (!supportsAlpha) return 255;
  433           int a = ((pixel & maskArray[3]) >>> maskOffsets[3]);
  434           if (scaleFactors[3] != 1.0f) {
  435               a = (int)(a * scaleFactors[3] + 0.5f);
  436           }
  437           return a;
  438       }
  439   
  440       /**
  441        * Returns the color/alpha components of the pixel in the default
  442        * RGB color model format.  A color conversion is done if necessary.
  443        * The pixel value is specified as an <code>int</code>.
  444        * The returned value is in a non pre-multiplied format.  Thus, if
  445        * the alpha is premultiplied, this method divides it out of the
  446        * color components.  If the alpha value is 0, for example, the color
  447        * values are each 0.
  448        * @param pixel the specified pixel
  449        * @return the RGB value of the color/alpha components of the specified
  450        *         pixel.
  451        * @see ColorModel#getRGBdefault
  452        */
  453       final public int getRGB(int pixel) {
  454           if (is_sRGB || is_LinearRGB) {
  455               return (getAlpha(pixel) << 24)
  456                   | (getRed(pixel) << 16)
  457                   | (getGreen(pixel) << 8)
  458                   | (getBlue(pixel) << 0);
  459           }
  460           float rgb[] = getDefaultRGBComponents(pixel);
  461           return (getAlpha(pixel) << 24)
  462               | (((int) (rgb[0] * 255.0f + 0.5f)) << 16)
  463               | (((int) (rgb[1] * 255.0f + 0.5f)) << 8)
  464               | (((int) (rgb[2] * 255.0f + 0.5f)) << 0);
  465       }
  466   
  467       /**
  468        * Returns the red color component for the specified pixel, scaled
  469        * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
  470        * color conversion is done if necessary.  The pixel value is specified
  471        * by an array of data elements of type <code>transferType</code> passed
  472        * in as an object reference.
  473        * The returned value is a non pre-multiplied value.  Thus, if the
  474        * alpha is premultiplied, this method divides it out before returning
  475        * the value.  If the alpha value is 0, for example, the red value
  476        * is 0.
  477        * If <code>inData</code> is not a primitive array of type
  478        * <code>transferType</code>, a <code>ClassCastException</code> is
  479        * thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
  480        * thrown if <code>inData</code> is not large enough to hold a
  481        * pixel value for this <code>ColorModel</code>.  Since
  482        * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  483        * the implementation of this method and if they don't override it
  484        * then they throw an exception if they use an unsupported
  485        * <code>transferType</code>.
  486        * An <code>UnsupportedOperationException</code> is thrown if this
  487        * <code>transferType</code> is not supported by this
  488        * <code>ColorModel</code>.
  489        * @param inData the array containing the pixel value
  490        * @return the value of the red component of the specified pixel.
  491        * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
  492        *         large enough to hold a pixel value for this color model
  493        * @throws ClassCastException if <code>inData</code> is not a
  494        *         primitive array of type <code>transferType</code>
  495        * @throws UnsupportedOperationException if this <code>transferType</code>
  496        *         is not supported by this color model
  497        */
  498       public int getRed(Object inData) {
  499           int pixel=0;
  500           switch (transferType) {
  501               case DataBuffer.TYPE_BYTE:
  502                  byte bdata[] = (byte[])inData;
  503                  pixel = bdata[0] & 0xff;
  504               break;
  505               case DataBuffer.TYPE_USHORT:
  506                  short sdata[] = (short[])inData;
  507                  pixel = sdata[0] & 0xffff;
  508               break;
  509               case DataBuffer.TYPE_INT:
  510                  int idata[] = (int[])inData;
  511                  pixel = idata[0];
  512               break;
  513               default:
  514                  throw new UnsupportedOperationException("This method has not been "+
  515                      "implemented for transferType " + transferType);
  516           }
  517           return getRed(pixel);
  518       }
  519   
  520   
  521       /**
  522        * Returns the green color component for the specified pixel, scaled
  523        * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
  524        * color conversion is done if necessary.  The pixel value is specified
  525        * by an array of data elements of type <code>transferType</code> passed
  526        * in as an object reference.
  527        * The returned value is a non pre-multiplied value.  Thus, if the
  528        * alpha is premultiplied, this method divides it out before returning
  529        * the value.  If the alpha value is 0, for example, the green value
  530        * is 0.  If <code>inData</code> is not a primitive array of type
  531        * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
  532        *  An <code>ArrayIndexOutOfBoundsException</code> is
  533        * thrown if <code>inData</code> is not large enough to hold a pixel
  534        * value for this <code>ColorModel</code>.  Since
  535        * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  536        * the implementation of this method and if they don't override it
  537        * then they throw an exception if they use an unsupported
  538        * <code>transferType</code>.
  539        * An <code>UnsupportedOperationException</code> is
  540        * thrown if this <code>transferType</code> is not supported by this
  541        * <code>ColorModel</code>.
  542        * @param inData the array containing the pixel value
  543        * @return the value of the green component of the specified pixel.
  544        * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
  545        *         large enough to hold a pixel value for this color model
  546        * @throws ClassCastException if <code>inData</code> is not a
  547        *         primitive array of type <code>transferType</code>
  548        * @throws UnsupportedOperationException if this <code>transferType</code>
  549        *         is not supported by this color model
  550        */
  551       public int getGreen(Object inData) {
  552           int pixel=0;
  553           switch (transferType) {
  554               case DataBuffer.TYPE_BYTE:
  555                  byte bdata[] = (byte[])inData;
  556                  pixel = bdata[0] & 0xff;
  557               break;
  558               case DataBuffer.TYPE_USHORT:
  559                  short sdata[] = (short[])inData;
  560                  pixel = sdata[0] & 0xffff;
  561               break;
  562               case DataBuffer.TYPE_INT:
  563                  int idata[] = (int[])inData;
  564                  pixel = idata[0];
  565               break;
  566               default:
  567                  throw new UnsupportedOperationException("This method has not been "+
  568                      "implemented for transferType " + transferType);
  569           }
  570           return getGreen(pixel);
  571       }
  572   
  573   
  574       /**
  575        * Returns the blue color component for the specified pixel, scaled
  576        * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB.  A
  577        * color conversion is done if necessary.  The pixel value is specified
  578        * by an array of data elements of type <code>transferType</code> passed
  579        * in as an object reference.
  580        * The returned value is a non pre-multiplied value.  Thus, if the
  581        * alpha is premultiplied, this method divides it out before returning
  582        * the value.  If the alpha value is 0, for example, the blue value
  583        * is 0.  If <code>inData</code> is not a primitive array of type
  584        * <code>transferType</code>, a <code>ClassCastException</code> is thrown.
  585        *  An <code>ArrayIndexOutOfBoundsException</code> is
  586        * thrown if <code>inData</code> is not large enough to hold a pixel
  587        * value for this <code>ColorModel</code>.  Since
  588        * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  589        * the implementation of this method and if they don't override it
  590        * then they throw an exception if they use an unsupported
  591        * <code>transferType</code>.
  592        * An <code>UnsupportedOperationException</code> is
  593        * thrown if this <code>transferType</code> is not supported by this
  594        * <code>ColorModel</code>.
  595        * @param inData the array containing the pixel value
  596        * @return the value of the blue component of the specified pixel.
  597        * @throws ArrayIndexOutOfBoundsException if <code>inData</code> is not
  598        *         large enough to hold a pixel value for this color model
  599        * @throws ClassCastException if <code>inData</code> is not a
  600        *         primitive array of type <code>transferType</code>
  601        * @throws UnsupportedOperationException if this <code>transferType</code>
  602        *         is not supported by this color model
  603        */
  604       public int getBlue(Object inData) {
  605           int pixel=0;
  606           switch (transferType) {
  607               case DataBuffer.TYPE_BYTE:
  608                  byte bdata[] = (byte[])inData;
  609                  pixel = bdata[0] & 0xff;
  610               break;
  611               case DataBuffer.TYPE_USHORT:
  612                  short sdata[] = (short[])inData;
  613                  pixel = sdata[0] & 0xffff;
  614               break;
  615               case DataBuffer.TYPE_INT:
  616                  int idata[] = (int[])inData;
  617                  pixel = idata[0];
  618               break;
  619               default:
  620                  throw new UnsupportedOperationException("This method has not been "+
  621                      "implemented for transferType " + transferType);
  622           }
  623           return getBlue(pixel);
  624       }
  625   
  626       /**
  627        * Returns the alpha component for the specified pixel, scaled
  628        * from 0 to 255.  The pixel value is specified by an array of data
  629        * elements of type <code>transferType</code> passed in as an object
  630        * reference.
  631        * If <code>inData</code> is not a primitive array of type
  632        * <code>transferType</code>, a <code>ClassCastException</code> is
  633        * thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
  634        * thrown if <code>inData</code> is not large enough to hold a pixel
  635        * value for this <code>ColorModel</code>.  Since
  636        * <code>DirectColorModel</code> can be subclassed, subclasses inherit
  637        * the implementation of this method and if they don't override it
  638        * then they throw an exception if they use an unsupported
  639        * <code>transferType</code>.
  640        * If this <code>transferType</code> is not supported, an
  641        * <code>UnsupportedOperationException</code> is thrown.
  642        * @param inData the specified pixel
  643        * @return the alpha component of the specified pixel, scaled from
  644        *         0 to 255.
  645        * @exception <code>ClassCastException</code> if <code>inData</code>
  646        *  is not a primitive array of type <code>transferType</code>
  647        * @exception <code>ArrayIndexOutOfBoundsException</code> if
  648        *  <code>inData</code> is not large enough to hold a pixel value
  649        *  for this <code>ColorModel</code>
  650        * @exception <code>UnsupportedOperationException</code> if this
  651        *  <code>tranferType</code> is not supported by this
  652        *  <code>ColorModel</code>
  653        */
  654       public int getAlpha(Object inData) {
  655           int pixel=0;
  656           switch (transferType) {
  657               case DataBuffer.TYPE_BYTE:
  658                  byte bdata[] = (byte[])inData;
  659                  pixel = bdata[0] & 0xff;
  660               break;
  661               case DataBuffer.TYPE_USHORT:
  662                  short sdata[] = (short[])inData;
  663                  pixel = sdata[0] & 0xffff;
  664               break;
  665               case DataBuffer.TYPE_INT:
  666                  int idata[] = (int[])inData;
  667                  pixel = idata[0];
  668               break;
  669               default:
  670                  throw new UnsupportedOperationException("This method has not been "+
  671                      "implemented for transferType " + transferType);
  672           }
  673           return getAlpha(pixel);
  674       }
  675   
  676       /**
  677        * Returns the color/alpha components for the specified pixel in the
  678        * default RGB color model format.  A color conversion is done if
  679        * necessary.  The pixel value is specified by an array of data
  680        * elements of type <code>transferType</code> passed in as an object
  681        * reference.  If <code>inData</code> is not a primitive array of type
  682        * <code>transferType</code>, a <code>ClassCastException</code> is
  683        * thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
  684        * thrown if <code>inData</code> is not large enough to hold a pixel
  685        * value for this <code>ColorModel</code>.
  686        * The returned value is in a non pre-multiplied format.  Thus, if
  687        * the alpha is premultiplied, this method divides it out of the
  688        * color components.  If the alpha value is 0, for example, the color
  689        * values is 0.  Since <code>DirectColorModel</code> can be
  690        * subclassed, subclasses inherit the implementation of this method
  691        * and if they don't override it then
  692        * they throw an exception if they use an unsupported
  693        * <code>transferType</code>.
  694        *
  695        * @param inData the specified pixel
  696        * @return the color and alpha components of the specified pixel.
  697        * @exception UnsupportedOperationException if this
  698        *            <code>transferType</code> is not supported by this
  699        *            <code>ColorModel</code>
  700        * @see ColorModel#getRGBdefault
  701        */
  702       public int getRGB(Object inData) {
  703           int pixel=0;
  704           switch (transferType) {
  705               case DataBuffer.TYPE_BYTE:
  706                  byte bdata[] = (byte[])inData;
  707                  pixel = bdata[0] & 0xff;
  708               break;
  709               case DataBuffer.TYPE_USHORT:
  710                  short sdata[] = (short[])inData;
  711                  pixel = sdata[0] & 0xffff;
  712               break;
  713               case DataBuffer.TYPE_INT:
  714                  int idata[] = (int[])inData;
  715                  pixel = idata[0];
  716               break;
  717               default:
  718                  throw new UnsupportedOperationException("This method has not been "+
  719                      "implemented for transferType " + transferType);
  720           }
  721           return getRGB(pixel);
  722       }
  723   
  724       /**
  725        * Returns a data element array representation of a pixel in this
  726        * <code>ColorModel</code>, given an integer pixel representation in the
  727        * default RGB color model.
  728        * This array can then be passed to the <code>setDataElements</code>
  729        * method of a <code>WritableRaster</code> object.  If the pixel variable
  730        * is <code>null</code>, a new array is allocated.  If <code>pixel</code>
  731        * is not <code>null</code>, it must be a primitive array of type
  732        * <code>transferType</code>; otherwise, a
  733        * <code>ClassCastException</code> is thrown.  An
  734        * <code>ArrayIndexOutOfBoundsException</code> is
  735        * thrown if <code>pixel</code> is not large enough to hold a pixel
  736        * value for this <code>ColorModel</code>.  The pixel array is returned.
  737        * Since <code>DirectColorModel</code> can be subclassed, subclasses
  738        * inherit the implementation of this method and if they don't
  739        * override it then they throw an exception if they use an unsupported
  740        * <code>transferType</code>.
  741        *
  742        * @param rgb the integer pixel representation in the default RGB
  743        *            color model
  744        * @param pixel the specified pixel
  745        * @return an array representation of the specified pixel in this
  746        *         <code>ColorModel</code>
  747        * @exception ClassCastException if <code>pixel</code>
  748        *  is not a primitive array of type <code>transferType</code>
  749        * @exception ArrayIndexOutOfBoundsException if
  750        *  <code>pixel</code> is not large enough to hold a pixel value
  751        *  for this <code>ColorModel</code>
  752        * @exception UnsupportedOperationException if this
  753        *  <code>transferType</code> is not supported by this
  754        *  <code>ColorModel</code>
  755        * @see WritableRaster#setDataElements
  756        * @see SampleModel#setDataElements
  757        */
  758       public Object getDataElements(int rgb, Object pixel) {
  759           //REMIND: maybe more efficient not to use int array for
  760           //DataBuffer.TYPE_USHORT and DataBuffer.TYPE_INT
  761           int intpixel[] = null;
  762           if (transferType == DataBuffer.TYPE_INT &&
  763               pixel != null) {
  764               intpixel = (int[])pixel;
  765               intpixel[0] = 0;
  766           } else {
  767               intpixel = new int[1];
  768           }
  769   
  770           ColorModel defaultCM = ColorModel.getRGBdefault();
  771           if (this == defaultCM || equals(defaultCM)) {
  772               intpixel[0] = rgb;
  773               return intpixel;
  774           }
  775   
  776           int red, grn, blu, alp;
  777           red = (rgb>>16) & 0xff;
  778           grn = (rgb>>8) & 0xff;
  779           blu = rgb & 0xff;
  780           if (is_sRGB || is_LinearRGB) {
  781               int precision;
  782               float factor;
  783               if (is_LinearRGB) {
  784                   if (lRGBprecision == 8) {
  785                       red = fromsRGB8LUT8[red] & 0xff;
  786                       grn = fromsRGB8LUT8[grn] & 0xff;
  787                       blu = fromsRGB8LUT8[blu] & 0xff;
  788                       precision = 8;
  789                       factor = 1.0f / 255.0f;
  790                   } else {
  791                       red = fromsRGB8LUT16[red] & 0xffff;
  792                       grn = fromsRGB8LUT16[grn] & 0xffff;
  793                       blu = fromsRGB8LUT16[blu] & 0xffff;
  794                       precision = 16;
  795                       factor = 1.0f / 65535.0f;
  796                   }
  797               } else {
  798                   precision = 8;
  799                   factor = 1.0f / 255.0f;
  800               }
  801               if (supportsAlpha) {
  802                   alp = (rgb>>24) & 0xff;
  803                   if (isAlphaPremultiplied) {
  804                       factor *= (alp * (1.0f / 255.0f));
  805                       precision = -1;  // force component calculations below
  806                   }
  807                   if (nBits[3] != 8) {
  808                       alp = (int)
  809                           ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
  810                       if (alp > ((1<<nBits[3]) - 1)) {
  811                           // fix 4412670 - see comment below
  812                           alp = (1<<nBits[3]) - 1;
  813                       }
  814                   }
  815                   intpixel[0] = alp << maskOffsets[3];
  816               }
  817               if (nBits[0] != precision) {
  818                   red = (int) ((red * factor * ((1<<nBits[0]) - 1)) + 0.5f);
  819               }
  820               if (nBits[1] != precision) {
  821                   grn = (int) ((grn * factor * ((1<<nBits[1]) - 1)) + 0.5f);
  822               }
  823               if (nBits[2] != precision) {
  824                   blu = (int) ((blu * factor * ((1<<nBits[2]) - 1)) + 0.5f);
  825               }
  826           } else {
  827               // Need to convert the color
  828               float[] norm = new float[3];
  829               float factor = 1.0f / 255.0f;
  830               norm[0] = red * factor;
  831               norm[1] = grn * factor;
  832               norm[2] = blu * factor;
  833               norm = colorSpace.fromRGB(norm);
  834               if (supportsAlpha) {
  835                   alp = (rgb>>24) & 0xff;
  836                   if (isAlphaPremultiplied) {
  837                       factor *= alp;
  838                       for (int i = 0; i < 3; i++) {
  839                           norm[i] *= factor;
  840                       }
  841                   }
  842                   if (nBits[3] != 8) {
  843                       alp = (int)
  844                           ((alp * (1.0f / 255.0f) * ((1<<nBits[3]) - 1)) + 0.5f);
  845                       if (alp > ((1<<nBits[3]) - 1)) {
  846                           // fix 4412670 - see comment below
  847                           alp = (1<<nBits[3]) - 1;
  848                       }
  849                   }
  850                   intpixel[0] = alp << maskOffsets[3];
  851               }
  852               red = (int) ((norm[0] * ((1<<nBits[0]) - 1)) + 0.5f);
  853               grn = (int) ((norm[1] * ((1<<nBits[1]) - 1)) + 0.5f);
  854               blu = (int) ((norm[2] * ((1<<nBits[2]) - 1)) + 0.5f);
  855           }
  856   
  857           if (maxBits > 23) {
  858               // fix 4412670 - for components of 24 or more bits
  859               // some calculations done above with float precision
  860               // may lose enough precision that the integer result
  861               // overflows nBits, so we need to clamp.
  862               if (red > ((1<<nBits[0]) - 1)) {
  863                   red = (1<<nBits[0]) - 1;
  864               }
  865               if (grn > ((1<<nBits[1]) - 1)) {
  866                   grn = (1<<nBits[1]) - 1;
  867               }
  868               if (blu > ((1<<nBits[2]) - 1)) {
  869                   blu = (1<<nBits[2]) - 1;
  870               }
  871           }
  872   
  873           intpixel[0] |= (red << maskOffsets[0]) |
  874                          (grn << maskOffsets[1]) |
  875                          (blu << maskOffsets[2]);
  876   
  877           switch (transferType) {
  878               case DataBuffer.TYPE_BYTE: {
  879                  byte bdata[];
  880                  if (pixel == null) {
  881                      bdata = new byte[1];
  882                  } else {
  883                      bdata = (byte[])pixel;
  884                  }
  885                  bdata[0] = (byte)(0xff&intpixel[0]);
  886                  return bdata;
  887               }
  888               case DataBuffer.TYPE_USHORT:{
  889                  short sdata[];
  890                  if (pixel == null) {
  891                      sdata = new short[1];
  892                  } else {
  893                      sdata = (short[])pixel;
  894                  }
  895                  sdata[0] = (short)(intpixel[0]&0xffff);
  896                  return sdata;
  897               }
  898               case DataBuffer.TYPE_INT:
  899                  return intpixel;
  900           }
  901           throw new UnsupportedOperationException("This method has not been "+
  902                    "implemented for transferType " + transferType);
  903   
  904       }
  905   
  906       /**
  907        * Returns an array of unnormalized color/alpha components given a pixel
  908        * in this <code>ColorModel</code>.  The pixel value is specified as an
  909        * <code>int</code>.  If the <code>components</code> array is
  910        * <code>null</code>, a new array is allocated.  The
  911        * <code>components</code> array is returned.  Color/alpha components are
  912        * stored in the <code>components</code> array starting at
  913        * <code>offset</code>, even if the array is allocated by this method.
  914        * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
  915        * <code>components</code> array is not <code>null</code> and is not large
  916        * enough to hold all the color and alpha components, starting at
  917        * <code>offset</code>.
  918        * @param pixel the specified pixel
  919        * @param components the array to receive the color and alpha
  920        * components of the specified pixel
  921        * @param offset the offset into the <code>components</code> array at
  922        * which to start storing the color and alpha components
  923        * @return an array containing the color and alpha components of the
  924        * specified pixel starting at the specified offset.
  925        */
  926       final public int[] getComponents(int pixel, int[] components, int offset) {
  927           if (components == null) {
  928               components = new int[offset+numComponents];
  929           }
  930   
  931           for (int i=0; i < numComponents; i++) {
  932               components[offset+i] = (pixel & maskArray[i]) >>> maskOffsets[i];
  933           }
  934   
  935           return components;
  936       }
  937   
  938       /**
  939        * Returns an array of unnormalized color/alpha components given a pixel
  940        * in this <code>ColorModel</code>.  The pixel value is specified by an
  941        * array of data elements of type <code>transferType</code> passed in as
  942        * an object reference.  If <code>pixel</code> is not a primitive array
  943        * of type <code>transferType</code>, a <code>ClassCastException</code>
  944        * is thrown.  An <code>ArrayIndexOutOfBoundsException</code> is
  945        * thrown if <code>pixel</code> is not large enough to hold a
  946        * pixel value for this <code>ColorModel</code>.  If the
  947        * <code>components</code> array is <code>null</code>, a new
  948        * array is allocated.  The <code>components</code> array is returned.
  949        * Color/alpha components are stored in the <code>components</code> array
  950        * starting at <code>offset</code>, even if the array is allocated by
  951        * this method.  An <code>ArrayIndexOutOfBoundsException</code>
  952        * is thrown if the <code>components</code> array is not
  953        * <code>null</code> and is not large enough to hold all the color and
  954        * alpha components, starting at <code>offset</code>.
  955        * Since <code>DirectColorModel</code> can be subclassed, subclasses
  956        * inherit the implementation of this method and if they don't
  957        * override it then they throw an exception if they use an unsupported
  958        * <code>transferType</code>.
  959        * @param pixel the specified pixel
  960        * @param components the array to receive the color and alpha
  961        *        components of the specified pixel
  962        * @param offset the offset into the <code>components</code> array at
  963        *        which to start storing the color and alpha components
  964        * @return an array containing the color and alpha components of the
  965        * specified pixel starting at the specified offset.
  966        * @exception ClassCastException if <code>pixel</code>
  967        *  is not a primitive array of type <code>transferType</code>
  968        * @exception ArrayIndexOutOfBoundsException if
  969        *  <code>pixel</code> is not large enough to hold a pixel value
  970        *  for this <code>ColorModel</code>, or if <code>components</code>
  971        *  is not <code>null</code> and is not large enough to hold all the
  972        *  color and alpha components, starting at <code>offset</code>
  973        * @exception UnsupportedOperationException if this
  974        *            <code>transferType</code> is not supported by this
  975        *            color model
  976        */
  977       final public int[] getComponents(Object pixel, int[] components,
  978                                        int offset) {
  979           int intpixel=0;
  980           switch (transferType) {
  981               case DataBuffer.TYPE_BYTE:
  982                  byte bdata[] = (byte[])pixel;
  983                  intpixel = bdata[0] & 0xff;
  984               break;
  985               case DataBuffer.TYPE_USHORT:
  986                  short sdata[] = (short[])pixel;
  987                  intpixel = sdata[0] & 0xffff;
  988               break;
  989               case DataBuffer.TYPE_INT:
  990                  int idata[] = (int[])pixel;
  991                  intpixel = idata[0];
  992               break;
  993               default:
  994                  throw new UnsupportedOperationException("This method has not been "+
  995                      "implemented for transferType " + transferType);
  996           }
  997           return getComponents(intpixel, components, offset);
  998       }
  999   
 1000       /**
 1001        * Creates a <code>WritableRaster</code> with the specified width and
 1002        * height that has a data layout (<code>SampleModel</code>) compatible
 1003        * with this <code>ColorModel</code>.
 1004        * @param w the width to apply to the new <code>WritableRaster</code>
 1005        * @param h the height to apply to the new <code>WritableRaster</code>
 1006        * @return a <code>WritableRaster</code> object with the specified
 1007        * width and height.
 1008        * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
 1009        *         is less than or equal to zero
 1010        * @see WritableRaster
 1011        * @see SampleModel
 1012        */
 1013       final public WritableRaster createCompatibleWritableRaster (int w,
 1014                                                                   int h) {
 1015           if ((w <= 0) || (h <= 0)) {
 1016               throw new IllegalArgumentException("Width (" + w + ") and height (" + h +
 1017                                                  ") cannot be <= 0");
 1018           }
 1019           int[] bandmasks;
 1020           if (supportsAlpha) {
 1021               bandmasks = new int[4];
 1022               bandmasks[3] = alpha_mask;
 1023           }
 1024           else {
 1025               bandmasks = new int[3];
 1026           }
 1027           bandmasks[0] = red_mask;
 1028           bandmasks[1] = green_mask;
 1029           bandmasks[2] = blue_mask;
 1030   
 1031           if (pixel_bits > 16) {
 1032               return Raster.createPackedRaster(DataBuffer.TYPE_INT,
 1033                                                w,h,bandmasks,null);
 1034           }
 1035           else if (pixel_bits > 8) {
 1036               return Raster.createPackedRaster(DataBuffer.TYPE_USHORT,
 1037                                                w,h,bandmasks,null);
 1038           }
 1039           else {
 1040               return Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
 1041                                                w,h,bandmasks,null);
 1042           }
 1043       }
 1044   
 1045       /**
 1046        * Returns a pixel value represented as an <code>int</code> in this
 1047        * <code>ColorModel</code>, given an array of unnormalized color/alpha
 1048        * components.   An <code>ArrayIndexOutOfBoundsException</code> is
 1049        * thrown if the <code>components</code> array is
 1050        * not large enough to hold all the color and alpha components, starting
 1051        * at <code>offset</code>.
 1052        * @param components an array of unnormalized color and alpha
 1053        * components
 1054        * @param offset the index into <code>components</code> at which to
 1055        * begin retrieving the color and alpha components
 1056        * @return an <code>int</code> pixel value in this
 1057        * <code>ColorModel</code> corresponding to the specified components.
 1058        * @exception <code>ArrayIndexOutOfBoundsException</code> if
 1059        *  the <code>components</code> array is not large enough to
 1060        *  hold all of the color and alpha components starting at
 1061        *  <code>offset</code>
 1062        */
 1063       public int getDataElement(int[] components, int offset) {
 1064           int pixel = 0;
 1065           for (int i=0; i < numComponents; i++) {
 1066               pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
 1067           }
 1068           return pixel;
 1069       }
 1070   
 1071       /**
 1072        * Returns a data element array representation of a pixel in this
 1073        * <code>ColorModel</code>, given an array of unnormalized color/alpha
 1074        * components.
 1075        * This array can then be passed to the <code>setDataElements</code>
 1076        * method of a <code>WritableRaster</code> object.
 1077        * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
 1078        * <code>components</code> array
 1079        * is not large enough to hold all the color and alpha components,
 1080        * starting at offset.  If the <code>obj</code> variable is
 1081        * <code>null</code>, a new array is allocated.  If <code>obj</code> is
 1082        * not <code>null</code>, it must be a primitive array
 1083        * of type <code>transferType</code>; otherwise, a
 1084        * <code>ClassCastException</code> is thrown.
 1085        * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
 1086        * <code>obj</code> is not large enough to hold a pixel value for this
 1087        * <code>ColorModel</code>.
 1088        * Since <code>DirectColorModel</code> can be subclassed, subclasses
 1089        * inherit the implementation of this method and if they don't
 1090        * override it then they throw an exception if they use an unsupported
 1091        * <code>transferType</code>.
 1092        * @param components an array of unnormalized color and alpha
 1093        * components
 1094        * @param offset the index into <code>components</code> at which to
 1095        * begin retrieving color and alpha components
 1096        * @param obj the <code>Object</code> representing an array of color
 1097        * and alpha components
 1098        * @return an <code>Object</code> representing an array of color and
 1099        * alpha components.
 1100        * @exception <code>ClassCastException</code> if <code>obj</code>
 1101        *  is not a primitive array of type <code>transferType</code>
 1102        * @exception <code>ArrayIndexOutOfBoundsException</code> if
 1103        *  <code>obj</code> is not large enough to hold a pixel value
 1104        *  for this <code>ColorModel</code> or the <code>components</code>
 1105        *  array is not large enough to hold all of the color and alpha
 1106        *  components starting at <code>offset</code>
 1107        * @exception UnsupportedOperationException if this
 1108        *            <code>transferType</code> is not supported by this
 1109        *            color model
 1110        * @see WritableRaster#setDataElements
 1111        * @see SampleModel#setDataElements
 1112        */
 1113       public Object getDataElements(int[] components, int offset, Object obj) {
 1114           int pixel = 0;
 1115           for (int i=0; i < numComponents; i++) {
 1116               pixel |= ((components[offset+i]<<maskOffsets[i])&maskArray[i]);
 1117           }
 1118           switch (transferType) {
 1119               case DataBuffer.TYPE_BYTE:
 1120                  if (obj instanceof byte[]) {
 1121                      byte bdata[] = (byte[])obj;
 1122                      bdata[0] = (byte)(pixel&0xff);
 1123                      return bdata;
 1124                  } else {
 1125                      byte bdata[] = {(byte)(pixel&0xff)};
 1126                      return bdata;
 1127                  }
 1128               case DataBuffer.TYPE_USHORT:
 1129                  if (obj instanceof short[]) {
 1130                      short sdata[] = (short[])obj;
 1131                      sdata[0] = (short)(pixel&0xffff);
 1132                      return sdata;
 1133                  } else {
 1134                      short sdata[] = {(short)(pixel&0xffff)};
 1135                      return sdata;
 1136                  }
 1137               case DataBuffer.TYPE_INT:
 1138                  if (obj instanceof int[]) {
 1139                      int idata[] = (int[])obj;
 1140                      idata[0] = pixel;
 1141                      return idata;
 1142                  } else {
 1143                      int idata[] = {pixel};
 1144                      return idata;
 1145                  }
 1146               default:
 1147                  throw new ClassCastException("This method has not been "+
 1148                      "implemented for transferType " + transferType);
 1149           }
 1150       }
 1151   
 1152       /**
 1153        * Forces the raster data to match the state specified in the
 1154        * <code>isAlphaPremultiplied</code> variable, assuming the data is
 1155        * currently correctly described by this <code>ColorModel</code>.  It
 1156        * may multiply or divide the color raster data by alpha, or do
 1157        * nothing if the data is in the correct state.  If the data needs to
 1158        * be coerced, this method will also return an instance of this
 1159        * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
 1160        * flag set appropriately.  This method will throw a
 1161        * <code>UnsupportedOperationException</code> if this transferType is
 1162        * not supported by this <code>ColorModel</code>.  Since
 1163        * <code>ColorModel</code> can be subclassed, subclasses inherit the
 1164        * implementation of this method and if they don't override it then
 1165        * they throw an exception if they use an unsupported transferType.
 1166        *
 1167        * @param raster the <code>WritableRaster</code> data
 1168        * @param isAlphaPremultiplied <code>true</code> if the alpha is
 1169        * premultiplied; <code>false</code> otherwise
 1170        * @return a <code>ColorModel</code> object that represents the
 1171        * coerced data.
 1172        * @exception UnsupportedOperationException if this
 1173        *            <code>transferType</code> is not supported by this
 1174        *            color model
 1175        */
 1176       final public ColorModel coerceData (WritableRaster raster,
 1177                                           boolean isAlphaPremultiplied)
 1178       {
 1179           if (!supportsAlpha ||
 1180               this.isAlphaPremultiplied() == isAlphaPremultiplied) {
 1181               return this;
 1182           }
 1183   
 1184           int w = raster.getWidth();
 1185           int h = raster.getHeight();
 1186           int aIdx = numColorComponents;
 1187           float normAlpha;
 1188           float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1));
 1189   
 1190           int rminX = raster.getMinX();
 1191           int rY = raster.getMinY();
 1192           int rX;
 1193           int pixel[] = null;
 1194           int zpixel[] = null;
 1195   
 1196           if (isAlphaPremultiplied) {
 1197               // Must mean that we are currently not premultiplied so
 1198               // multiply by alpha
 1199               switch (transferType) {
 1200                   case DataBuffer.TYPE_BYTE: {
 1201                       for (int y = 0; y < h; y++, rY++) {
 1202                           rX = rminX;
 1203                           for (int x = 0; x < w; x++, rX++) {
 1204                               pixel = raster.getPixel(rX, rY, pixel);
 1205                               normAlpha = pixel[aIdx] * alphaScale;
 1206                               if (normAlpha != 0.f) {
 1207                                   for (int c=0; c < aIdx; c++) {
 1208                                       pixel[c] = (int) (pixel[c] * normAlpha +
 1209                                                         0.5f);
 1210                                   }
 1211                                   raster.setPixel(rX, rY, pixel);
 1212                               } else {
 1213                                   if (zpixel == null) {
 1214                                       zpixel = new int[numComponents];
 1215                                       java.util.Arrays.fill(zpixel, 0);
 1216                                   }
 1217                                   raster.setPixel(rX, rY, zpixel);
 1218                               }
 1219                           }
 1220                       }
 1221                   }
 1222                   break;
 1223                   case DataBuffer.TYPE_USHORT: {
 1224                       for (int y = 0; y < h; y++, rY++) {
 1225                           rX = rminX;
 1226                           for (int x = 0; x < w; x++, rX++) {
 1227                               pixel = raster.getPixel(rX, rY, pixel);
 1228                               normAlpha = pixel[aIdx] * alphaScale;
 1229                               if (normAlpha != 0.f) {
 1230                                   for (int c=0; c < aIdx; c++) {
 1231                                       pixel[c] = (int) (pixel[c] * normAlpha +
 1232                                                         0.5f);
 1233                                   }
 1234                                   raster.setPixel(rX, rY, pixel);
 1235                               } else {
 1236                                   if (zpixel == null) {
 1237                                       zpixel = new int[numComponents];
 1238                                       java.util.Arrays.fill(zpixel, 0);
 1239                                   }
 1240                                   raster.setPixel(rX, rY, zpixel);
 1241                               }
 1242                           }
 1243                       }
 1244                   }
 1245                   break;
 1246                   case DataBuffer.TYPE_INT: {
 1247                       for (int y = 0; y < h; y++, rY++) {
 1248                           rX = rminX;
 1249                           for (int x = 0; x < w; x++, rX++) {
 1250                               pixel = raster.getPixel(rX, rY, pixel);
 1251                               normAlpha = pixel[aIdx] * alphaScale;
 1252                               if (normAlpha != 0.f) {
 1253                                   for (int c=0; c < aIdx; c++) {
 1254                                       pixel[c] = (int) (pixel[c] * normAlpha +
 1255                                                         0.5f);
 1256                                   }
 1257                                   raster.setPixel(rX, rY, pixel);
 1258                               } else {
 1259                                   if (zpixel == null) {
 1260                                       zpixel = new int[numComponents];
 1261                                       java.util.Arrays.fill(zpixel, 0);
 1262                                   }
 1263                                   raster.setPixel(rX, rY, zpixel);
 1264                               }
 1265                           }
 1266                       }
 1267                   }
 1268                   break;
 1269                   default:
 1270                       throw new UnsupportedOperationException("This method has not been "+
 1271                            "implemented for transferType " + transferType);
 1272               }
 1273           }
 1274           else {
 1275               // We are premultiplied and want to divide it out
 1276               switch (transferType) {
 1277                   case DataBuffer.TYPE_BYTE: {
 1278                       for (int y = 0; y < h; y++, rY++) {
 1279                           rX = rminX;
 1280                           for (int x = 0; x < w; x++, rX++) {
 1281                               pixel = raster.getPixel(rX, rY, pixel);
 1282                               normAlpha = pixel[aIdx] * alphaScale;
 1283                               if (normAlpha != 0.0f) {
 1284                                   float invAlpha = 1.0f / normAlpha;
 1285                                   for (int c=0; c < aIdx; c++) {
 1286                                       pixel[c] = (int) (pixel[c] * invAlpha +
 1287                                                         0.5f);
 1288                                   }
 1289                                   raster.setPixel(rX, rY, pixel);
 1290                               }
 1291                           }
 1292                       }
 1293                   }
 1294                   break;
 1295                   case DataBuffer.TYPE_USHORT: {
 1296                       for (int y = 0; y < h; y++, rY++) {
 1297                           rX = rminX;
 1298                           for (int x = 0; x < w; x++, rX++) {
 1299                               pixel = raster.getPixel(rX, rY, pixel);
 1300                               normAlpha = pixel[aIdx] * alphaScale;
 1301                               if (normAlpha != 0) {
 1302                                   float invAlpha = 1.0f / normAlpha;
 1303                                   for (int c=0; c < aIdx; c++) {
 1304                                       pixel[c] = (int) (pixel[c] * invAlpha +
 1305                                                         0.5f);
 1306                                   }
 1307                                   raster.setPixel(rX, rY, pixel);
 1308                               }
 1309                           }
 1310                       }
 1311                   }
 1312                   break;
 1313                   case DataBuffer.TYPE_INT: {
 1314                       for (int y = 0; y < h; y++, rY++) {
 1315                           rX = rminX;
 1316                           for (int x = 0; x < w; x++, rX++) {
 1317                               pixel = raster.getPixel(rX, rY, pixel);
 1318                               normAlpha = pixel[aIdx] * alphaScale;
 1319                               if (normAlpha != 0) {
 1320                                   float invAlpha = 1.0f / normAlpha;
 1321                                   for (int c=0; c < aIdx; c++) {
 1322                                       pixel[c] = (int) (pixel[c] * invAlpha +
 1323                                                         0.5f);
 1324                                   }
 1325                                   raster.setPixel(rX, rY, pixel);
 1326                               }
 1327                           }
 1328                       }
 1329                   }
 1330                   break;
 1331                   default:
 1332                       throw new UnsupportedOperationException("This method has not been "+
 1333                            "implemented for transferType " + transferType);
 1334               }
 1335           }
 1336   
 1337           // Return a new color model
 1338           return new DirectColorModel(colorSpace, pixel_bits, maskArray[0],
 1339                                       maskArray[1], maskArray[2], maskArray[3],
 1340                                       isAlphaPremultiplied,
 1341                                       transferType);
 1342   
 1343       }
 1344   
 1345       /**
 1346         * Returns <code>true</code> if <code>raster</code> is compatible
 1347         * with this <code>ColorModel</code> and <code>false</code> if it is
 1348         * not.
 1349         * @param raster the {@link Raster} object to test for compatibility
 1350         * @return <code>true</code> if <code>raster</code> is compatible
 1351         * with this <code>ColorModel</code>; <code>false</code> otherwise.
 1352         */
 1353       public boolean isCompatibleRaster(Raster raster) {
 1354           SampleModel sm = raster.getSampleModel();
 1355           SinglePixelPackedSampleModel spsm;
 1356           if (sm instanceof SinglePixelPackedSampleModel) {
 1357               spsm = (SinglePixelPackedSampleModel) sm;
 1358           }
 1359           else {
 1360               return false;
 1361           }
 1362           if (spsm.getNumBands() != getNumComponents()) {
 1363               return false;
 1364           }
 1365   
 1366           int[] bitMasks = spsm.getBitMasks();
 1367           for (int i=0; i<numComponents; i++) {
 1368               if (bitMasks[i] != maskArray[i]) {
 1369                   return false;
 1370               }
 1371           }
 1372   
 1373           return (raster.getTransferType() == transferType);
 1374       }
 1375   
 1376       private void setFields() {
 1377           // Set the private fields
 1378           // REMIND: Get rid of these from the native code
 1379           red_mask     = maskArray[0];
 1380           red_offset   = maskOffsets[0];
 1381           green_mask   = maskArray[1];
 1382           green_offset = maskOffsets[1];
 1383           blue_mask    = maskArray[2];
 1384           blue_offset  = maskOffsets[2];
 1385           if (nBits[0] < 8) {
 1386               red_scale = (1 << nBits[0]) - 1;
 1387           }
 1388           if (nBits[1] < 8) {
 1389               green_scale = (1 << nBits[1]) - 1;
 1390           }
 1391           if (nBits[2] < 8) {
 1392               blue_scale = (1 << nBits[2]) - 1;
 1393           }
 1394           if (supportsAlpha) {
 1395               alpha_mask   = maskArray[3];
 1396               alpha_offset = maskOffsets[3];
 1397               if (nBits[3] < 8) {
 1398                   alpha_scale = (1 << nBits[3]) - 1;
 1399               }
 1400           }
 1401       }
 1402   
 1403       /**
 1404        * Returns a <code>String</code> that represents this
 1405        * <code>DirectColorModel</code>.
 1406        * @return a <code>String</code> representing this
 1407        * <code>DirectColorModel</code>.
 1408        */
 1409       public String toString() {
 1410           return new String("DirectColorModel: rmask="
 1411                             +Integer.toHexString(red_mask)+" gmask="
 1412                             +Integer.toHexString(green_mask)+" bmask="
 1413                             +Integer.toHexString(blue_mask)+" amask="
 1414                             +Integer.toHexString(alpha_mask));
 1415       }
 1416   }

Home » openjdk-7 » java » awt » image » [javadoc | source]