Save This Page
Home » openjdk-7 » javax » imageio » [javadoc | source]
    1   /*
    2    * Copyright 2000-2003 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.imageio;
   27   
   28   import java.awt.Point;
   29   import java.awt.Transparency;
   30   import java.awt.image.BandedSampleModel;
   31   import java.awt.image.BufferedImage;
   32   import java.awt.image.ColorModel;
   33   import java.awt.color.ColorSpace;
   34   import java.awt.image.IndexColorModel;
   35   import java.awt.image.ComponentColorModel;
   36   import java.awt.image.DataBuffer;
   37   import java.awt.image.DirectColorModel;
   38   import java.awt.image.MultiPixelPackedSampleModel;
   39   import java.awt.image.PixelInterleavedSampleModel;
   40   import java.awt.image.SinglePixelPackedSampleModel;
   41   import java.awt.image.Raster;
   42   import java.awt.image.RenderedImage;
   43   import java.awt.image.SampleModel;
   44   import java.awt.image.WritableRaster;
   45   import java.util.Hashtable;
   46   
   47   /**
   48    * A class that allows the format of an image (in particular, its
   49    * <code>SampleModel</code> and <code>ColorModel</code>) to be
   50    * specified in a convenient manner.
   51    *
   52    */
   53   public class ImageTypeSpecifier {
   54   
   55       /**
   56        * The <code>ColorModel</code> to be used as a prototype.
   57        */
   58       protected ColorModel colorModel;
   59   
   60       /**
   61        * A <code>SampleModel</code> to be used as a prototype.
   62        */
   63       protected SampleModel sampleModel;
   64   
   65       /**
   66        * Cached specifiers for all of the standard
   67        * <code>BufferedImage</code> types.
   68        */
   69       private static ImageTypeSpecifier[] BISpecifier;
   70   
   71       // Initialize the standard specifiers
   72       static {
   73           ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
   74   
   75           BISpecifier =
   76               new ImageTypeSpecifier[BufferedImage.TYPE_BYTE_INDEXED + 1];
   77   
   78           BISpecifier[BufferedImage.TYPE_CUSTOM] = null;
   79   
   80           BISpecifier[BufferedImage.TYPE_INT_RGB] =
   81               createPacked(sRGB,
   82                            0x00ff0000,
   83                            0x0000ff00,
   84                            0x000000ff,
   85                            0x0,
   86                            DataBuffer.TYPE_INT,
   87                            false);
   88   
   89           BISpecifier[BufferedImage.TYPE_INT_ARGB] =
   90               createPacked(sRGB,
   91                            0x00ff0000,
   92                            0x0000ff00,
   93                            0x000000ff,
   94                            0xff000000,
   95                            DataBuffer.TYPE_INT,
   96                            false);
   97   
   98           BISpecifier[BufferedImage.TYPE_INT_ARGB_PRE] =
   99               createPacked(sRGB,
  100                            0x00ff0000,
  101                            0x0000ff00,
  102                            0x000000ff,
  103                            0xff000000,
  104                            DataBuffer.TYPE_INT,
  105                            true);
  106   
  107           BISpecifier[BufferedImage.TYPE_INT_BGR] =
  108               createPacked(sRGB,
  109                            0x000000ff,
  110                            0x0000ff00,
  111                            0x00ff0000,
  112                            0x0,
  113                            DataBuffer.TYPE_INT,
  114                            false);
  115   
  116           int[] bOffsRGB = { 2, 1, 0 };
  117           BISpecifier[BufferedImage.TYPE_3BYTE_BGR] =
  118               createInterleaved(sRGB,
  119                                 bOffsRGB,
  120                                 DataBuffer.TYPE_BYTE,
  121                                 false,
  122                                 false);
  123   
  124           int[] bOffsABGR = { 3, 2, 1, 0 };
  125           BISpecifier[BufferedImage.TYPE_4BYTE_ABGR] =
  126               createInterleaved(sRGB,
  127                                 bOffsABGR,
  128                                 DataBuffer.TYPE_BYTE,
  129                                 true,
  130                                 false);
  131   
  132           BISpecifier[BufferedImage.TYPE_4BYTE_ABGR_PRE] =
  133               createInterleaved(sRGB,
  134                                 bOffsABGR,
  135                                 DataBuffer.TYPE_BYTE,
  136                                 true,
  137                                 true);
  138   
  139           BISpecifier[BufferedImage.TYPE_USHORT_565_RGB] =
  140               createPacked(sRGB,
  141                            0xF800,
  142                            0x07E0,
  143                            0x001F,
  144                            0x0,
  145                            DataBuffer.TYPE_USHORT,
  146                            false);
  147   
  148           BISpecifier[BufferedImage.TYPE_USHORT_555_RGB] =
  149               createPacked(sRGB,
  150                            0x7C00,
  151                            0x03E0,
  152                            0x001F,
  153                            0x0,
  154                            DataBuffer.TYPE_USHORT,
  155                            false);
  156   
  157           BISpecifier[BufferedImage.TYPE_BYTE_GRAY] =
  158               createGrayscale(8,
  159                               DataBuffer.TYPE_BYTE,
  160                               false);
  161   
  162           BISpecifier[BufferedImage.TYPE_USHORT_GRAY] =
  163               createGrayscale(16,
  164                               DataBuffer.TYPE_USHORT,
  165                               false);
  166   
  167           BISpecifier[BufferedImage.TYPE_BYTE_BINARY] =
  168               createGrayscale(1,
  169                               DataBuffer.TYPE_BYTE,
  170                               false);
  171   
  172           BufferedImage bi =
  173               new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED);
  174           IndexColorModel icm = (IndexColorModel)bi.getColorModel();
  175           int mapSize = icm.getMapSize();
  176           byte[] redLUT = new byte[mapSize];
  177           byte[] greenLUT = new byte[mapSize];
  178           byte[] blueLUT = new byte[mapSize];
  179           byte[] alphaLUT = new byte[mapSize];
  180   
  181           icm.getReds(redLUT);
  182           icm.getGreens(greenLUT);
  183           icm.getBlues(blueLUT);
  184           icm.getAlphas(alphaLUT);
  185   
  186           BISpecifier[BufferedImage.TYPE_BYTE_INDEXED] =
  187               createIndexed(redLUT, greenLUT, blueLUT, alphaLUT,
  188                             8,
  189                             DataBuffer.TYPE_BYTE);
  190       }
  191   
  192       /**
  193        * A constructor to be used by inner subclasses only.
  194        */
  195       private ImageTypeSpecifier() {}
  196   
  197       /**
  198        * Constructs an <code>ImageTypeSpecifier</code> directly
  199        * from a <code>ColorModel</code> and a <code>SampleModel</code>.
  200        * It is the caller's responsibility to supply compatible
  201        * parameters.
  202        *
  203        * @param colorModel a <code>ColorModel</code>.
  204        * @param sampleModel a <code>SampleModel</code>.
  205        *
  206        * @exception IllegalArgumentException if either parameter is
  207        * <code>null</code>.
  208        * @exception IllegalArgumentException if <code>sampleModel</code>
  209        * is not compatible with <code>colorModel</code>.
  210        */
  211       public ImageTypeSpecifier(ColorModel colorModel, SampleModel sampleModel) {
  212           if (colorModel == null) {
  213               throw new IllegalArgumentException("colorModel == null!");
  214           }
  215           if (sampleModel == null) {
  216               throw new IllegalArgumentException("sampleModel == null!");
  217           }
  218           if (!colorModel.isCompatibleSampleModel(sampleModel)) {
  219               throw new IllegalArgumentException
  220                   ("sampleModel is incompatible with colorModel!");
  221           }
  222           this.colorModel = colorModel;
  223           this.sampleModel = sampleModel;
  224       }
  225   
  226       /**
  227        * Constructs an <code>ImageTypeSpecifier</code> from a
  228        * <code>RenderedImage</code>.  If a <code>BufferedImage</code> is
  229        * being used, one of the factory methods
  230        * <code>createFromRenderedImage</code> or
  231        * <code>createFromBufferedImageType</code> should be used instead in
  232        * order to get a more accurate result.
  233        *
  234        * @param image a <code>RenderedImage</code>.
  235        *
  236        * @exception IllegalArgumentException if the argument is
  237        * <code>null</code>.
  238        */
  239       public ImageTypeSpecifier(RenderedImage image) {
  240           if (image == null) {
  241               throw new IllegalArgumentException("image == null!");
  242           }
  243           colorModel = image.getColorModel();
  244           sampleModel = image.getSampleModel();
  245       }
  246   
  247       // Packed
  248   
  249       static class Packed extends ImageTypeSpecifier {
  250           ColorSpace colorSpace;
  251           int redMask;
  252           int greenMask;
  253           int blueMask;
  254           int alphaMask;
  255           int transferType;
  256           boolean isAlphaPremultiplied;
  257   
  258           public Packed(ColorSpace colorSpace,
  259                         int redMask,
  260                         int greenMask,
  261                         int blueMask,
  262                         int alphaMask, // 0 if no alpha
  263                         int transferType,
  264                         boolean isAlphaPremultiplied) {
  265               if (colorSpace == null) {
  266                   throw new IllegalArgumentException("colorSpace == null!");
  267               }
  268               if (colorSpace.getType() != ColorSpace.TYPE_RGB) {
  269                   throw new IllegalArgumentException
  270                       ("colorSpace is not of type TYPE_RGB!");
  271               }
  272               if (transferType != DataBuffer.TYPE_BYTE &&
  273                   transferType != DataBuffer.TYPE_USHORT &&
  274                   transferType != DataBuffer.TYPE_INT) {
  275                   throw new IllegalArgumentException
  276                       ("Bad value for transferType!");
  277               }
  278               if (redMask == 0 && greenMask == 0 &&
  279                   blueMask == 0 && alphaMask == 0) {
  280                   throw new IllegalArgumentException
  281                       ("No mask has at least 1 bit set!");
  282               }
  283               this.colorSpace = colorSpace;
  284               this.redMask = redMask;
  285               this.greenMask = greenMask;
  286               this.blueMask = blueMask;
  287               this.alphaMask = alphaMask;
  288               this.transferType = transferType;
  289               this.isAlphaPremultiplied = isAlphaPremultiplied;
  290   
  291               int bits = 32;
  292               this.colorModel =
  293                   new DirectColorModel(colorSpace,
  294                                        bits,
  295                                        redMask, greenMask, blueMask,
  296                                        alphaMask, isAlphaPremultiplied,
  297                                        transferType);
  298               this.sampleModel = colorModel.createCompatibleSampleModel(1, 1);
  299           }
  300       }
  301   
  302       /**
  303        * Returns a specifier for a packed image format that will use a
  304        * <code>DirectColorModel</code> and a packed
  305        * <code>SampleModel</code> to store each pixel packed into in a
  306        * single byte, short, or int.
  307        *
  308        * @param colorSpace the desired <code>ColorSpace</code>.
  309        * @param redMask a contiguous mask indicated the position of the
  310        * red channel.
  311        * @param greenMask a contiguous mask indicated the position of the
  312        * green channel.
  313        * @param blueMask a contiguous mask indicated the position of the
  314        * blue channel.
  315        * @param alphaMask a contiguous mask indicated the position of the
  316        * alpha channel.
  317        * @param transferType the desired <code>SampleModel</code> transfer type.
  318        * @param isAlphaPremultiplied <code>true</code> if the color channels
  319        * will be premultipled by the alpha channel.
  320        *
  321        * @return an <code>ImageTypeSpecifier</code> with the desired
  322        * characteristics.
  323        *
  324        * @exception IllegalArgumentException if <code>colorSpace</code>
  325        * is <code>null</code>.
  326        * @exception IllegalArgumentException if <code>colorSpace</code>
  327        * is not of type <code>TYPE_RGB</code>.
  328        * @exception IllegalArgumentException if no mask has at least 1
  329        * bit set.
  330        * @exception IllegalArgumentException if
  331        * <code>transferType</code> if not one of
  332        * <code>DataBuffer.TYPE_BYTE</code>,
  333        * <code>DataBuffer.TYPE_USHORT</code>, or
  334        * <code>DataBuffer.TYPE_INT</code>.
  335        */
  336       public static ImageTypeSpecifier
  337           createPacked(ColorSpace colorSpace,
  338                        int redMask,
  339                        int greenMask,
  340                        int blueMask,
  341                        int alphaMask, // 0 if no alpha
  342                        int transferType,
  343                        boolean isAlphaPremultiplied) {
  344           return new ImageTypeSpecifier.Packed(colorSpace,
  345                                                redMask,
  346                                                greenMask,
  347                                                blueMask,
  348                                                alphaMask, // 0 if no alpha
  349                                                transferType,
  350                                                isAlphaPremultiplied);
  351       }
  352   
  353       static ColorModel createComponentCM(ColorSpace colorSpace,
  354                                           int numBands,
  355                                           int dataType,
  356                                           boolean hasAlpha,
  357                                           boolean isAlphaPremultiplied) {
  358           int transparency =
  359               hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
  360   
  361           int[] numBits = new int[numBands];
  362           int bits = DataBuffer.getDataTypeSize(dataType);
  363   
  364           for (int i = 0; i < numBands; i++) {
  365               numBits[i] = bits;
  366           }
  367   
  368           return new ComponentColorModel(colorSpace,
  369                                          numBits,
  370                                          hasAlpha,
  371                                          isAlphaPremultiplied,
  372                                          transparency,
  373                                          dataType);
  374       }
  375   
  376       // Interleaved
  377   
  378       static class Interleaved extends ImageTypeSpecifier {
  379           ColorSpace colorSpace;
  380           int[] bandOffsets;
  381           int dataType;
  382           boolean hasAlpha;
  383           boolean isAlphaPremultiplied;
  384   
  385           public Interleaved(ColorSpace colorSpace,
  386                              int[] bandOffsets,
  387                              int dataType,
  388                              boolean hasAlpha,
  389                              boolean isAlphaPremultiplied) {
  390               if (colorSpace == null) {
  391                   throw new IllegalArgumentException("colorSpace == null!");
  392               }
  393               if (bandOffsets == null) {
  394                   throw new IllegalArgumentException("bandOffsets == null!");
  395               }
  396               int numBands = colorSpace.getNumComponents() +
  397                   (hasAlpha ? 1 : 0);
  398               if (bandOffsets.length != numBands) {
  399                   throw new IllegalArgumentException
  400                       ("bandOffsets.length is wrong!");
  401               }
  402               if (dataType != DataBuffer.TYPE_BYTE &&
  403                   dataType != DataBuffer.TYPE_SHORT &&
  404                   dataType != DataBuffer.TYPE_USHORT &&
  405                   dataType != DataBuffer.TYPE_INT &&
  406                   dataType != DataBuffer.TYPE_FLOAT &&
  407                   dataType != DataBuffer.TYPE_DOUBLE) {
  408                   throw new IllegalArgumentException
  409                       ("Bad value for dataType!");
  410               }
  411               this.colorSpace = colorSpace;
  412               this.bandOffsets = (int[])bandOffsets.clone();
  413               this.dataType = dataType;
  414               this.hasAlpha = hasAlpha;
  415               this.isAlphaPremultiplied = isAlphaPremultiplied;
  416   
  417               this.colorModel =
  418                   ImageTypeSpecifier.createComponentCM(colorSpace,
  419                                                        bandOffsets.length,
  420                                                        dataType,
  421                                                        hasAlpha,
  422                                                        isAlphaPremultiplied);
  423   
  424               int minBandOffset = bandOffsets[0];
  425               int maxBandOffset = minBandOffset;
  426               for (int i = 0; i < bandOffsets.length; i++) {
  427                   int offset = bandOffsets[i];
  428                   minBandOffset = Math.min(offset, minBandOffset);
  429                   maxBandOffset = Math.max(offset, maxBandOffset);
  430               }
  431               int pixelStride = maxBandOffset - minBandOffset + 1;
  432   
  433               int w = 1;
  434               int h = 1;
  435               this.sampleModel =
  436                   new PixelInterleavedSampleModel(dataType,
  437                                                   w, h,
  438                                                   pixelStride,
  439                                                   w*pixelStride,
  440                                                   bandOffsets);
  441           }
  442   
  443           public boolean equals(Object o) {
  444               if ((o == null) ||
  445                   !(o instanceof ImageTypeSpecifier.Interleaved)) {
  446                   return false;
  447               }
  448   
  449               ImageTypeSpecifier.Interleaved that =
  450                   (ImageTypeSpecifier.Interleaved)o;
  451   
  452               if ((!(this.colorSpace.equals(that.colorSpace))) ||
  453                   (this.dataType != that.dataType) ||
  454                   (this.hasAlpha != that.hasAlpha) ||
  455                   (this.isAlphaPremultiplied != that.isAlphaPremultiplied) ||
  456                   (this.bandOffsets.length != that.bandOffsets.length)) {
  457                   return false;
  458               }
  459   
  460               for (int i = 0; i < bandOffsets.length; i++) {
  461                   if (this.bandOffsets[i] != that.bandOffsets[i]) {
  462                       return false;
  463                   }
  464               }
  465   
  466               return true;
  467           }
  468   
  469           public int hashCode() {
  470               return (super.hashCode() +
  471                       (4 * bandOffsets.length) +
  472                       (25 * dataType) +
  473                       (hasAlpha ? 17 : 18));
  474           }
  475       }
  476   
  477       /**
  478        * Returns a specifier for an interleaved image format that will
  479        * use a <code>ComponentColorModel</code> and a
  480        * <code>PixelInterleavedSampleModel</code> to store each pixel
  481        * component in a separate byte, short, or int.
  482        *
  483        * @param colorSpace the desired <code>ColorSpace</code>.
  484        * @param bandOffsets an array of <code>int</code>s indicating the
  485        * offsets for each band.
  486        * @param dataType the desired data type, as one of the enumerations
  487        * from the <code>DataBuffer</code> class.
  488        * @param hasAlpha <code>true</code> if an alpha channel is desired.
  489        * @param isAlphaPremultiplied <code>true</code> if the color channels
  490        * will be premultipled by the alpha channel.
  491        *
  492        * @return an <code>ImageTypeSpecifier</code> with the desired
  493        * characteristics.
  494        *
  495        * @exception IllegalArgumentException if <code>colorSpace</code>
  496        * is <code>null</code>.
  497        * @exception IllegalArgumentException if <code>bandOffsets</code>
  498        * is <code>null</code>.
  499        * @exception IllegalArgumentException if <code>dataType</code> is
  500        * not one of the legal <code>DataBuffer.TYPE_*</code> constants.
  501        * @exception IllegalArgumentException if
  502        * <code>bandOffsets.length</code> does not equal the number of
  503        * color space components, plus 1 if <code>hasAlpha</code> is
  504        * <code>true</code>.
  505        */
  506       public static ImageTypeSpecifier
  507           createInterleaved(ColorSpace colorSpace,
  508                             int[] bandOffsets,
  509                             int dataType,
  510                             boolean hasAlpha,
  511                             boolean isAlphaPremultiplied) {
  512           return new ImageTypeSpecifier.Interleaved(colorSpace,
  513                                                     bandOffsets,
  514                                                     dataType,
  515                                                     hasAlpha,
  516                                                     isAlphaPremultiplied);
  517       }
  518   
  519       // Banded
  520   
  521       static class Banded extends ImageTypeSpecifier {
  522           ColorSpace colorSpace;
  523           int[] bankIndices;
  524           int[] bandOffsets;
  525           int dataType;
  526           boolean hasAlpha;
  527           boolean isAlphaPremultiplied;
  528   
  529           public Banded(ColorSpace colorSpace,
  530                         int[] bankIndices,
  531                         int[] bandOffsets,
  532                         int dataType,
  533                         boolean hasAlpha,
  534                         boolean isAlphaPremultiplied) {
  535               if (colorSpace == null) {
  536                   throw new IllegalArgumentException("colorSpace == null!");
  537               }
  538               if (bankIndices == null) {
  539                   throw new IllegalArgumentException("bankIndices == null!");
  540               }
  541               if (bandOffsets == null) {
  542                   throw new IllegalArgumentException("bandOffsets == null!");
  543               }
  544               if (bankIndices.length != bandOffsets.length) {
  545                   throw new IllegalArgumentException
  546                       ("bankIndices.length != bandOffsets.length!");
  547               }
  548               if (dataType != DataBuffer.TYPE_BYTE &&
  549                   dataType != DataBuffer.TYPE_SHORT &&
  550                   dataType != DataBuffer.TYPE_USHORT &&
  551                   dataType != DataBuffer.TYPE_INT &&
  552                   dataType != DataBuffer.TYPE_FLOAT &&
  553                   dataType != DataBuffer.TYPE_DOUBLE) {
  554                   throw new IllegalArgumentException
  555                       ("Bad value for dataType!");
  556               }
  557               int numBands = colorSpace.getNumComponents() +
  558                   (hasAlpha ? 1 : 0);
  559               if (bandOffsets.length != numBands) {
  560                   throw new IllegalArgumentException
  561                       ("bandOffsets.length is wrong!");
  562               }
  563   
  564               this.colorSpace = colorSpace;
  565               this.bankIndices = (int[])bankIndices.clone();
  566               this.bandOffsets = (int[])bandOffsets.clone();
  567               this.dataType = dataType;
  568               this.hasAlpha = hasAlpha;
  569               this.isAlphaPremultiplied = isAlphaPremultiplied;
  570   
  571               this.colorModel =
  572                   ImageTypeSpecifier.createComponentCM(colorSpace,
  573                                                        bankIndices.length,
  574                                                        dataType,
  575                                                        hasAlpha,
  576                                                        isAlphaPremultiplied);
  577   
  578               int w = 1;
  579               int h = 1;
  580               this.sampleModel = new BandedSampleModel(dataType,
  581                                                        w, h,
  582                                                        w,
  583                                                        bankIndices,
  584                                                        bandOffsets);
  585           }
  586   
  587           public boolean equals(Object o) {
  588               if ((o == null) ||
  589                   !(o instanceof ImageTypeSpecifier.Banded)) {
  590                   return false;
  591               }
  592   
  593               ImageTypeSpecifier.Banded that =
  594                   (ImageTypeSpecifier.Banded)o;
  595   
  596               if ((!(this.colorSpace.equals(that.colorSpace))) ||
  597                   (this.dataType != that.dataType) ||
  598                   (this.hasAlpha != that.hasAlpha) ||
  599                   (this.isAlphaPremultiplied != that.isAlphaPremultiplied) ||
  600                   (this.bankIndices.length != that.bankIndices.length) ||
  601                   (this.bandOffsets.length != that.bandOffsets.length)) {
  602                   return false;
  603               }
  604   
  605               for (int i = 0; i < bankIndices.length; i++) {
  606                   if (this.bankIndices[i] != that.bankIndices[i]) {
  607                       return false;
  608                   }
  609               }
  610   
  611               for (int i = 0; i < bandOffsets.length; i++) {
  612                   if (this.bandOffsets[i] != that.bandOffsets[i]) {
  613                       return false;
  614                   }
  615               }
  616   
  617               return true;
  618           }
  619   
  620           public int hashCode() {
  621               return (super.hashCode() +
  622                       (3 * bandOffsets.length) +
  623                       (7 * bankIndices.length) +
  624                       (21 * dataType) +
  625                       (hasAlpha ? 19 : 29));
  626           }
  627       }
  628   
  629       /**
  630        * Returns a specifier for a banded image format that will use a
  631        * <code>ComponentColorModel</code> and a
  632        * <code>BandedSampleModel</code> to store each channel in a
  633        * separate array.
  634        *
  635        * @param colorSpace the desired <code>ColorSpace</code>.
  636        * @param bankIndices an array of <code>int</code>s indicating the
  637        * bank in which each band will be stored.
  638        * @param bandOffsets an array of <code>int</code>s indicating the
  639        * starting offset of each band within its bank.
  640        * @param dataType the desired data type, as one of the enumerations
  641        * from the <code>DataBuffer</code> class.
  642        * @param hasAlpha <code>true</code> if an alpha channel is desired.
  643        * @param isAlphaPremultiplied <code>true</code> if the color channels
  644        * will be premultipled by the alpha channel.
  645        *
  646        * @return an <code>ImageTypeSpecifier</code> with the desired
  647        * characteristics.
  648        *
  649        * @exception IllegalArgumentException if <code>colorSpace</code>
  650        * is <code>null</code>.
  651        * @exception IllegalArgumentException if <code>bankIndices</code>
  652        * is <code>null</code>.
  653        * @exception IllegalArgumentException if <code>bandOffsets</code>
  654        * is <code>null</code>.
  655        * @exception IllegalArgumentException if the lengths of
  656        * <code>bankIndices</code> and <code>bandOffsets</code> differ.
  657        * @exception IllegalArgumentException if
  658        * <code>bandOffsets.length</code> does not equal the number of
  659        * color space components, plus 1 if <code>hasAlpha</code> is
  660        * <code>true</code>.
  661        * @exception IllegalArgumentException if <code>dataType</code> is
  662        * not one of the legal <code>DataBuffer.TYPE_*</code> constants.
  663        */
  664       public static ImageTypeSpecifier
  665           createBanded(ColorSpace colorSpace,
  666                        int[] bankIndices,
  667                        int[] bandOffsets,
  668                        int dataType,
  669                        boolean hasAlpha,
  670                        boolean isAlphaPremultiplied) {
  671           return new ImageTypeSpecifier.Banded(colorSpace,
  672                                                bankIndices,
  673                                                bandOffsets,
  674                                                dataType,
  675                                                hasAlpha,
  676                                                isAlphaPremultiplied);
  677       }
  678   
  679       // Grayscale
  680   
  681       static class Grayscale extends ImageTypeSpecifier {
  682           int bits;
  683           int dataType;
  684           boolean isSigned;
  685           boolean hasAlpha;
  686           boolean isAlphaPremultiplied;
  687   
  688           public Grayscale(int bits,
  689                            int dataType,
  690                            boolean isSigned,
  691                            boolean hasAlpha,
  692                            boolean isAlphaPremultiplied)
  693           {
  694               if (bits != 1 && bits != 2 && bits != 4 &&
  695                   bits != 8 && bits != 16)
  696               {
  697                   throw new IllegalArgumentException("Bad value for bits!");
  698               }
  699               if (dataType != DataBuffer.TYPE_BYTE &&
  700                   dataType != DataBuffer.TYPE_SHORT &&
  701                   dataType != DataBuffer.TYPE_USHORT)
  702               {
  703                   throw new IllegalArgumentException
  704                       ("Bad value for dataType!");
  705               }
  706               if (bits > 8 && dataType == DataBuffer.TYPE_BYTE) {
  707                   throw new IllegalArgumentException
  708                       ("Too many bits for dataType!");
  709               }
  710   
  711               this.bits = bits;
  712               this.dataType = dataType;
  713               this.isSigned = isSigned;
  714               this.hasAlpha = hasAlpha;
  715               this.isAlphaPremultiplied = isAlphaPremultiplied;
  716   
  717               ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
  718   
  719               if ((bits == 8 && dataType == DataBuffer.TYPE_BYTE) ||
  720                   (bits == 16 &&
  721                    (dataType == DataBuffer.TYPE_SHORT ||
  722                     dataType == DataBuffer.TYPE_USHORT))) {
  723                   // Use component color model & sample model
  724   
  725                   int numBands = hasAlpha ? 2 : 1;
  726                   int transparency =
  727                       hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
  728   
  729   
  730                   int[] nBits = new int[numBands];
  731                   nBits[0] = bits;
  732                   if (numBands == 2) {
  733                       nBits[1] = bits;
  734                   }
  735                   this.colorModel =
  736                       new ComponentColorModel(colorSpace,
  737                                               nBits,
  738                                               hasAlpha,
  739                                               isAlphaPremultiplied,
  740                                               transparency,
  741                                               dataType);
  742   
  743                   int[] bandOffsets = new int[numBands];
  744                   bandOffsets[0] = 0;
  745                   if (numBands == 2) {
  746                       bandOffsets[1] = 1;
  747                   }
  748   
  749                   int w = 1;
  750                   int h = 1;
  751                   this.sampleModel =
  752                       new PixelInterleavedSampleModel(dataType,
  753                                                       w, h,
  754                                                       numBands, w*numBands,
  755                                                       bandOffsets);
  756               } else {
  757                   int numEntries = 1 << bits;
  758                   byte[] arr = new byte[numEntries];
  759                   for (int i = 0; i < numEntries; i++) {
  760                       arr[i] = (byte)(i*255/(numEntries - 1));
  761                   }
  762                   this.colorModel =
  763                       new IndexColorModel(bits, numEntries, arr, arr, arr);
  764   
  765                   this.sampleModel =
  766                       new MultiPixelPackedSampleModel(dataType, 1, 1, bits);
  767               }
  768           }
  769       }
  770   
  771       /**
  772        * Returns a specifier for a grayscale image format that will pack
  773        * pixels of the given bit depth into array elements of
  774        * the specified data type.
  775        *
  776        * @param bits the number of bits per gray value (1, 2, 4, 8, or 16).
  777        * @param dataType the desired data type, as one of the enumerations
  778        * from the <code>DataBuffer</code> class.
  779        * @param isSigned <code>true</code> if negative values are to
  780        * be represented.
  781        *
  782        * @return an <code>ImageTypeSpecifier</code> with the desired
  783        * characteristics.
  784        *
  785        * @exception IllegalArgumentException if <code>bits</code> is
  786        * not one of 1, 2, 4, 8, or 16.
  787        * @exception IllegalArgumentException if <code>dataType</code> is
  788        * not one of <code>DataBuffer.TYPE_BYTE</code>,
  789        * <code>DataBuffer.TYPE_SHORT</code>, or
  790        * <code>DataBuffer.TYPE_USHORT</code>.
  791        * @exception IllegalArgumentException if <code>bits</code> is
  792        * larger than the bit size of the given <code>dataType</code>.
  793        */
  794       public static ImageTypeSpecifier
  795           createGrayscale(int bits,
  796                           int dataType,
  797                           boolean isSigned) {
  798           return new ImageTypeSpecifier.Grayscale(bits,
  799                                                   dataType,
  800                                                   isSigned,
  801                                                   false,
  802                                                   false);
  803       }
  804   
  805       /**
  806        * Returns a specifier for a grayscale plus alpha image format
  807        * that will pack pixels of the given bit depth into array
  808        * elements of the specified data type.
  809        *
  810        * @param bits the number of bits per gray value (1, 2, 4, 8, or 16).
  811        * @param dataType the desired data type, as one of the enumerations
  812        * from the <code>DataBuffer</code> class.
  813        * @param isSigned <code>true</code> if negative values are to
  814        * be represented.
  815        * @param isAlphaPremultiplied <code>true</code> if the luminance channel
  816        * will be premultipled by the alpha channel.
  817        *
  818        * @return an <code>ImageTypeSpecifier</code> with the desired
  819        * characteristics.
  820        *
  821        * @exception IllegalArgumentException if <code>bits</code> is
  822        * not one of 1, 2, 4, 8, or 16.
  823        * @exception IllegalArgumentException if <code>dataType</code> is
  824        * not one of <code>DataBuffer.TYPE_BYTE</code>,
  825        * <code>DataBuffer.TYPE_SHORT</code>, or
  826        * <code>DataBuffer.TYPE_USHORT</code>.
  827        * @exception IllegalArgumentException if <code>bits</code> is
  828        * larger than the bit size of the given <code>dataType</code>.
  829        */
  830       public static ImageTypeSpecifier
  831           createGrayscale(int bits,
  832                           int dataType,
  833                           boolean isSigned,
  834                           boolean isAlphaPremultiplied) {
  835           return new ImageTypeSpecifier.Grayscale(bits,
  836                                                   dataType,
  837                                                   isSigned,
  838                                                   true,
  839                                                   isAlphaPremultiplied);
  840       }
  841   
  842       // Indexed
  843   
  844       static class Indexed extends ImageTypeSpecifier {
  845           byte[] redLUT;
  846           byte[] greenLUT;
  847           byte[] blueLUT;
  848           byte[] alphaLUT = null;
  849           int bits;
  850           int dataType;
  851   
  852           public Indexed(byte[] redLUT,
  853                          byte[] greenLUT,
  854                          byte[] blueLUT,
  855                          byte[] alphaLUT,
  856                          int bits,
  857                          int dataType) {
  858               if (redLUT == null || greenLUT == null || blueLUT == null) {
  859                   throw new IllegalArgumentException("LUT is null!");
  860               }
  861               if (bits != 1 && bits != 2 && bits != 4 &&
  862                   bits != 8 && bits != 16) {
  863                   throw new IllegalArgumentException("Bad value for bits!");
  864               }
  865               if (dataType != DataBuffer.TYPE_BYTE &&
  866                   dataType != DataBuffer.TYPE_SHORT &&
  867                   dataType != DataBuffer.TYPE_USHORT &&
  868                   dataType != DataBuffer.TYPE_INT) {
  869                   throw new IllegalArgumentException
  870                       ("Bad value for dataType!");
  871               }
  872               if ((bits > 8 && dataType == DataBuffer.TYPE_BYTE) ||
  873                   (bits > 16 && dataType != DataBuffer.TYPE_INT)) {
  874                   throw new IllegalArgumentException
  875                       ("Too many bits for dataType!");
  876               }
  877   
  878               int len = 1 << bits;
  879               if (redLUT.length != len ||
  880                   greenLUT.length != len ||
  881                   blueLUT.length != len ||
  882                   (alphaLUT != null && alphaLUT.length != len)) {
  883                   throw new IllegalArgumentException("LUT has improper length!");
  884               }
  885               this.redLUT = (byte[])redLUT.clone();
  886               this.greenLUT = (byte[])greenLUT.clone();
  887               this.blueLUT = (byte[])blueLUT.clone();
  888               if (alphaLUT != null) {
  889                   this.alphaLUT = (byte[])alphaLUT.clone();
  890               }
  891               this.bits = bits;
  892               this.dataType = dataType;
  893   
  894               if (alphaLUT == null) {
  895                   this.colorModel = new IndexColorModel(bits,
  896                                                         redLUT.length,
  897                                                         redLUT,
  898                                                         greenLUT,
  899                                                         blueLUT);
  900               } else {
  901                   this.colorModel = new IndexColorModel(bits,
  902                                                         redLUT.length,
  903                                                         redLUT,
  904                                                         greenLUT,
  905                                                         blueLUT,
  906                                                         alphaLUT);
  907               }
  908   
  909               if ((bits == 8 && dataType == DataBuffer.TYPE_BYTE) ||
  910                   (bits == 16 &&
  911                    (dataType == DataBuffer.TYPE_SHORT ||
  912                     dataType == DataBuffer.TYPE_USHORT))) {
  913                   int[] bandOffsets = { 0 };
  914                   this.sampleModel =
  915                       new PixelInterleavedSampleModel(dataType,
  916                                                       1, 1, 1, 1,
  917                                                       bandOffsets);
  918               } else {
  919                   this.sampleModel =
  920                       new MultiPixelPackedSampleModel(dataType, 1, 1, bits);
  921               }
  922           }
  923       }
  924   
  925       /**
  926        * Returns a specifier for an indexed-color image format that will pack
  927        * index values of the given bit depth into array elements of
  928        * the specified data type.
  929        *
  930        * @param redLUT an array of <code>byte</code>s containing
  931        * the red values for each index.
  932        * @param greenLUT an array of <code>byte</code>s containing * the
  933        *  green values for each index.
  934        * @param blueLUT an array of <code>byte</code>s containing the
  935        * blue values for each index.
  936        * @param alphaLUT an array of <code>byte</code>s containing the
  937        * alpha values for each index, or <code>null</code> to create a
  938        * fully opaque LUT.
  939        * @param bits the number of bits in each index.
  940        * @param dataType the desired output type, as one of the enumerations
  941        * from the <code>DataBuffer</code> class.
  942        *
  943        * @return an <code>ImageTypeSpecifier</code> with the desired
  944        * characteristics.
  945        *
  946        * @exception IllegalArgumentException if <code>redLUT</code> is
  947        * <code>null</code>.
  948        * @exception IllegalArgumentException if <code>greenLUT</code> is
  949        * <code>null</code>.
  950        * @exception IllegalArgumentException if <code>blueLUT</code> is
  951        * <code>null</code>.
  952        * @exception IllegalArgumentException if <code>bits</code> is
  953        * not one of 1, 2, 4, 8, or 16.
  954        * @exception IllegalArgumentException if the
  955        * non-<code>null</code> LUT parameters do not have lengths of
  956        * exactly <code>1 << bits</code>.
  957        * @exception IllegalArgumentException if <code>dataType</code> is
  958        * not one of <code>DataBuffer.TYPE_BYTE</code>,
  959        * <code>DataBuffer.TYPE_SHORT</code>,
  960        * <code>DataBuffer.TYPE_USHORT</code>,
  961        * or <code>DataBuffer.TYPE_INT</code>.
  962        * @exception IllegalArgumentException if <code>bits</code> is
  963        * larger than the bit size of the given <code>dataType</code>.
  964        */
  965       public static ImageTypeSpecifier
  966           createIndexed(byte[] redLUT,
  967                         byte[] greenLUT,
  968                         byte[] blueLUT,
  969                         byte[] alphaLUT,
  970                         int bits,
  971                         int dataType) {
  972           return new ImageTypeSpecifier.Indexed(redLUT,
  973                                                 greenLUT,
  974                                                 blueLUT,
  975                                                 alphaLUT,
  976                                                 bits,
  977                                                 dataType);
  978       }
  979   
  980       /**
  981        * Returns an <code>ImageTypeSpecifier</code> that encodes
  982        * one of the standard <code>BufferedImage</code> types
  983        * (other than <code>TYPE_CUSTOM</code>).
  984        *
  985        * @param bufferedImageType an int representing one of the standard
  986        * <code>BufferedImage</code> types.
  987        *
  988        * @return an <code>ImageTypeSpecifier</code> with the desired
  989        * characteristics.
  990        *
  991        * @exception IllegalArgumentException if
  992        * <code>bufferedImageType</code> is not one of the standard
  993        * types, or is equal to <code>TYPE_CUSTOM</code>.
  994        *
  995        * @see java.awt.image.BufferedImage
  996        * @see java.awt.image.BufferedImage#TYPE_INT_RGB
  997        * @see java.awt.image.BufferedImage#TYPE_INT_ARGB
  998        * @see java.awt.image.BufferedImage#TYPE_INT_ARGB_PRE
  999        * @see java.awt.image.BufferedImage#TYPE_INT_BGR
 1000        * @see java.awt.image.BufferedImage#TYPE_3BYTE_BGR
 1001        * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR
 1002        * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR_PRE
 1003        * @see java.awt.image.BufferedImage#TYPE_USHORT_565_RGB
 1004        * @see java.awt.image.BufferedImage#TYPE_USHORT_555_RGB
 1005        * @see java.awt.image.BufferedImage#TYPE_BYTE_GRAY
 1006        * @see java.awt.image.BufferedImage#TYPE_USHORT_GRAY
 1007        * @see java.awt.image.BufferedImage#TYPE_BYTE_BINARY
 1008        * @see java.awt.image.BufferedImage#TYPE_BYTE_INDEXED
 1009        */
 1010       public static
 1011           ImageTypeSpecifier createFromBufferedImageType(int bufferedImageType) {
 1012           if (bufferedImageType >= BufferedImage.TYPE_INT_RGB &&
 1013               bufferedImageType <= BufferedImage.TYPE_BYTE_INDEXED) {
 1014               return BISpecifier[bufferedImageType];
 1015           } else if (bufferedImageType == BufferedImage.TYPE_CUSTOM) {
 1016               throw new IllegalArgumentException("Cannot create from TYPE_CUSTOM!");
 1017           } else {
 1018               throw new IllegalArgumentException("Invalid BufferedImage type!");
 1019           }
 1020       }
 1021   
 1022       /**
 1023        * Returns an <code>ImageTypeSpecifier</code> that encodes the
 1024        * layout of a <code>RenderedImage</code> (which may be a
 1025        * <code>BufferedImage</code>).
 1026        *
 1027        * @param image a <code>RenderedImage</code>.
 1028        *
 1029        * @return an <code>ImageTypeSpecifier</code> with the desired
 1030        * characteristics.
 1031        *
 1032        * @exception IllegalArgumentException if <code>image</code> is
 1033        * <code>null</code>.
 1034        */
 1035       public static
 1036           ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
 1037           if (image == null) {
 1038               throw new IllegalArgumentException("image == null!");
 1039           }
 1040   
 1041           if (image instanceof BufferedImage) {
 1042               int bufferedImageType = ((BufferedImage)image).getType();
 1043               if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
 1044                   return BISpecifier[bufferedImageType];
 1045               }
 1046           }
 1047   
 1048           return new ImageTypeSpecifier(image);
 1049       }
 1050   
 1051       /**
 1052        * Returns an int containing one of the enumerated constant values
 1053        * describing image formats from <code>BufferedImage</code>.
 1054        *
 1055        * @return an <code>int</code> representing a
 1056        * <code>BufferedImage</code> type.
 1057        *
 1058        * @see java.awt.image.BufferedImage
 1059        * @see java.awt.image.BufferedImage#TYPE_CUSTOM
 1060        * @see java.awt.image.BufferedImage#TYPE_INT_RGB
 1061        * @see java.awt.image.BufferedImage#TYPE_INT_ARGB
 1062        * @see java.awt.image.BufferedImage#TYPE_INT_ARGB_PRE
 1063        * @see java.awt.image.BufferedImage#TYPE_INT_BGR
 1064        * @see java.awt.image.BufferedImage#TYPE_3BYTE_BGR
 1065        * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR
 1066        * @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR_PRE
 1067        * @see java.awt.image.BufferedImage#TYPE_USHORT_565_RGB
 1068        * @see java.awt.image.BufferedImage#TYPE_USHORT_555_RGB
 1069        * @see java.awt.image.BufferedImage#TYPE_BYTE_GRAY
 1070        * @see java.awt.image.BufferedImage#TYPE_USHORT_GRAY
 1071        * @see java.awt.image.BufferedImage#TYPE_BYTE_BINARY
 1072        * @see java.awt.image.BufferedImage#TYPE_BYTE_INDEXED
 1073        */
 1074       public int getBufferedImageType() {
 1075           BufferedImage bi = createBufferedImage(1, 1);
 1076           return bi.getType();
 1077       }
 1078   
 1079       /**
 1080        * Return the number of color components
 1081        * specified by this object.  This is the same value as returned by
 1082        * <code>ColorModel.getNumComponents</code>
 1083        *
 1084        * @return the number of components in the image.
 1085        */
 1086       public int getNumComponents() {
 1087           return colorModel.getNumComponents();
 1088       }
 1089   
 1090       /**
 1091        * Return the number of bands
 1092        * specified by this object.  This is the same value as returned by
 1093        * <code>SampleModel.getNumBands</code>
 1094        *
 1095        * @return the number of bands in the image.
 1096        */
 1097       public int getNumBands() {
 1098           return sampleModel.getNumBands();
 1099       }
 1100   
 1101       /**
 1102        * Return the number of bits used to represent samples of the given band.
 1103        *
 1104        * @param band the index of the band to be queried, as an
 1105        * int.
 1106        *
 1107        * @return an int specifying a number of bits.
 1108        *
 1109        * @exception IllegalArgumentException if <code>band</code> is
 1110        * negative or greater than the largest band index.
 1111        */
 1112       public int getBitsPerBand(int band) {
 1113           if (band < 0 | band >= getNumBands()) {
 1114               throw new IllegalArgumentException("band out of range!");
 1115           }
 1116           return sampleModel.getSampleSize(band);
 1117       }
 1118   
 1119       /**
 1120        * Returns a <code>SampleModel</code> based on the settings
 1121        * encapsulated within this object.  The width and height of the
 1122        * <code>SampleModel</code> will be set to arbitrary values.
 1123        *
 1124        * @return a <code>SampleModel</code> with arbitrary dimensions.
 1125        */
 1126       public SampleModel getSampleModel() {
 1127           return sampleModel;
 1128       }
 1129   
 1130       /**
 1131        * Returns a <code>SampleModel</code> based on the settings
 1132        * encapsulated within this object.  The width and height of the
 1133        * <code>SampleModel</code> will be set to the supplied values.
 1134        *
 1135        * @param width the desired width of the returned <code>SampleModel</code>.
 1136        * @param height the desired height of the returned
 1137        * <code>SampleModel</code>.
 1138        *
 1139        * @return a <code>SampleModel</code> with the given dimensions.
 1140        *
 1141        * @exception IllegalArgumentException if either <code>width</code> or
 1142        * <code>height</code> are negative or zero.
 1143        * @exception IllegalArgumentException if the product of
 1144        * <code>width</code> and <code>height</code> is greater than
 1145        * <code>Integer.MAX_VALUE</code>
 1146        */
 1147       public SampleModel getSampleModel(int width, int height) {
 1148           if ((long)width*height > Integer.MAX_VALUE) {
 1149               throw new IllegalArgumentException
 1150                   ("width*height > Integer.MAX_VALUE!");
 1151           }
 1152           return sampleModel.createCompatibleSampleModel(width, height);
 1153       }
 1154   
 1155       /**
 1156        * Returns the <code>ColorModel</code> specified by this object.
 1157        *
 1158        * @return a <code>ColorModel</code>.
 1159        */
 1160       public ColorModel getColorModel() {
 1161           return colorModel;
 1162       }
 1163   
 1164       /**
 1165        * Creates a <code>BufferedImage</code> with a given width and
 1166        * height according to the specification embodied in this object.
 1167        *
 1168        * @param width the desired width of the returned
 1169        * <code>BufferedImage</code>.
 1170        * @param height the desired height of the returned
 1171        * <code>BufferedImage</code>.
 1172        *
 1173        * @return a new <code>BufferedImage</code>
 1174        *
 1175        * @exception IllegalArgumentException if either <code>width</code> or
 1176        * <code>height</code> are negative or zero.
 1177        * @exception IllegalArgumentException if the product of
 1178        * <code>width</code> and <code>height</code> is greater than
 1179        * <code>Integer.MAX_VALUE</code>, or if the number of array
 1180        * elements needed to store the image is greater than
 1181        * <code>Integer.MAX_VALUE</code>.
 1182        */
 1183       public BufferedImage createBufferedImage(int width, int height) {
 1184           try {
 1185               SampleModel sampleModel = getSampleModel(width, height);
 1186               WritableRaster raster =
 1187                   Raster.createWritableRaster(sampleModel,
 1188                                               new Point(0, 0));
 1189               return new BufferedImage(colorModel, raster,
 1190                                        colorModel.isAlphaPremultiplied(),
 1191                                        new Hashtable());
 1192           } catch (NegativeArraySizeException e) {
 1193               // Exception most likely thrown from a DataBuffer constructor
 1194               throw new IllegalArgumentException
 1195                   ("Array size > Integer.MAX_VALUE!");
 1196           }
 1197       }
 1198   
 1199       /**
 1200        * Returns <code>true</code> if the given <code>Object</code> is
 1201        * an <code>ImageTypeSpecifier</code> and has a
 1202        * <code>SampleModel</code> and <code>ColorModel</code> that are
 1203        * equal to those of this object.
 1204        *
 1205        * @param o the <code>Object</code> to be compared for equality.
 1206        *
 1207        * @return <code>true</code> if the given object is an equivalent
 1208        * <code>ImageTypeSpecifier</code>.
 1209        */
 1210       public boolean equals(Object o) {
 1211           if ((o == null) || !(o instanceof ImageTypeSpecifier)) {
 1212               return false;
 1213           }
 1214   
 1215           ImageTypeSpecifier that = (ImageTypeSpecifier)o;
 1216           return (colorModel.equals(that.colorModel)) &&
 1217               (sampleModel.equals(that.sampleModel));
 1218       }
 1219   
 1220       /**
 1221        * Returns the hash code for this ImageTypeSpecifier.
 1222        *
 1223        * @return a hash code for this ImageTypeSpecifier
 1224        */
 1225       public int hashCode() {
 1226           return (9 * colorModel.hashCode()) + (14 * sampleModel.hashCode());
 1227       }
 1228   }

Save This Page
Home » openjdk-7 » javax » imageio » [javadoc | source]