src/java.desktop/share/classes/java/awt/image/ComponentSampleModel.java
changeset 47216 71c04702a3d5
parent 35667 ed476aba94de
child 52248 2e330da7cbf4
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1997, 2015, 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 /* ****************************************************************
       
    27  ******************************************************************
       
    28  ******************************************************************
       
    29  *** COPYRIGHT (c) Eastman Kodak Company, 1997
       
    30  *** As  an unpublished  work pursuant to Title 17 of the United
       
    31  *** States Code.  All rights reserved.
       
    32  ******************************************************************
       
    33  ******************************************************************
       
    34  ******************************************************************/
       
    35 
       
    36 package java.awt.image;
       
    37 
       
    38 import java.util.Arrays;
       
    39 
       
    40 /**
       
    41  *  This class represents image data which is stored such that each sample
       
    42  *  of a pixel occupies one data element of the DataBuffer.  It stores the
       
    43  *  N samples which make up a pixel in N separate data array elements.
       
    44  *  Different bands may be in different banks of the DataBuffer.
       
    45  *  Accessor methods are provided so that image data can be manipulated
       
    46  *  directly. This class can support different kinds of interleaving, e.g.
       
    47  *  band interleaving, scanline interleaving, and pixel interleaving.
       
    48  *  Pixel stride is the number of data array elements between two samples
       
    49  *  for the same band on the same scanline. Scanline stride is the number
       
    50  *  of data array elements between a given sample and the corresponding sample
       
    51  *  in the same column of the next scanline.  Band offsets denote the number
       
    52  *  of data array elements from the first data array element of the bank
       
    53  *  of the DataBuffer holding each band to the first sample of the band.
       
    54  *  The bands are numbered from 0 to N-1.  This class can represent image
       
    55  *  data for which each sample is an unsigned integral number which can be
       
    56  *  stored in 8, 16, or 32 bits (using {@code DataBuffer.TYPE_BYTE},
       
    57  *  {@code DataBuffer.TYPE_USHORT}, or {@code DataBuffer.TYPE_INT},
       
    58  *  respectively), data for which each sample is a signed integral number
       
    59  *  which can be stored in 16 bits (using {@code DataBuffer.TYPE_SHORT}),
       
    60  *  or data for which each sample is a signed float or double quantity
       
    61  *  (using {@code DataBuffer.TYPE_FLOAT} or
       
    62  *  {@code DataBuffer.TYPE_DOUBLE}, respectively).
       
    63  *  All samples of a given ComponentSampleModel
       
    64  *  are stored with the same precision.  All strides and offsets must be
       
    65  *  non-negative.  This class supports
       
    66  *  {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
       
    67  *  {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
       
    68  *  {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
       
    69  *  {@link DataBuffer#TYPE_INT TYPE_INT},
       
    70  *  {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT},
       
    71  *  {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE},
       
    72  *  @see java.awt.image.PixelInterleavedSampleModel
       
    73  *  @see java.awt.image.BandedSampleModel
       
    74  */
       
    75 
       
    76 public class ComponentSampleModel extends SampleModel
       
    77 {
       
    78     /** Offsets for all bands in data array elements. */
       
    79     protected int bandOffsets[];
       
    80 
       
    81     /** Index for each bank storing a band of image data. */
       
    82     protected int[] bankIndices;
       
    83 
       
    84     /**
       
    85      * The number of bands in this
       
    86      * {@code ComponentSampleModel}.
       
    87      */
       
    88     protected int numBands = 1;
       
    89 
       
    90     /**
       
    91      * The number of banks in this
       
    92      * {@code ComponentSampleModel}.
       
    93      */
       
    94     protected int numBanks = 1;
       
    95 
       
    96     /**
       
    97      *  Line stride (in data array elements) of the region of image
       
    98      *  data described by this ComponentSampleModel.
       
    99      */
       
   100     protected int scanlineStride;
       
   101 
       
   102     /** Pixel stride (in data array elements) of the region of image
       
   103      *  data described by this ComponentSampleModel.
       
   104      */
       
   105     protected int pixelStride;
       
   106 
       
   107     /**
       
   108      * Constructs a ComponentSampleModel with the specified parameters.
       
   109      * The number of bands will be given by the length of the bandOffsets array.
       
   110      * All bands will be stored in the first bank of the DataBuffer.
       
   111      * @param dataType  the data type for storing samples
       
   112      * @param w         the width (in pixels) of the region of
       
   113      *     image data described
       
   114      * @param h         the height (in pixels) of the region of
       
   115      *     image data described
       
   116      * @param pixelStride the pixel stride of the region of image
       
   117      *     data described
       
   118      * @param scanlineStride the line stride of the region of image
       
   119      *     data described
       
   120      * @param bandOffsets the offsets of all bands
       
   121      * @throws IllegalArgumentException if {@code w} or
       
   122      *         {@code h} is not greater than 0
       
   123      * @throws IllegalArgumentException if {@code pixelStride}
       
   124      *         is less than 0
       
   125      * @throws IllegalArgumentException if {@code scanlineStride}
       
   126      *         is less than 0
       
   127      * @throws IllegalArgumentException if {@code numBands}
       
   128      *         is less than 1
       
   129      * @throws IllegalArgumentException if the product of {@code w}
       
   130      *         and {@code h} is greater than
       
   131      *         {@code Integer.MAX_VALUE}
       
   132      * @throws IllegalArgumentException if {@code dataType} is not
       
   133      *         one of the supported data types
       
   134      */
       
   135     public ComponentSampleModel(int dataType,
       
   136                                 int w, int h,
       
   137                                 int pixelStride,
       
   138                                 int scanlineStride,
       
   139                                 int bandOffsets[]) {
       
   140         super(dataType, w, h, bandOffsets.length);
       
   141         this.dataType = dataType;
       
   142         this.pixelStride = pixelStride;
       
   143         this.scanlineStride  = scanlineStride;
       
   144         this.bandOffsets = bandOffsets.clone();
       
   145         numBands = this.bandOffsets.length;
       
   146         if (pixelStride < 0) {
       
   147             throw new IllegalArgumentException("Pixel stride must be >= 0");
       
   148         }
       
   149         // TODO - bug 4296691 - remove this check
       
   150         if (scanlineStride < 0) {
       
   151             throw new IllegalArgumentException("Scanline stride must be >= 0");
       
   152         }
       
   153         if (numBands < 1) {
       
   154             throw new IllegalArgumentException("Must have at least one band.");
       
   155         }
       
   156         if ((dataType < DataBuffer.TYPE_BYTE) ||
       
   157             (dataType > DataBuffer.TYPE_DOUBLE)) {
       
   158             throw new IllegalArgumentException("Unsupported dataType.");
       
   159         }
       
   160         bankIndices = new int[numBands];
       
   161         for (int i=0; i<numBands; i++) {
       
   162             bankIndices[i] = 0;
       
   163         }
       
   164         verify();
       
   165     }
       
   166 
       
   167 
       
   168     /**
       
   169      * Constructs a ComponentSampleModel with the specified parameters.
       
   170      * The number of bands will be given by the length of the bandOffsets array.
       
   171      * Different bands may be stored in different banks of the DataBuffer.
       
   172      *
       
   173      * @param dataType  the data type for storing samples
       
   174      * @param w         the width (in pixels) of the region of
       
   175      *     image data described
       
   176      * @param h         the height (in pixels) of the region of
       
   177      *     image data described
       
   178      * @param pixelStride the pixel stride of the region of image
       
   179      *     data described
       
   180      * @param scanlineStride The line stride of the region of image
       
   181      *     data described
       
   182      * @param bankIndices the bank indices of all bands
       
   183      * @param bandOffsets the band offsets of all bands
       
   184      * @throws IllegalArgumentException if {@code w} or
       
   185      *         {@code h} is not greater than 0
       
   186      * @throws IllegalArgumentException if {@code pixelStride}
       
   187      *         is less than 0
       
   188      * @throws IllegalArgumentException if {@code scanlineStride}
       
   189      *         is less than 0
       
   190      * @throws IllegalArgumentException if the length of
       
   191      *         {@code bankIndices} does not equal the length of
       
   192      *         {@code bankOffsets}
       
   193      * @throws IllegalArgumentException if any of the bank indices
       
   194      *         of {@code bandIndices} is less than 0
       
   195      * @throws IllegalArgumentException if {@code dataType} is not
       
   196      *         one of the supported data types
       
   197      */
       
   198     public ComponentSampleModel(int dataType,
       
   199                                 int w, int h,
       
   200                                 int pixelStride,
       
   201                                 int scanlineStride,
       
   202                                 int bankIndices[],
       
   203                                 int bandOffsets[]) {
       
   204         super(dataType, w, h, bandOffsets.length);
       
   205         this.dataType = dataType;
       
   206         this.pixelStride = pixelStride;
       
   207         this.scanlineStride  = scanlineStride;
       
   208         this.bandOffsets = bandOffsets.clone();
       
   209         this.bankIndices = bankIndices.clone();
       
   210         if (pixelStride < 0) {
       
   211             throw new IllegalArgumentException("Pixel stride must be >= 0");
       
   212         }
       
   213         // TODO - bug 4296691 - remove this check
       
   214         if (scanlineStride < 0) {
       
   215             throw new IllegalArgumentException("Scanline stride must be >= 0");
       
   216         }
       
   217         if ((dataType < DataBuffer.TYPE_BYTE) ||
       
   218             (dataType > DataBuffer.TYPE_DOUBLE)) {
       
   219             throw new IllegalArgumentException("Unsupported dataType.");
       
   220         }
       
   221         int maxBank = this.bankIndices[0];
       
   222         if (maxBank < 0) {
       
   223             throw new IllegalArgumentException("Index of bank 0 is less than "+
       
   224                                                "0 ("+maxBank+")");
       
   225         }
       
   226         for (int i=1; i < this.bankIndices.length; i++) {
       
   227             if (this.bankIndices[i] > maxBank) {
       
   228                 maxBank = this.bankIndices[i];
       
   229             }
       
   230             else if (this.bankIndices[i] < 0) {
       
   231                 throw new IllegalArgumentException("Index of bank "+i+
       
   232                                                    " is less than 0 ("+
       
   233                                                    maxBank+")");
       
   234             }
       
   235         }
       
   236         numBanks         = maxBank+1;
       
   237         numBands         = this.bandOffsets.length;
       
   238         if (this.bandOffsets.length != this.bankIndices.length) {
       
   239             throw new IllegalArgumentException("Length of bandOffsets must "+
       
   240                                                "equal length of bankIndices.");
       
   241         }
       
   242         verify();
       
   243     }
       
   244 
       
   245     private void verify() {
       
   246         int requiredSize = getBufferSize();
       
   247     }
       
   248 
       
   249     /**
       
   250      * Returns the size of the data buffer (in data elements) needed
       
   251      * for a data buffer that matches this ComponentSampleModel.
       
   252      */
       
   253      private int getBufferSize() {
       
   254          int maxBandOff=bandOffsets[0];
       
   255          for (int i=1; i<bandOffsets.length; i++) {
       
   256              maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
       
   257          }
       
   258 
       
   259          if (maxBandOff < 0 || maxBandOff > (Integer.MAX_VALUE - 1)) {
       
   260              throw new IllegalArgumentException("Invalid band offset");
       
   261          }
       
   262 
       
   263          if (pixelStride < 0 || pixelStride > (Integer.MAX_VALUE / width)) {
       
   264              throw new IllegalArgumentException("Invalid pixel stride");
       
   265          }
       
   266 
       
   267          if (scanlineStride < 0 || scanlineStride > (Integer.MAX_VALUE / height)) {
       
   268              throw new IllegalArgumentException("Invalid scanline stride");
       
   269          }
       
   270 
       
   271          int size = maxBandOff + 1;
       
   272 
       
   273          int val = pixelStride * (width - 1);
       
   274 
       
   275          if (val > (Integer.MAX_VALUE - size)) {
       
   276              throw new IllegalArgumentException("Invalid pixel stride");
       
   277          }
       
   278 
       
   279          size += val;
       
   280 
       
   281          val = scanlineStride * (height - 1);
       
   282 
       
   283          if (val > (Integer.MAX_VALUE - size)) {
       
   284              throw new IllegalArgumentException("Invalid scan stride");
       
   285          }
       
   286 
       
   287          size += val;
       
   288 
       
   289          return size;
       
   290      }
       
   291 
       
   292      /**
       
   293       * Preserves band ordering with new step factor...
       
   294       */
       
   295     int []orderBands(int orig[], int step) {
       
   296         int map[] = new int[orig.length];
       
   297         int ret[] = new int[orig.length];
       
   298 
       
   299         for (int i=0; i<map.length; i++) map[i] = i;
       
   300 
       
   301         for (int i = 0; i < ret.length; i++) {
       
   302             int index = i;
       
   303             for (int j = i+1; j < ret.length; j++) {
       
   304                 if (orig[map[index]] > orig[map[j]]) {
       
   305                     index = j;
       
   306                 }
       
   307             }
       
   308             ret[map[index]] = i*step;
       
   309             map[index]  = map[i];
       
   310         }
       
   311         return ret;
       
   312     }
       
   313 
       
   314     /**
       
   315      * Creates a new {@code ComponentSampleModel} with the specified
       
   316      * width and height.  The new {@code SampleModel} will have the same
       
   317      * number of bands, storage data type, interleaving scheme, and
       
   318      * pixel stride as this {@code SampleModel}.
       
   319      * @param w the width of the resulting {@code SampleModel}
       
   320      * @param h the height of the resulting {@code SampleModel}
       
   321      * @return a new {@code ComponentSampleModel} with the specified size
       
   322      * @throws IllegalArgumentException if {@code w} or
       
   323      *         {@code h} is not greater than 0
       
   324      */
       
   325     public SampleModel createCompatibleSampleModel(int w, int h) {
       
   326         SampleModel ret=null;
       
   327         long size;
       
   328         int minBandOff=bandOffsets[0];
       
   329         int maxBandOff=bandOffsets[0];
       
   330         for (int i=1; i<bandOffsets.length; i++) {
       
   331             minBandOff = Math.min(minBandOff,bandOffsets[i]);
       
   332             maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
       
   333         }
       
   334         maxBandOff -= minBandOff;
       
   335 
       
   336         int bands   = bandOffsets.length;
       
   337         int bandOff[];
       
   338         int pStride = Math.abs(pixelStride);
       
   339         int lStride = Math.abs(scanlineStride);
       
   340         int bStride = Math.abs(maxBandOff);
       
   341 
       
   342         if (pStride > lStride) {
       
   343             if (pStride > bStride) {
       
   344                 if (lStride > bStride) { // pix > line > band
       
   345                     bandOff = new int[bandOffsets.length];
       
   346                     for (int i=0; i<bands; i++)
       
   347                         bandOff[i] = bandOffsets[i]-minBandOff;
       
   348                     lStride = bStride+1;
       
   349                     pStride = lStride*h;
       
   350                 } else { // pix > band > line
       
   351                     bandOff = orderBands(bandOffsets,lStride*h);
       
   352                     pStride = bands*lStride*h;
       
   353                 }
       
   354             } else { // band > pix > line
       
   355                 pStride = lStride*h;
       
   356                 bandOff = orderBands(bandOffsets,pStride*w);
       
   357             }
       
   358         } else {
       
   359             if (pStride > bStride) { // line > pix > band
       
   360                 bandOff = new int[bandOffsets.length];
       
   361                 for (int i=0; i<bands; i++)
       
   362                     bandOff[i] = bandOffsets[i]-minBandOff;
       
   363                 pStride = bStride+1;
       
   364                 lStride = pStride*w;
       
   365             } else {
       
   366                 if (lStride > bStride) { // line > band > pix
       
   367                     bandOff = orderBands(bandOffsets,pStride*w);
       
   368                     lStride = bands*pStride*w;
       
   369                 } else { // band > line > pix
       
   370                     lStride = pStride*w;
       
   371                     bandOff = orderBands(bandOffsets,lStride*h);
       
   372                 }
       
   373             }
       
   374         }
       
   375 
       
   376         // make sure we make room for negative offsets...
       
   377         int base = 0;
       
   378         if (scanlineStride < 0) {
       
   379             base += lStride*h;
       
   380             lStride *= -1;
       
   381         }
       
   382         if (pixelStride    < 0) {
       
   383             base += pStride*w;
       
   384             pStride *= -1;
       
   385         }
       
   386 
       
   387         for (int i=0; i<bands; i++)
       
   388             bandOff[i] += base;
       
   389         return new ComponentSampleModel(dataType, w, h, pStride,
       
   390                                         lStride, bankIndices, bandOff);
       
   391     }
       
   392 
       
   393     /**
       
   394      * Creates a new ComponentSampleModel with a subset of the bands
       
   395      * of this ComponentSampleModel.  The new ComponentSampleModel can be
       
   396      * used with any DataBuffer that the existing ComponentSampleModel
       
   397      * can be used with.  The new ComponentSampleModel/DataBuffer
       
   398      * combination will represent an image with a subset of the bands
       
   399      * of the original ComponentSampleModel/DataBuffer combination.
       
   400      * @param bands a subset of bands from this
       
   401      *              {@code ComponentSampleModel}
       
   402      * @return a {@code ComponentSampleModel} created with a subset
       
   403      *          of bands from this {@code ComponentSampleModel}.
       
   404      */
       
   405     public SampleModel createSubsetSampleModel(int bands[]) {
       
   406        if (bands.length > bankIndices.length)
       
   407             throw new RasterFormatException("There are only " +
       
   408                                             bankIndices.length +
       
   409                                             " bands");
       
   410         int newBankIndices[] = new int[bands.length];
       
   411         int newBandOffsets[] = new int[bands.length];
       
   412 
       
   413         for (int i=0; i<bands.length; i++) {
       
   414             newBankIndices[i] = bankIndices[bands[i]];
       
   415             newBandOffsets[i] = bandOffsets[bands[i]];
       
   416         }
       
   417 
       
   418         return new ComponentSampleModel(this.dataType, width, height,
       
   419                                         this.pixelStride,
       
   420                                         this.scanlineStride,
       
   421                                         newBankIndices, newBandOffsets);
       
   422     }
       
   423 
       
   424     /**
       
   425      * Creates a {@code DataBuffer} that corresponds to this
       
   426      * {@code ComponentSampleModel}.
       
   427      * The {@code DataBuffer} object's data type, number of banks,
       
   428      * and size are be consistent with this {@code ComponentSampleModel}.
       
   429      * @return a {@code DataBuffer} whose data type, number of banks
       
   430      *         and size are consistent with this
       
   431      *         {@code ComponentSampleModel}.
       
   432      */
       
   433     public DataBuffer createDataBuffer() {
       
   434         DataBuffer dataBuffer = null;
       
   435 
       
   436         int size = getBufferSize();
       
   437         switch (dataType) {
       
   438         case DataBuffer.TYPE_BYTE:
       
   439             dataBuffer = new DataBufferByte(size, numBanks);
       
   440             break;
       
   441         case DataBuffer.TYPE_USHORT:
       
   442             dataBuffer = new DataBufferUShort(size, numBanks);
       
   443             break;
       
   444         case DataBuffer.TYPE_SHORT:
       
   445             dataBuffer = new DataBufferShort(size, numBanks);
       
   446             break;
       
   447         case DataBuffer.TYPE_INT:
       
   448             dataBuffer = new DataBufferInt(size, numBanks);
       
   449             break;
       
   450         case DataBuffer.TYPE_FLOAT:
       
   451             dataBuffer = new DataBufferFloat(size, numBanks);
       
   452             break;
       
   453         case DataBuffer.TYPE_DOUBLE:
       
   454             dataBuffer = new DataBufferDouble(size, numBanks);
       
   455             break;
       
   456         }
       
   457 
       
   458         return dataBuffer;
       
   459     }
       
   460 
       
   461 
       
   462     /** Gets the offset for the first band of pixel (x,y).
       
   463      *  A sample of the first band can be retrieved from a
       
   464      * {@code DataBuffer}
       
   465      *  {@code data} with a {@code ComponentSampleModel}
       
   466      * {@code csm} as
       
   467      * <pre>
       
   468      *        data.getElem(csm.getOffset(x, y));
       
   469      * </pre>
       
   470      * @param x the X location of the pixel
       
   471      * @param y the Y location of the pixel
       
   472      * @return the offset for the first band of the specified pixel.
       
   473      */
       
   474     public int getOffset(int x, int y) {
       
   475         int offset = y*scanlineStride + x*pixelStride + bandOffsets[0];
       
   476         return offset;
       
   477     }
       
   478 
       
   479     /** Gets the offset for band b of pixel (x,y).
       
   480      *  A sample of band {@code b} can be retrieved from a
       
   481      *  {@code DataBuffer data}
       
   482      *  with a {@code ComponentSampleModel csm} as
       
   483      * <pre>
       
   484      *       data.getElem(csm.getOffset(x, y, b));
       
   485      * </pre>
       
   486      * @param x the X location of the specified pixel
       
   487      * @param y the Y location of the specified pixel
       
   488      * @param b the specified band
       
   489      * @return the offset for the specified band of the specified pixel.
       
   490      */
       
   491     public int getOffset(int x, int y, int b) {
       
   492         int offset = y*scanlineStride + x*pixelStride + bandOffsets[b];
       
   493         return offset;
       
   494     }
       
   495 
       
   496     /** Returns the number of bits per sample for all bands.
       
   497      *  @return an array containing the number of bits per sample
       
   498      *          for all bands, where each element in the array
       
   499      *          represents a band.
       
   500      */
       
   501     public final int[] getSampleSize() {
       
   502         int sampleSize[] = new int [numBands];
       
   503         int sizeInBits = getSampleSize(0);
       
   504 
       
   505         for (int i=0; i<numBands; i++)
       
   506             sampleSize[i] = sizeInBits;
       
   507 
       
   508         return sampleSize;
       
   509     }
       
   510 
       
   511     /** Returns the number of bits per sample for the specified band.
       
   512      *  @param band the specified band
       
   513      *  @return the number of bits per sample for the specified band.
       
   514      */
       
   515     public final int getSampleSize(int band) {
       
   516         return DataBuffer.getDataTypeSize(dataType);
       
   517     }
       
   518 
       
   519     /** Returns the bank indices for all bands.
       
   520      *  @return the bank indices for all bands.
       
   521      */
       
   522     public final int [] getBankIndices() {
       
   523         return bankIndices.clone();
       
   524     }
       
   525 
       
   526     /** Returns the band offset for all bands.
       
   527      *  @return the band offsets for all bands.
       
   528      */
       
   529     public final int [] getBandOffsets() {
       
   530         return bandOffsets.clone();
       
   531     }
       
   532 
       
   533     /** Returns the scanline stride of this ComponentSampleModel.
       
   534      *  @return the scanline stride of this {@code ComponentSampleModel}.
       
   535      */
       
   536     public final int getScanlineStride() {
       
   537         return scanlineStride;
       
   538     }
       
   539 
       
   540     /** Returns the pixel stride of this ComponentSampleModel.
       
   541      *  @return the pixel stride of this {@code ComponentSampleModel}.
       
   542      */
       
   543     public final int getPixelStride() {
       
   544         return pixelStride;
       
   545     }
       
   546 
       
   547     /**
       
   548      * Returns the number of data elements needed to transfer a pixel
       
   549      * with the
       
   550      * {@link #getDataElements(int, int, Object, DataBuffer) } and
       
   551      * {@link #setDataElements(int, int, Object, DataBuffer) }
       
   552      * methods.
       
   553      * For a {@code ComponentSampleModel}, this is identical to the
       
   554      * number of bands.
       
   555      * @return the number of data elements needed to transfer a pixel with
       
   556      *         the {@code getDataElements} and
       
   557      *         {@code setDataElements} methods.
       
   558      * @see java.awt.image.SampleModel#getNumDataElements
       
   559      * @see #getNumBands
       
   560      */
       
   561     public final int getNumDataElements() {
       
   562         return getNumBands();
       
   563     }
       
   564 
       
   565     /**
       
   566      * Returns data for a single pixel in a primitive array of type
       
   567      * {@code TransferType}.  For a {@code ComponentSampleModel},
       
   568      * this is the same as the data type, and samples are returned
       
   569      * one per array element.  Generally, {@code obj} should
       
   570      * be passed in as {@code null}, so that the {@code Object}
       
   571      * is created automatically and is the right primitive data type.
       
   572      * <p>
       
   573      * The following code illustrates transferring data for one pixel from
       
   574      * {@code DataBuffer db1}, whose storage layout is
       
   575      * described by {@code ComponentSampleModel csm1},
       
   576      * to {@code DataBuffer db2}, whose storage layout
       
   577      * is described by {@code ComponentSampleModel csm2}.
       
   578      * The transfer is usually more efficient than using
       
   579      * {@code getPixel} and {@code setPixel}.
       
   580      * <pre>
       
   581      *       ComponentSampleModel csm1, csm2;
       
   582      *       DataBufferInt db1, db2;
       
   583      *       csm2.setDataElements(x, y,
       
   584      *                            csm1.getDataElements(x, y, null, db1), db2);
       
   585      * </pre>
       
   586      *
       
   587      * Using {@code getDataElements} and {@code setDataElements}
       
   588      * to transfer between two {@code DataBuffer/SampleModel}
       
   589      * pairs is legitimate if the {@code SampleModel} objects have
       
   590      * the same number of bands, corresponding bands have the same number of
       
   591      * bits per sample, and the {@code TransferType}s are the same.
       
   592      * <p>
       
   593      * If {@code obj} is not {@code null}, it should be a
       
   594      * primitive array of type {@code TransferType}.
       
   595      * Otherwise, a {@code ClassCastException} is thrown.  An
       
   596      * {@code ArrayIndexOutOfBoundsException} might be thrown if the
       
   597      * coordinates are not in bounds, or if {@code obj} is not
       
   598      * {@code null} and is not large enough to hold
       
   599      * the pixel data.
       
   600      *
       
   601      * @param x         the X coordinate of the pixel location
       
   602      * @param y         the Y coordinate of the pixel location
       
   603      * @param obj       if non-{@code null}, a primitive array
       
   604      *                  in which to return the pixel data
       
   605      * @param data      the {@code DataBuffer} containing the image data
       
   606      * @return the data of the specified pixel
       
   607      * @see #setDataElements(int, int, Object, DataBuffer)
       
   608      *
       
   609      * @throws NullPointerException if data is null.
       
   610      * @throws ArrayIndexOutOfBoundsException if the coordinates are
       
   611      * not in bounds, or if obj is too small to hold the output.
       
   612      */
       
   613     public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
       
   614         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
   615             throw new ArrayIndexOutOfBoundsException
       
   616                 ("Coordinate out of bounds!");
       
   617         }
       
   618 
       
   619         int type = getTransferType();
       
   620         int numDataElems = getNumDataElements();
       
   621         int pixelOffset = y*scanlineStride + x*pixelStride;
       
   622 
       
   623         switch(type) {
       
   624 
       
   625         case DataBuffer.TYPE_BYTE:
       
   626 
       
   627             byte[] bdata;
       
   628 
       
   629             if (obj == null)
       
   630                 bdata = new byte[numDataElems];
       
   631             else
       
   632                 bdata = (byte[])obj;
       
   633 
       
   634             for (int i=0; i<numDataElems; i++) {
       
   635                 bdata[i] = (byte)data.getElem(bankIndices[i],
       
   636                                               pixelOffset + bandOffsets[i]);
       
   637             }
       
   638 
       
   639             obj = (Object)bdata;
       
   640             break;
       
   641 
       
   642         case DataBuffer.TYPE_USHORT:
       
   643         case DataBuffer.TYPE_SHORT:
       
   644 
       
   645             short[] sdata;
       
   646 
       
   647             if (obj == null)
       
   648                 sdata = new short[numDataElems];
       
   649             else
       
   650                 sdata = (short[])obj;
       
   651 
       
   652             for (int i=0; i<numDataElems; i++) {
       
   653                 sdata[i] = (short)data.getElem(bankIndices[i],
       
   654                                                pixelOffset + bandOffsets[i]);
       
   655             }
       
   656 
       
   657             obj = (Object)sdata;
       
   658             break;
       
   659 
       
   660         case DataBuffer.TYPE_INT:
       
   661 
       
   662             int[] idata;
       
   663 
       
   664             if (obj == null)
       
   665                 idata = new int[numDataElems];
       
   666             else
       
   667                 idata = (int[])obj;
       
   668 
       
   669             for (int i=0; i<numDataElems; i++) {
       
   670                 idata[i] = data.getElem(bankIndices[i],
       
   671                                         pixelOffset + bandOffsets[i]);
       
   672             }
       
   673 
       
   674             obj = (Object)idata;
       
   675             break;
       
   676 
       
   677         case DataBuffer.TYPE_FLOAT:
       
   678 
       
   679             float[] fdata;
       
   680 
       
   681             if (obj == null)
       
   682                 fdata = new float[numDataElems];
       
   683             else
       
   684                 fdata = (float[])obj;
       
   685 
       
   686             for (int i=0; i<numDataElems; i++) {
       
   687                 fdata[i] = data.getElemFloat(bankIndices[i],
       
   688                                              pixelOffset + bandOffsets[i]);
       
   689             }
       
   690 
       
   691             obj = (Object)fdata;
       
   692             break;
       
   693 
       
   694         case DataBuffer.TYPE_DOUBLE:
       
   695 
       
   696             double[] ddata;
       
   697 
       
   698             if (obj == null)
       
   699                 ddata = new double[numDataElems];
       
   700             else
       
   701                 ddata = (double[])obj;
       
   702 
       
   703             for (int i=0; i<numDataElems; i++) {
       
   704                 ddata[i] = data.getElemDouble(bankIndices[i],
       
   705                                               pixelOffset + bandOffsets[i]);
       
   706             }
       
   707 
       
   708             obj = (Object)ddata;
       
   709             break;
       
   710         }
       
   711 
       
   712         return obj;
       
   713     }
       
   714 
       
   715     /**
       
   716      * Returns all samples for the specified pixel in an int array,
       
   717      * one sample per array element.
       
   718      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
   719      * the coordinates are not in bounds.
       
   720      * @param x         the X coordinate of the pixel location
       
   721      * @param y         the Y coordinate of the pixel location
       
   722      * @param iArray    If non-null, returns the samples in this array
       
   723      * @param data      The DataBuffer containing the image data
       
   724      * @return the samples of the specified pixel.
       
   725      * @see #setPixel(int, int, int[], DataBuffer)
       
   726      *
       
   727      * @throws NullPointerException if data is null.
       
   728      * @throws ArrayIndexOutOfBoundsException if the coordinates are
       
   729      * not in bounds, or if iArray is too small to hold the output.
       
   730      */
       
   731     public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
       
   732         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
   733             throw new ArrayIndexOutOfBoundsException
       
   734                 ("Coordinate out of bounds!");
       
   735         }
       
   736         int pixels[];
       
   737         if (iArray != null) {
       
   738            pixels = iArray;
       
   739         } else {
       
   740            pixels = new int [numBands];
       
   741         }
       
   742         int pixelOffset = y*scanlineStride + x*pixelStride;
       
   743         for (int i=0; i<numBands; i++) {
       
   744             pixels[i] = data.getElem(bankIndices[i],
       
   745                                      pixelOffset + bandOffsets[i]);
       
   746         }
       
   747         return pixels;
       
   748     }
       
   749 
       
   750     /**
       
   751      * Returns all samples for the specified rectangle of pixels in
       
   752      * an int array, one sample per array element.
       
   753      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
   754      * the coordinates are not in bounds.
       
   755      * @param x         The X coordinate of the upper left pixel location
       
   756      * @param y         The Y coordinate of the upper left pixel location
       
   757      * @param w         The width of the pixel rectangle
       
   758      * @param h         The height of the pixel rectangle
       
   759      * @param iArray    If non-null, returns the samples in this array
       
   760      * @param data      The DataBuffer containing the image data
       
   761      * @return the samples of the pixels within the specified region.
       
   762      * @see #setPixels(int, int, int, int, int[], DataBuffer)
       
   763      */
       
   764     public int[] getPixels(int x, int y, int w, int h,
       
   765                            int iArray[], DataBuffer data) {
       
   766         int x1 = x + w;
       
   767         int y1 = y + h;
       
   768 
       
   769         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
       
   770             y < 0 || y >= height || y > height || y1 < 0 || y1 >  height)
       
   771         {
       
   772             throw new ArrayIndexOutOfBoundsException
       
   773                 ("Coordinate out of bounds!");
       
   774         }
       
   775         int pixels[];
       
   776         if (iArray != null) {
       
   777            pixels = iArray;
       
   778         } else {
       
   779            pixels = new int [w*h*numBands];
       
   780         }
       
   781         int lineOffset = y*scanlineStride + x*pixelStride;
       
   782         int srcOffset = 0;
       
   783 
       
   784         for (int i = 0; i < h; i++) {
       
   785            int pixelOffset = lineOffset;
       
   786            for (int j = 0; j < w; j++) {
       
   787               for (int k=0; k < numBands; k++) {
       
   788                  pixels[srcOffset++] =
       
   789                     data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]);
       
   790               }
       
   791               pixelOffset += pixelStride;
       
   792            }
       
   793            lineOffset += scanlineStride;
       
   794         }
       
   795         return pixels;
       
   796     }
       
   797 
       
   798     /**
       
   799      * Returns as int the sample in a specified band for the pixel
       
   800      * located at (x,y).
       
   801      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
   802      * the coordinates are not in bounds.
       
   803      * @param x         the X coordinate of the pixel location
       
   804      * @param y         the Y coordinate of the pixel location
       
   805      * @param b         the band to return
       
   806      * @param data      the {@code DataBuffer} containing the image data
       
   807      * @return the sample in a specified band for the specified pixel
       
   808      * @see #setSample(int, int, int, int, DataBuffer)
       
   809      */
       
   810     public int getSample(int x, int y, int b, DataBuffer data) {
       
   811         // Bounds check for 'b' will be performed automatically
       
   812         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
   813             throw new ArrayIndexOutOfBoundsException
       
   814                 ("Coordinate out of bounds!");
       
   815         }
       
   816         int sample = data.getElem(bankIndices[b],
       
   817                                   y*scanlineStride + x*pixelStride +
       
   818                                   bandOffsets[b]);
       
   819         return sample;
       
   820     }
       
   821 
       
   822     /**
       
   823      * Returns the sample in a specified band
       
   824      * for the pixel located at (x,y) as a float.
       
   825      * An {@code ArrayIndexOutOfBoundsException} might be
       
   826      * thrown if the coordinates are not in bounds.
       
   827      * @param x         The X coordinate of the pixel location
       
   828      * @param y         The Y coordinate of the pixel location
       
   829      * @param b         The band to return
       
   830      * @param data      The DataBuffer containing the image data
       
   831      * @return a float value representing the sample in the specified
       
   832      * band for the specified pixel.
       
   833      */
       
   834     public float getSampleFloat(int x, int y, int b, DataBuffer data) {
       
   835         // Bounds check for 'b' will be performed automatically
       
   836         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
   837             throw new ArrayIndexOutOfBoundsException
       
   838                 ("Coordinate out of bounds!");
       
   839         }
       
   840 
       
   841         float sample = data.getElemFloat(bankIndices[b],
       
   842                                          y*scanlineStride + x*pixelStride +
       
   843                                          bandOffsets[b]);
       
   844         return sample;
       
   845     }
       
   846 
       
   847     /**
       
   848      * Returns the sample in a specified band
       
   849      * for a pixel located at (x,y) as a double.
       
   850      * An {@code ArrayIndexOutOfBoundsException} might be
       
   851      * thrown if the coordinates are not in bounds.
       
   852      * @param x         The X coordinate of the pixel location
       
   853      * @param y         The Y coordinate of the pixel location
       
   854      * @param b         The band to return
       
   855      * @param data      The DataBuffer containing the image data
       
   856      * @return a double value representing the sample in the specified
       
   857      * band for the specified pixel.
       
   858      */
       
   859     public double getSampleDouble(int x, int y, int b, DataBuffer data) {
       
   860         // Bounds check for 'b' will be performed automatically
       
   861         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
   862             throw new ArrayIndexOutOfBoundsException
       
   863                 ("Coordinate out of bounds!");
       
   864         }
       
   865 
       
   866         double sample = data.getElemDouble(bankIndices[b],
       
   867                                            y*scanlineStride + x*pixelStride +
       
   868                                            bandOffsets[b]);
       
   869         return sample;
       
   870     }
       
   871 
       
   872     /**
       
   873      * Returns the samples in a specified band for the specified rectangle
       
   874      * of pixels in an int array, one sample per data array element.
       
   875      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
   876      * the coordinates are not in bounds.
       
   877      * @param x         The X coordinate of the upper left pixel location
       
   878      * @param y         The Y coordinate of the upper left pixel location
       
   879      * @param w         the width of the pixel rectangle
       
   880      * @param h         the height of the pixel rectangle
       
   881      * @param b         the band to return
       
   882      * @param iArray    if non-{@code null}, returns the samples
       
   883      *                  in this array
       
   884      * @param data      the {@code DataBuffer} containing the image data
       
   885      * @return the samples in the specified band of the specified pixel
       
   886      * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
       
   887      */
       
   888     public int[] getSamples(int x, int y, int w, int h, int b,
       
   889                             int iArray[], DataBuffer data) {
       
   890         // Bounds check for 'b' will be performed automatically
       
   891         if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
       
   892             throw new ArrayIndexOutOfBoundsException
       
   893                 ("Coordinate out of bounds!");
       
   894         }
       
   895         int samples[];
       
   896         if (iArray != null) {
       
   897            samples = iArray;
       
   898         } else {
       
   899            samples = new int [w*h];
       
   900         }
       
   901         int lineOffset = y*scanlineStride + x*pixelStride +  bandOffsets[b];
       
   902         int srcOffset = 0;
       
   903 
       
   904         for (int i = 0; i < h; i++) {
       
   905            int sampleOffset = lineOffset;
       
   906            for (int j = 0; j < w; j++) {
       
   907               samples[srcOffset++] = data.getElem(bankIndices[b],
       
   908                                                   sampleOffset);
       
   909               sampleOffset += pixelStride;
       
   910            }
       
   911            lineOffset += scanlineStride;
       
   912         }
       
   913         return samples;
       
   914     }
       
   915 
       
   916     /**
       
   917      * Sets the data for a single pixel in the specified
       
   918      * {@code DataBuffer} from a primitive array of type
       
   919      * {@code TransferType}.  For a {@code ComponentSampleModel},
       
   920      * this is the same as the data type, and samples are transferred
       
   921      * one per array element.
       
   922      * <p>
       
   923      * The following code illustrates transferring data for one pixel from
       
   924      * {@code DataBuffer db1}, whose storage layout is
       
   925      * described by {@code ComponentSampleModel csm1},
       
   926      * to {@code DataBuffer db2}, whose storage layout
       
   927      * is described by {@code ComponentSampleModel csm2}.
       
   928      * The transfer is usually more efficient than using
       
   929      * {@code getPixel} and {@code setPixel}.
       
   930      * <pre>
       
   931      *       ComponentSampleModel csm1, csm2;
       
   932      *       DataBufferInt db1, db2;
       
   933      *       csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
       
   934      *                            db2);
       
   935      * </pre>
       
   936      * Using {@code getDataElements} and {@code setDataElements}
       
   937      * to transfer between two {@code DataBuffer/SampleModel} pairs
       
   938      * is legitimate if the {@code SampleModel} objects have
       
   939      * the same number of bands, corresponding bands have the same number of
       
   940      * bits per sample, and the {@code TransferType}s are the same.
       
   941      * <p>
       
   942      * A {@code ClassCastException} is thrown if {@code obj} is not
       
   943      * a primitive array of type {@code TransferType}.
       
   944      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
   945      * the coordinates are not in bounds, or if {@code obj} is not large
       
   946      * enough to hold the pixel data.
       
   947      * @param x         the X coordinate of the pixel location
       
   948      * @param y         the Y coordinate of the pixel location
       
   949      * @param obj       a primitive array containing pixel data
       
   950      * @param data      the DataBuffer containing the image data
       
   951      * @see #getDataElements(int, int, Object, DataBuffer)
       
   952      */
       
   953     public void setDataElements(int x, int y, Object obj, DataBuffer data) {
       
   954         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
   955             throw new ArrayIndexOutOfBoundsException
       
   956                 ("Coordinate out of bounds!");
       
   957         }
       
   958 
       
   959         int type = getTransferType();
       
   960         int numDataElems = getNumDataElements();
       
   961         int pixelOffset = y*scanlineStride + x*pixelStride;
       
   962 
       
   963         switch(type) {
       
   964 
       
   965         case DataBuffer.TYPE_BYTE:
       
   966 
       
   967             byte[] barray = (byte[])obj;
       
   968 
       
   969             for (int i=0; i<numDataElems; i++) {
       
   970                 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
       
   971                            ((int)barray[i])&0xff);
       
   972             }
       
   973             break;
       
   974 
       
   975         case DataBuffer.TYPE_USHORT:
       
   976         case DataBuffer.TYPE_SHORT:
       
   977 
       
   978             short[] sarray = (short[])obj;
       
   979 
       
   980             for (int i=0; i<numDataElems; i++) {
       
   981                 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
       
   982                            ((int)sarray[i])&0xffff);
       
   983             }
       
   984             break;
       
   985 
       
   986         case DataBuffer.TYPE_INT:
       
   987 
       
   988             int[] iarray = (int[])obj;
       
   989 
       
   990             for (int i=0; i<numDataElems; i++) {
       
   991                 data.setElem(bankIndices[i],
       
   992                              pixelOffset + bandOffsets[i], iarray[i]);
       
   993             }
       
   994             break;
       
   995 
       
   996         case DataBuffer.TYPE_FLOAT:
       
   997 
       
   998             float[] farray = (float[])obj;
       
   999 
       
  1000             for (int i=0; i<numDataElems; i++) {
       
  1001                 data.setElemFloat(bankIndices[i],
       
  1002                              pixelOffset + bandOffsets[i], farray[i]);
       
  1003             }
       
  1004             break;
       
  1005 
       
  1006         case DataBuffer.TYPE_DOUBLE:
       
  1007 
       
  1008             double[] darray = (double[])obj;
       
  1009 
       
  1010             for (int i=0; i<numDataElems; i++) {
       
  1011                 data.setElemDouble(bankIndices[i],
       
  1012                              pixelOffset + bandOffsets[i], darray[i]);
       
  1013             }
       
  1014             break;
       
  1015 
       
  1016         }
       
  1017     }
       
  1018 
       
  1019     /**
       
  1020      * Sets a pixel in the {@code DataBuffer} using an int array of
       
  1021      * samples for input.  An {@code ArrayIndexOutOfBoundsException}
       
  1022      * might be thrown if the coordinates are
       
  1023      * not in bounds.
       
  1024      * @param x         The X coordinate of the pixel location
       
  1025      * @param y         The Y coordinate of the pixel location
       
  1026      * @param iArray    The input samples in an int array
       
  1027      * @param data      The DataBuffer containing the image data
       
  1028      * @see #getPixel(int, int, int[], DataBuffer)
       
  1029      */
       
  1030     public void setPixel(int x, int y, int iArray[], DataBuffer data) {
       
  1031         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
  1032             throw new ArrayIndexOutOfBoundsException
       
  1033                 ("Coordinate out of bounds!");
       
  1034         }
       
  1035        int pixelOffset = y*scanlineStride + x*pixelStride;
       
  1036        for (int i=0; i<numBands; i++) {
       
  1037            data.setElem(bankIndices[i],
       
  1038                         pixelOffset + bandOffsets[i],iArray[i]);
       
  1039        }
       
  1040     }
       
  1041 
       
  1042     /**
       
  1043      * Sets all samples for a rectangle of pixels from an int array containing
       
  1044      * one sample per array element.
       
  1045      * An {@code ArrayIndexOutOfBoundsException} might be thrown if the
       
  1046      * coordinates are not in bounds.
       
  1047      * @param x         The X coordinate of the upper left pixel location
       
  1048      * @param y         The Y coordinate of the upper left pixel location
       
  1049      * @param w         The width of the pixel rectangle
       
  1050      * @param h         The height of the pixel rectangle
       
  1051      * @param iArray    The input samples in an int array
       
  1052      * @param data      The DataBuffer containing the image data
       
  1053      * @see #getPixels(int, int, int, int, int[], DataBuffer)
       
  1054      */
       
  1055     public void setPixels(int x, int y, int w, int h,
       
  1056                           int iArray[], DataBuffer data) {
       
  1057         int x1 = x + w;
       
  1058         int y1 = y + h;
       
  1059 
       
  1060         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
       
  1061             y < 0 || y >= height || h > height || y1 < 0 || y1 >  height)
       
  1062         {
       
  1063             throw new ArrayIndexOutOfBoundsException
       
  1064                 ("Coordinate out of bounds!");
       
  1065         }
       
  1066 
       
  1067         int lineOffset = y*scanlineStride + x*pixelStride;
       
  1068         int srcOffset = 0;
       
  1069 
       
  1070         for (int i = 0; i < h; i++) {
       
  1071            int pixelOffset = lineOffset;
       
  1072            for (int j = 0; j < w; j++) {
       
  1073               for (int k=0; k < numBands; k++) {
       
  1074                  data.setElem(bankIndices[k], pixelOffset + bandOffsets[k],
       
  1075                               iArray[srcOffset++]);
       
  1076               }
       
  1077               pixelOffset += pixelStride;
       
  1078            }
       
  1079            lineOffset += scanlineStride;
       
  1080         }
       
  1081     }
       
  1082 
       
  1083     /**
       
  1084      * Sets a sample in the specified band for the pixel located at (x,y)
       
  1085      * in the {@code DataBuffer} using an int for input.
       
  1086      * An {@code ArrayIndexOutOfBoundsException} might be thrown if the
       
  1087      * coordinates are not in bounds.
       
  1088      * @param x         The X coordinate of the pixel location
       
  1089      * @param y         The Y coordinate of the pixel location
       
  1090      * @param b         the band to set
       
  1091      * @param s         the input sample as an int
       
  1092      * @param data      the DataBuffer containing the image data
       
  1093      * @see #getSample(int, int, int, DataBuffer)
       
  1094      */
       
  1095     public void setSample(int x, int y, int b, int s,
       
  1096                           DataBuffer data) {
       
  1097         // Bounds check for 'b' will be performed automatically
       
  1098         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
  1099             throw new ArrayIndexOutOfBoundsException
       
  1100                 ("Coordinate out of bounds!");
       
  1101         }
       
  1102         data.setElem(bankIndices[b],
       
  1103                      y*scanlineStride + x*pixelStride + bandOffsets[b], s);
       
  1104     }
       
  1105 
       
  1106     /**
       
  1107      * Sets a sample in the specified band for the pixel located at (x,y)
       
  1108      * in the {@code DataBuffer} using a float for input.
       
  1109      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
  1110      * the coordinates are not in bounds.
       
  1111      * @param x         The X coordinate of the pixel location
       
  1112      * @param y         The Y coordinate of the pixel location
       
  1113      * @param b         The band to set
       
  1114      * @param s         The input sample as a float
       
  1115      * @param data      The DataBuffer containing the image data
       
  1116      * @see #getSample(int, int, int, DataBuffer)
       
  1117      */
       
  1118     public void setSample(int x, int y, int b,
       
  1119                           float s ,
       
  1120                           DataBuffer data) {
       
  1121         // Bounds check for 'b' will be performed automatically
       
  1122         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
  1123             throw new ArrayIndexOutOfBoundsException
       
  1124                 ("Coordinate out of bounds!");
       
  1125         }
       
  1126         data.setElemFloat(bankIndices[b],
       
  1127                           y*scanlineStride + x*pixelStride + bandOffsets[b],
       
  1128                           s);
       
  1129     }
       
  1130 
       
  1131     /**
       
  1132      * Sets a sample in the specified band for the pixel located at (x,y)
       
  1133      * in the {@code DataBuffer} using a double for input.
       
  1134      * An {@code ArrayIndexOutOfBoundsException} might be thrown if
       
  1135      * the coordinates are not in bounds.
       
  1136      * @param x         The X coordinate of the pixel location
       
  1137      * @param y         The Y coordinate of the pixel location
       
  1138      * @param b         The band to set
       
  1139      * @param s         The input sample as a double
       
  1140      * @param data      The DataBuffer containing the image data
       
  1141      * @see #getSample(int, int, int, DataBuffer)
       
  1142      */
       
  1143     public void setSample(int x, int y, int b,
       
  1144                           double s,
       
  1145                           DataBuffer data) {
       
  1146         // Bounds check for 'b' will be performed automatically
       
  1147         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
       
  1148             throw new ArrayIndexOutOfBoundsException
       
  1149                 ("Coordinate out of bounds!");
       
  1150         }
       
  1151         data.setElemDouble(bankIndices[b],
       
  1152                           y*scanlineStride + x*pixelStride + bandOffsets[b],
       
  1153                           s);
       
  1154     }
       
  1155 
       
  1156     /**
       
  1157      * Sets the samples in the specified band for the specified rectangle
       
  1158      * of pixels from an int array containing one sample per data array element.
       
  1159      * An {@code ArrayIndexOutOfBoundsException} might be thrown if the
       
  1160      * coordinates are not in bounds.
       
  1161      * @param x         The X coordinate of the upper left pixel location
       
  1162      * @param y         The Y coordinate of the upper left pixel location
       
  1163      * @param w         The width of the pixel rectangle
       
  1164      * @param h         The height of the pixel rectangle
       
  1165      * @param b         The band to set
       
  1166      * @param iArray    The input samples in an int array
       
  1167      * @param data      The DataBuffer containing the image data
       
  1168      * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
       
  1169      */
       
  1170     public void setSamples(int x, int y, int w, int h, int b,
       
  1171                            int iArray[], DataBuffer data) {
       
  1172         // Bounds check for 'b' will be performed automatically
       
  1173         if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
       
  1174             throw new ArrayIndexOutOfBoundsException
       
  1175                 ("Coordinate out of bounds!");
       
  1176         }
       
  1177         int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
       
  1178         int srcOffset = 0;
       
  1179 
       
  1180         for (int i = 0; i < h; i++) {
       
  1181            int sampleOffset = lineOffset;
       
  1182            for (int j = 0; j < w; j++) {
       
  1183               data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]);
       
  1184               sampleOffset += pixelStride;
       
  1185            }
       
  1186            lineOffset += scanlineStride;
       
  1187         }
       
  1188     }
       
  1189 
       
  1190     public boolean equals(Object o) {
       
  1191         if ((o == null) || !(o instanceof ComponentSampleModel)) {
       
  1192             return false;
       
  1193         }
       
  1194 
       
  1195         ComponentSampleModel that = (ComponentSampleModel)o;
       
  1196         return this.width == that.width &&
       
  1197             this.height == that.height &&
       
  1198             this.numBands == that.numBands &&
       
  1199             this.dataType == that.dataType &&
       
  1200             Arrays.equals(this.bandOffsets, that.bandOffsets) &&
       
  1201             Arrays.equals(this.bankIndices, that.bankIndices) &&
       
  1202             this.numBands == that.numBands &&
       
  1203             this.numBanks == that.numBanks &&
       
  1204             this.scanlineStride == that.scanlineStride &&
       
  1205             this.pixelStride == that.pixelStride;
       
  1206     }
       
  1207 
       
  1208     // If we implement equals() we must also implement hashCode
       
  1209     public int hashCode() {
       
  1210         int hash = 0;
       
  1211         hash = width;
       
  1212         hash <<= 8;
       
  1213         hash ^= height;
       
  1214         hash <<= 8;
       
  1215         hash ^= numBands;
       
  1216         hash <<= 8;
       
  1217         hash ^= dataType;
       
  1218         hash <<= 8;
       
  1219         for (int i = 0; i < bandOffsets.length; i++) {
       
  1220             hash ^= bandOffsets[i];
       
  1221             hash <<= 8;
       
  1222         }
       
  1223         for (int i = 0; i < bankIndices.length; i++) {
       
  1224             hash ^= bankIndices[i];
       
  1225             hash <<= 8;
       
  1226         }
       
  1227         hash ^= numBands;
       
  1228         hash <<= 8;
       
  1229         hash ^= numBanks;
       
  1230         hash <<= 8;
       
  1231         hash ^= scanlineStride;
       
  1232         hash <<= 8;
       
  1233         hash ^= pixelStride;
       
  1234         return hash;
       
  1235     }
       
  1236 }