1 /*
   2  * Copyright (c) 1997, 2018, 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 /**
  39  *  This abstract class defines an interface for extracting samples of pixels
  40  *  in an image.  All image data is expressed as a collection of pixels.
  41  *  Each pixel consists of a number of samples. A sample is a datum
  42  *  for one band of an image and a band consists of all samples of a
  43  *  particular type in an image.  For example, a pixel might contain
  44  *  three samples representing its red, green and blue components.
  45  *  There are three bands in the image containing this pixel.  One band
  46  *  consists of all the red samples from all pixels in the
  47  *  image.  The second band consists of all the green samples and
  48  *  the remaining band consists of all of the blue samples.  The pixel
  49  *  can be stored in various formats.  For example, all samples from
  50  *  a particular band can be stored contiguously or all samples from a
  51  *  single pixel can be stored contiguously.
  52  *  <p>
  53  *  Subclasses of SampleModel specify the types of samples they can
  54  *  represent (e.g. unsigned 8-bit byte, signed 16-bit short, etc.)
  55  *  and may specify how the samples are organized in memory.
  56  *  In the Java 2D(tm) API, built-in image processing operators may
  57  *  not operate on all possible sample types, but generally will work
  58  *  for unsigned integral samples of 16 bits or less.  Some operators
  59  *  support a wider variety of sample types.
  60  *  <p>
  61  *  A collection of pixels is represented as a Raster, which consists of
  62  *  a DataBuffer and a SampleModel.  The SampleModel allows access to
  63  *  samples in the DataBuffer and may provide low-level information that
  64  *  a programmer can use to directly manipulate samples and pixels in the
  65  *  DataBuffer.
  66  *  <p>
  67  *  This class is generally a fall back method for dealing with
  68  *  images.  More efficient code will cast the SampleModel to the
  69  *  appropriate subclass and extract the information needed to directly
  70  *  manipulate pixels in the DataBuffer.
  71  *
  72  *  @see java.awt.image.DataBuffer
  73  *  @see java.awt.image.Raster
  74  *  @see java.awt.image.ComponentSampleModel
  75  *  @see java.awt.image.PixelInterleavedSampleModel
  76  *  @see java.awt.image.BandedSampleModel
  77  *  @see java.awt.image.MultiPixelPackedSampleModel
  78  *  @see java.awt.image.SinglePixelPackedSampleModel
  79  */
  80 
  81 public abstract class SampleModel
  82 {
  83 
  84     /** Width in pixels of the region of image data that this SampleModel
  85      *  describes.
  86      */
  87     protected int width;
  88 
  89     /** Height in pixels of the region of image data that this SampleModel
  90      *  describes.
  91      */
  92     protected int height;
  93 
  94     /** Number of bands of the image data that this SampleModel describes. */
  95     protected int numBands;
  96 
  97     /** Data type of the DataBuffer storing the pixel data.
  98      *  @see java.awt.image.DataBuffer
  99      */
 100     protected int dataType;
 101 
 102     private static native void initIDs();
 103     static {
 104         ColorModel.loadLibraries();
 105         initIDs();
 106     }
 107 
 108     /**
 109      * Constructs a SampleModel with the specified parameters.
 110      * @param dataType  The data type of the DataBuffer storing the pixel data.
 111      * @param w         The width (in pixels) of the region of image data.
 112      * @param h         The height (in pixels) of the region of image data.
 113      * @param numBands  The number of bands of the image data.
 114      * @throws IllegalArgumentException if {@code w} or {@code h}
 115      *         is not greater than 0
 116      * @throws IllegalArgumentException if the product of {@code w}
 117      *         and {@code h} is greater than
 118      *         {@code Integer.MAX_VALUE}
 119      * @throws IllegalArgumentException if {@code dataType} is not
 120      *         one of the supported data types
 121      */
 122     public SampleModel(int dataType, int w, int h, int numBands)
 123     {
 124         long size = (long)w * h;
 125         if (w <= 0 || h <= 0) {
 126             throw new IllegalArgumentException("Width ("+w+") and height ("+
 127                                                h+") must be > 0");
 128         }
 129         if (size > Integer.MAX_VALUE) {
 130             throw new IllegalArgumentException("Dimensions (width="+w+
 131                                                " height="+h+") are too large");
 132         }
 133 
 134         if (dataType < DataBuffer.TYPE_BYTE ||
 135             (dataType > DataBuffer.TYPE_DOUBLE &&
 136              dataType != DataBuffer.TYPE_UNDEFINED))
 137         {
 138             throw new IllegalArgumentException("Unsupported dataType: "+
 139                                                dataType);
 140         }
 141 
 142         if (numBands <= 0) {
 143             throw new IllegalArgumentException("Number of bands must be > 0");
 144         }
 145 
 146         this.dataType = dataType;
 147         this.width = w;
 148         this.height = h;
 149         this.numBands = numBands;
 150     }
 151 
 152     /** Returns the width in pixels.
 153      *  @return the width in pixels of the region of image data
 154      *          that this {@code SampleModel} describes.
 155      */
 156     public final int getWidth() {
 157          return width;
 158     }
 159 
 160     /** Returns the height in pixels.
 161      *  @return the height in pixels of the region of image data
 162      *          that this {@code SampleModel} describes.
 163      */
 164     public final int getHeight() {
 165          return height;
 166     }
 167 
 168     /** Returns the total number of bands of image data.
 169      *  @return the number of bands of image data that this
 170      *          {@code SampleModel} describes.
 171      */
 172     public final int getNumBands() {
 173          return numBands;
 174     }
 175 
 176     /** Returns the number of data elements needed to transfer a pixel
 177      *  via the getDataElements and setDataElements methods.  When pixels
 178      *  are transferred via these methods, they may be transferred in a
 179      *  packed or unpacked format, depending on the implementation of the
 180      *  SampleModel.  Using these methods, pixels are transferred as an
 181      *  array of getNumDataElements() elements of a primitive type given
 182      *  by getTransferType().  The TransferType may or may not be the same
 183      *  as the storage DataType.
 184      *  @return the number of data elements.
 185      *  @see #getDataElements(int, int, Object, DataBuffer)
 186      *  @see #getDataElements(int, int, int, int, Object, DataBuffer)
 187      *  @see #setDataElements(int, int, Object, DataBuffer)
 188      *  @see #setDataElements(int, int, int, int, Object, DataBuffer)
 189      *  @see #getTransferType
 190      */
 191     public abstract int getNumDataElements();
 192 
 193     /** Returns the data type of the DataBuffer storing the pixel data.
 194      *  @return the data type.
 195      */
 196     public final int getDataType() {
 197         return dataType;
 198     }
 199 
 200     /** Returns the TransferType used to transfer pixels via the
 201      *  getDataElements and setDataElements methods.  When pixels
 202      *  are transferred via these methods, they may be transferred in a
 203      *  packed or unpacked format, depending on the implementation of the
 204      *  SampleModel.  Using these methods, pixels are transferred as an
 205      *  array of getNumDataElements() elements of a primitive type given
 206      *  by getTransferType().  The TransferType may or may not be the same
 207      *  as the storage DataType.  The TransferType will be one of the types
 208      *  defined in DataBuffer.
 209      *  @return the transfer type.
 210      *  @see #getDataElements(int, int, Object, DataBuffer)
 211      *  @see #getDataElements(int, int, int, int, Object, DataBuffer)
 212      *  @see #setDataElements(int, int, Object, DataBuffer)
 213      *  @see #setDataElements(int, int, int, int, Object, DataBuffer)
 214      *  @see #getNumDataElements
 215      *  @see java.awt.image.DataBuffer
 216      */
 217     public int getTransferType() {
 218         return dataType;
 219     }
 220 
 221     /**
 222      * Returns the samples for a specified pixel in an int array,
 223      * one sample per array element.
 224      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 225      * not in bounds.
 226      * @param x         The X coordinate of the pixel location
 227      * @param y         The Y coordinate of the pixel location
 228      * @param iArray    If non-null, returns the samples in this array
 229      * @param data      The DataBuffer containing the image data
 230      * @return the samples for the specified pixel.
 231      * @see #setPixel(int, int, int[], DataBuffer)
 232      *
 233      * @throws NullPointerException if data is null.
 234      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 235      * not in bounds, or if iArray is too small to hold the output.
 236      */
 237     public int[] getPixel(int x, int y, int[] iArray, DataBuffer data) {
 238 
 239         int[] pixels;
 240 
 241         if (iArray != null)
 242             pixels = iArray;
 243         else
 244             pixels = new int[numBands];
 245 
 246         for (int i=0; i<numBands; i++) {
 247             pixels[i] = getSample(x, y, i, data);
 248         }
 249 
 250         return pixels;
 251     }
 252 
 253     /**
 254      * Returns data for a single pixel in a primitive array of type
 255      * TransferType.  For image data supported by the Java 2D API, this
 256      * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
 257      * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
 258      * or DataBuffer.TYPE_DOUBLE.  Data may be returned in a packed format,
 259      * thus increasing efficiency for data transfers. Generally, obj
 260      * should be passed in as null, so that the Object will be created
 261      * automatically and will be of the right primitive data type.
 262      * <p>
 263      * The following code illustrates transferring data for one pixel from
 264      * DataBuffer {@code db1}, whose storage layout is described by
 265      * SampleModel {@code sm1}, to DataBuffer {@code db2}, whose
 266      * storage layout is described by SampleModel {@code sm2}.
 267      * The transfer will generally be more efficient than using
 268      * getPixel/setPixel.
 269      * <pre>
 270      *       SampleModel sm1, sm2;
 271      *       DataBuffer db1, db2;
 272      *       sm2.setDataElements(x, y, sm1.getDataElements(x, y, null, db1), db2);
 273      * </pre>
 274      * Using getDataElements/setDataElements to transfer between two
 275      * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
 276      * the same number of bands, corresponding bands have the same number of
 277      * bits per sample, and the TransferTypes are the same.
 278      * <p>
 279      * If obj is non-null, it should be a primitive array of type TransferType.
 280      * Otherwise, a ClassCastException is thrown.  An
 281      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 282      * not in bounds, or if obj is non-null and is not large enough to hold
 283      * the pixel data.
 284      * @param x         The X coordinate of the pixel location.
 285      * @param y         The Y coordinate of the pixel location.
 286      * @param obj       If non-null, a primitive array in which to return
 287      *                  the pixel data.
 288      * @param data      The DataBuffer containing the image data.
 289      * @return the data elements for the specified pixel.
 290      * @see #getNumDataElements
 291      * @see #getTransferType
 292      * @see java.awt.image.DataBuffer
 293      * @see #setDataElements(int, int, Object, DataBuffer)
 294      *
 295      * @throws NullPointerException if data is null.
 296      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 297      * not in bounds, or if obj is too small to hold the output.
 298      */
 299     public abstract Object getDataElements(int x, int y,
 300                                            Object obj, DataBuffer data);
 301 
 302     /**
 303      * Returns the pixel data for the specified rectangle of pixels in a
 304      * primitive array of type TransferType.
 305      * For image data supported by the Java 2D API, this
 306      * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
 307      * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
 308      * or DataBuffer.TYPE_DOUBLE.  Data may be returned in a packed format,
 309      * thus increasing efficiency for data transfers. Generally, obj
 310      * should be passed in as null, so that the Object will be created
 311      * automatically and will be of the right primitive data type.
 312      * <p>
 313      * The following code illustrates transferring data for a rectangular
 314      * region of pixels from
 315      * DataBuffer {@code db1}, whose storage layout is described by
 316      * SampleModel {@code sm1}, to DataBuffer {@code db2}, whose
 317      * storage layout is described by SampleModel {@code sm2}.
 318      * The transfer will generally be more efficient than using
 319      * getPixels/setPixels.
 320      * <pre>
 321      *       SampleModel sm1, sm2;
 322      *       DataBuffer db1, db2;
 323      *       sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w,
 324      *                           h, null, db1), db2);
 325      * </pre>
 326      * Using getDataElements/setDataElements to transfer between two
 327      * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
 328      * the same number of bands, corresponding bands have the same number of
 329      * bits per sample, and the TransferTypes are the same.
 330      * <p>
 331      * If obj is non-null, it should be a primitive array of type TransferType.
 332      * Otherwise, a ClassCastException is thrown.  An
 333      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 334      * not in bounds, or if obj is non-null and is not large enough to hold
 335      * the pixel data.
 336      * @param x         The minimum X coordinate of the pixel rectangle.
 337      * @param y         The minimum Y coordinate of the pixel rectangle.
 338      * @param w         The width of the pixel rectangle.
 339      * @param h         The height of the pixel rectangle.
 340      * @param obj       If non-null, a primitive array in which to return
 341      *                  the pixel data.
 342      * @param data      The DataBuffer containing the image data.
 343      * @return the data elements for the specified region of pixels.
 344      * @see #getNumDataElements
 345      * @see #getTransferType
 346      * @see #setDataElements(int, int, int, int, Object, DataBuffer)
 347      * @see java.awt.image.DataBuffer
 348      *
 349      * @throws NullPointerException if data is null.
 350      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 351      * not in bounds, or if obj is too small to hold the output.
 352      */
 353     public Object getDataElements(int x, int y, int w, int h,
 354                                   Object obj, DataBuffer data) {
 355 
 356         int type = getTransferType();
 357         int numDataElems = getNumDataElements();
 358         int cnt = 0;
 359         Object o = null;
 360 
 361         int x1 = x + w;
 362         int y1 = y + h;
 363 
 364         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
 365             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
 366         {
 367             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
 368         }
 369 
 370         switch(type) {
 371 
 372         case DataBuffer.TYPE_BYTE:
 373 
 374             byte[] btemp;
 375             byte[] bdata;
 376 
 377             if (obj == null)
 378                 bdata = new byte[numDataElems*w*h];
 379             else
 380                 bdata = (byte[])obj;
 381 
 382             for (int i=y; i<y1; i++) {
 383                 for (int j=x; j<x1; j++) {
 384                     o = getDataElements(j, i, o, data);
 385                     btemp = (byte[])o;
 386                     for (int k=0; k<numDataElems; k++) {
 387                         bdata[cnt++] = btemp[k];
 388                     }
 389                 }
 390             }
 391             obj = (Object)bdata;
 392             break;
 393 
 394         case DataBuffer.TYPE_USHORT:
 395         case DataBuffer.TYPE_SHORT:
 396 
 397             short[] sdata;
 398             short[] stemp;
 399 
 400             if (obj == null)
 401                 sdata = new short[numDataElems*w*h];
 402             else
 403                 sdata = (short[])obj;
 404 
 405             for (int i=y; i<y1; i++) {
 406                 for (int j=x; j<x1; j++) {
 407                     o = getDataElements(j, i, o, data);
 408                     stemp = (short[])o;
 409                     for (int k=0; k<numDataElems; k++) {
 410                         sdata[cnt++] = stemp[k];
 411                     }
 412                 }
 413             }
 414 
 415             obj = (Object)sdata;
 416             break;
 417 
 418         case DataBuffer.TYPE_INT:
 419 
 420             int[] idata;
 421             int[] itemp;
 422 
 423             if (obj == null)
 424                 idata = new int[numDataElems*w*h];
 425             else
 426                 idata = (int[])obj;
 427 
 428             for (int i=y; i<y1; i++) {
 429                 for (int j=x; j<x1; j++) {
 430                     o = getDataElements(j, i, o, data);
 431                     itemp = (int[])o;
 432                     for (int k=0; k<numDataElems; k++) {
 433                         idata[cnt++] = itemp[k];
 434                     }
 435                 }
 436             }
 437 
 438             obj = (Object)idata;
 439             break;
 440 
 441         case DataBuffer.TYPE_FLOAT:
 442 
 443             float[] fdata;
 444             float[] ftemp;
 445 
 446             if (obj == null)
 447                 fdata = new float[numDataElems*w*h];
 448             else
 449                 fdata = (float[])obj;
 450 
 451             for (int i=y; i<y1; i++) {
 452                 for (int j=x; j<x1; j++) {
 453                     o = getDataElements(j, i, o, data);
 454                     ftemp = (float[])o;
 455                     for (int k=0; k<numDataElems; k++) {
 456                         fdata[cnt++] = ftemp[k];
 457                     }
 458                 }
 459             }
 460 
 461             obj = (Object)fdata;
 462             break;
 463 
 464         case DataBuffer.TYPE_DOUBLE:
 465 
 466             double[] ddata;
 467             double[] dtemp;
 468 
 469             if (obj == null)
 470                 ddata = new double[numDataElems*w*h];
 471             else
 472                 ddata = (double[])obj;
 473 
 474             for (int i=y; i<y1; i++) {
 475                 for (int j=x; j<x1; j++) {
 476                     o = getDataElements(j, i, o, data);
 477                     dtemp = (double[])o;
 478                     for (int k=0; k<numDataElems; k++) {
 479                         ddata[cnt++] = dtemp[k];
 480                     }
 481                 }
 482             }
 483 
 484             obj = (Object)ddata;
 485             break;
 486         }
 487 
 488         return obj;
 489     }
 490 
 491     /**
 492      * Sets the data for a single pixel in the specified DataBuffer from a
 493      * primitive array of type TransferType.  For image data supported by
 494      * the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
 495      * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
 496      * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.  Data in the array
 497      * may be in a packed format, thus increasing efficiency for data
 498      * transfers.
 499      * <p>
 500      * The following code illustrates transferring data for one pixel from
 501      * DataBuffer {@code db1}, whose storage layout is described by
 502      * SampleModel {@code sm1}, to DataBuffer {@code db2}, whose
 503      * storage layout is described by SampleModel {@code sm2}.
 504      * The transfer will generally be more efficient than using
 505      * getPixel/setPixel.
 506      * <pre>
 507      *       SampleModel sm1, sm2;
 508      *       DataBuffer db1, db2;
 509      *       sm2.setDataElements(x, y, sm1.getDataElements(x, y, null, db1),
 510      *                           db2);
 511      * </pre>
 512      * Using getDataElements/setDataElements to transfer between two
 513      * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
 514      * the same number of bands, corresponding bands have the same number of
 515      * bits per sample, and the TransferTypes are the same.
 516      * <p>
 517      * obj must be a primitive array of type TransferType.  Otherwise,
 518      * a ClassCastException is thrown.  An
 519      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 520      * not in bounds, or if obj is not large enough to hold the pixel data.
 521      * @param x         The X coordinate of the pixel location.
 522      * @param y         The Y coordinate of the pixel location.
 523      * @param obj       A primitive array containing pixel data.
 524      * @param data      The DataBuffer containing the image data.
 525      * @see #getNumDataElements
 526      * @see #getTransferType
 527      * @see #getDataElements(int, int, Object, DataBuffer)
 528      * @see java.awt.image.DataBuffer
 529      *
 530      * @throws NullPointerException if data is null.
 531      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 532      * not in bounds, or if obj is too small to hold the input.
 533      */
 534     public abstract void setDataElements(int x, int y,
 535                                          Object obj, DataBuffer data);
 536 
 537     /**
 538      * Sets the data for a rectangle of pixels in the specified DataBuffer
 539      * from a primitive array of type TransferType.  For image data supported
 540      * by the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
 541      * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
 542      * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE.  Data in the array
 543      * may be in a packed format, thus increasing efficiency for data
 544      * transfers.
 545      * <p>
 546      * The following code illustrates transferring data for a rectangular
 547      * region of pixels from
 548      * DataBuffer {@code db1}, whose storage layout is described by
 549      * SampleModel {@code sm1}, to DataBuffer {@code db2}, whose
 550      * storage layout is described by SampleModel {@code sm2}.
 551      * The transfer will generally be more efficient than using
 552      * getPixels/setPixels.
 553      * <pre>
 554      *       SampleModel sm1, sm2;
 555      *       DataBuffer db1, db2;
 556      *       sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h,
 557      *                           null, db1), db2);
 558      * </pre>
 559      * Using getDataElements/setDataElements to transfer between two
 560      * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
 561      * the same number of bands, corresponding bands have the same number of
 562      * bits per sample, and the TransferTypes are the same.
 563      * <p>
 564      * obj must be a primitive array of type TransferType.  Otherwise,
 565      * a ClassCastException is thrown.  An
 566      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 567      * not in bounds, or if obj is not large enough to hold the pixel data.
 568      * @param x         The minimum X coordinate of the pixel rectangle.
 569      * @param y         The minimum Y coordinate of the pixel rectangle.
 570      * @param w         The width of the pixel rectangle.
 571      * @param h         The height of the pixel rectangle.
 572      * @param obj       A primitive array containing pixel data.
 573      * @param data      The DataBuffer containing the image data.
 574      * @see #getNumDataElements
 575      * @see #getTransferType
 576      * @see #getDataElements(int, int, int, int, Object, DataBuffer)
 577      * @see java.awt.image.DataBuffer
 578      *
 579      * @throws NullPointerException if data is null.
 580      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 581      * not in bounds, or if obj is too small to hold the input.
 582      */
 583     public void setDataElements(int x, int y, int w, int h,
 584                                 Object obj, DataBuffer data) {
 585 
 586         int cnt = 0;
 587         Object o = null;
 588         int type = getTransferType();
 589         int numDataElems = getNumDataElements();
 590 
 591         int x1 = x + w;
 592         int y1 = y + h;
 593 
 594         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
 595             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
 596         {
 597             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
 598         }
 599 
 600         switch(type) {
 601 
 602         case DataBuffer.TYPE_BYTE:
 603 
 604             byte[] barray = (byte[])obj;
 605             byte[] btemp = new byte[numDataElems];
 606 
 607             for (int i=y; i<y1; i++) {
 608                 for (int j=x; j<x1; j++) {
 609                     for (int k=0; k<numDataElems; k++) {
 610                         btemp[k] = barray[cnt++];
 611                     }
 612 
 613                     setDataElements(j, i, btemp, data);
 614                 }
 615             }
 616             break;
 617 
 618         case DataBuffer.TYPE_USHORT:
 619         case DataBuffer.TYPE_SHORT:
 620 
 621             short[] sarray = (short[])obj;
 622             short[] stemp = new short[numDataElems];
 623 
 624             for (int i=y; i<y1; i++) {
 625                 for (int j=x; j<x1; j++) {
 626                     for (int k=0; k<numDataElems; k++) {
 627                         stemp[k] = sarray[cnt++];
 628                     }
 629 
 630                     setDataElements(j, i, stemp, data);
 631                 }
 632             }
 633             break;
 634 
 635         case DataBuffer.TYPE_INT:
 636 
 637             int[] iArray = (int[])obj;
 638             int[] itemp = new int[numDataElems];
 639 
 640             for (int i=y; i<y1; i++) {
 641                 for (int j=x; j<x1; j++) {
 642                     for (int k=0; k<numDataElems; k++) {
 643                         itemp[k] = iArray[cnt++];
 644                     }
 645 
 646                     setDataElements(j, i, itemp, data);
 647                 }
 648             }
 649             break;
 650 
 651         case DataBuffer.TYPE_FLOAT:
 652 
 653             float[] fArray = (float[])obj;
 654             float[] ftemp = new float[numDataElems];
 655 
 656             for (int i=y; i<y1; i++) {
 657                 for (int j=x; j<x1; j++) {
 658                     for (int k=0; k<numDataElems; k++) {
 659                         ftemp[k] = fArray[cnt++];
 660                     }
 661 
 662                     setDataElements(j, i, ftemp, data);
 663                 }
 664             }
 665             break;
 666 
 667         case DataBuffer.TYPE_DOUBLE:
 668 
 669             double[] dArray = (double[])obj;
 670             double[] dtemp = new double[numDataElems];
 671 
 672             for (int i=y; i<y1; i++) {
 673                 for (int j=x; j<x1; j++) {
 674                     for (int k=0; k<numDataElems; k++) {
 675                         dtemp[k] = dArray[cnt++];
 676                     }
 677 
 678                     setDataElements(j, i, dtemp, data);
 679                 }
 680             }
 681             break;
 682         }
 683 
 684     }
 685 
 686     /**
 687      * Returns the samples for the specified pixel in an array of float.
 688      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 689      * not in bounds.
 690      * @param x         The X coordinate of the pixel location.
 691      * @param y         The Y coordinate of the pixel location.
 692      * @param fArray    If non-null, returns the samples in this array.
 693      * @param data      The DataBuffer containing the image data.
 694      * @return the samples for the specified pixel.
 695      * @see #setPixel(int, int, float[], DataBuffer)
 696      *
 697      * @throws NullPointerException if data is null.
 698      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 699      * not in bounds, or if fArray is too small to hold the output.
 700      */
 701     public float[] getPixel(int x, int y, float[] fArray,
 702                             DataBuffer data) {
 703 
 704         float[] pixels;
 705 
 706         if (fArray != null)
 707             pixels = fArray;
 708         else
 709             pixels = new float[numBands];
 710 
 711         for (int i=0; i<numBands; i++)
 712             pixels[i] = getSampleFloat(x, y, i, data);
 713 
 714         return pixels;
 715     }
 716 
 717     /**
 718      * Returns the samples for the specified pixel in an array of double.
 719      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 720      * not in bounds.
 721      * @param x         The X coordinate of the pixel location.
 722      * @param y         The Y coordinate of the pixel location.
 723      * @param dArray    If non-null, returns the samples in this array.
 724      * @param data      The DataBuffer containing the image data.
 725      * @return the samples for the specified pixel.
 726      * @see #setPixel(int, int, double[], DataBuffer)
 727      *
 728      * @throws NullPointerException if data is null.
 729      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 730      * not in bounds, or if dArray is too small to hold the output.
 731      */
 732     public double[] getPixel(int x, int y, double[] dArray,
 733                              DataBuffer data) {
 734 
 735         double[] pixels;
 736 
 737         if(dArray != null)
 738             pixels = dArray;
 739         else
 740             pixels = new double[numBands];
 741 
 742         for (int i=0; i<numBands; i++)
 743             pixels[i] = getSampleDouble(x, y, i, data);
 744 
 745         return pixels;
 746     }
 747 
 748     /**
 749      * Returns all samples for a rectangle of pixels in an
 750      * int array, one sample per array element.
 751      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 752      * not in bounds.
 753      * @param x         The X coordinate of the upper left pixel location.
 754      * @param y         The Y coordinate of the upper left pixel location.
 755      * @param w         The width of the pixel rectangle.
 756      * @param h         The height of the pixel rectangle.
 757      * @param iArray    If non-null, returns the samples in this array.
 758      * @param data      The DataBuffer containing the image data.
 759      * @return the samples for the specified region of pixels.
 760      * @see #setPixels(int, int, int, int, int[], DataBuffer)
 761      *
 762      * @throws NullPointerException if data is null.
 763      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 764      * not in bounds, or if iArray is too small to hold the output.
 765      */
 766     public int[] getPixels(int x, int y, int w, int h,
 767                            int[] iArray, DataBuffer data) {
 768 
 769         int[] pixels;
 770         int Offset=0;
 771         int x1 = x + w;
 772         int y1 = y + h;
 773 
 774         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
 775             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
 776         {
 777             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
 778         }
 779 
 780         if (iArray != null)
 781             pixels = iArray;
 782         else
 783             pixels = new int[numBands * w * h];
 784 
 785         for (int i=y; i<y1; i++) {
 786             for (int j=x; j<x1; j++) {
 787                 for(int k=0; k<numBands; k++) {
 788                     pixels[Offset++] = getSample(j, i, k, data);
 789                 }
 790             }
 791         }
 792 
 793         return pixels;
 794     }
 795 
 796     /**
 797      * Returns all samples for a rectangle of pixels in a float
 798      * array, one sample per array element.
 799      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 800      * not in bounds.
 801      * @param x         The X coordinate of the upper left pixel location.
 802      * @param y         The Y coordinate of the upper left pixel location.
 803      * @param w         The width of the pixel rectangle.
 804      * @param h         The height of the pixel rectangle.
 805      * @param fArray    If non-null, returns the samples in this array.
 806      * @param data      The DataBuffer containing the image data.
 807      * @return the samples for the specified region of pixels.
 808      * @see #setPixels(int, int, int, int, float[], DataBuffer)
 809      *
 810      * @throws NullPointerException if data is null.
 811      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 812      * not in bounds, or if fArray is too small to hold the output.
 813      */
 814     public float[] getPixels(int x, int y, int w, int h,
 815                              float[] fArray, DataBuffer data) {
 816 
 817         float[] pixels;
 818         int Offset = 0;
 819         int x1 = x + w;
 820         int y1 = y + h;
 821 
 822         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
 823             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
 824         {
 825             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
 826         }
 827 
 828         if (fArray != null)
 829             pixels = fArray;
 830         else
 831             pixels = new float[numBands * w * h];
 832 
 833         for (int i=y; i<y1; i++) {
 834             for(int j=x; j<x1; j++) {
 835                 for(int k=0; k<numBands; k++) {
 836                     pixels[Offset++] = getSampleFloat(j, i, k, data);
 837                 }
 838             }
 839         }
 840 
 841         return pixels;
 842     }
 843 
 844     /**
 845      * Returns all samples for a rectangle of pixels in a double
 846      * array, one sample per array element.
 847      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 848      * not in bounds.
 849      * @param x         The X coordinate of the upper left pixel location.
 850      * @param y         The Y coordinate of the upper left pixel location.
 851      * @param w         The width of the pixel rectangle.
 852      * @param h         The height of the pixel rectangle.
 853      * @param dArray    If non-null, returns the samples in this array.
 854      * @param data      The DataBuffer containing the image data.
 855      * @return the samples for the specified region of pixels.
 856      * @see #setPixels(int, int, int, int, double[], DataBuffer)
 857      *
 858      * @throws NullPointerException if data is null.
 859      * @throws ArrayIndexOutOfBoundsException if the coordinates are
 860      * not in bounds, or if dArray is too small to hold the output.
 861      */
 862     public double[] getPixels(int x, int y, int w, int h,
 863                               double[] dArray, DataBuffer data) {
 864         double[] pixels;
 865         int    Offset = 0;
 866         int x1 = x + w;
 867         int y1 = y + h;
 868 
 869         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
 870             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
 871         {
 872             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
 873         }
 874 
 875         if (dArray != null)
 876             pixels = dArray;
 877         else
 878             pixels = new double[numBands * w * h];
 879 
 880         // Fix 4217412
 881         for (int i=y; i<y1; i++) {
 882             for (int j=x; j<x1; j++) {
 883                 for (int k=0; k<numBands; k++) {
 884                     pixels[Offset++] = getSampleDouble(j, i, k, data);
 885                 }
 886             }
 887         }
 888 
 889         return pixels;
 890     }
 891 
 892 
 893     /**
 894      * Returns the sample in a specified band for the pixel located
 895      * at (x,y) as an int.
 896      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 897      * not in bounds.
 898      * @param x         The X coordinate of the pixel location.
 899      * @param y         The Y coordinate of the pixel location.
 900      * @param b         The band to return.
 901      * @param data      The DataBuffer containing the image data.
 902      * @return the sample in a specified band for the specified pixel.
 903      * @see #setSample(int, int, int, int, DataBuffer)
 904      *
 905      * @throws NullPointerException if data is null.
 906      * @throws ArrayIndexOutOfBoundsException if the coordinates or
 907      * the band index are not in bounds.
 908      */
 909     public abstract int getSample(int x, int y, int b, DataBuffer data);
 910 
 911 
 912     /**
 913      * Returns the sample in a specified band
 914      * for the pixel located at (x,y) as a float.
 915      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 916      * not in bounds.
 917      * @param x         The X coordinate of the pixel location.
 918      * @param y         The Y coordinate of the pixel location.
 919      * @param b         The band to return.
 920      * @param data      The DataBuffer containing the image data.
 921      * @return the sample in a specified band for the specified pixel.
 922      *
 923      * @throws NullPointerException if data is null.
 924      * @throws ArrayIndexOutOfBoundsException if the coordinates or
 925      * the band index are not in bounds.
 926      */
 927     public float getSampleFloat(int x, int y, int b, DataBuffer data) {
 928 
 929         float sample;
 930         sample = (float) getSample(x, y, b, data);
 931         return sample;
 932     }
 933 
 934     /**
 935      * Returns the sample in a specified band
 936      * for a pixel located at (x,y) as a double.
 937      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 938      * not in bounds.
 939      * @param x         The X coordinate of the pixel location.
 940      * @param y         The Y coordinate of the pixel location.
 941      * @param b         The band to return.
 942      * @param data      The DataBuffer containing the image data.
 943      * @return the sample in a specified band for the specified pixel.
 944      *
 945      * @throws NullPointerException if data is null.
 946      * @throws ArrayIndexOutOfBoundsException if the coordinates or
 947      * the band index are not in bounds.
 948      */
 949     public double getSampleDouble(int x, int y, int b, DataBuffer data) {
 950 
 951         double sample;
 952 
 953         sample = (double) getSample(x, y, b, data);
 954         return sample;
 955     }
 956 
 957     /**
 958      * Returns the samples for a specified band for the specified rectangle
 959      * of pixels in an int array, one sample per array element.
 960      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 961      * not in bounds.
 962      * @param x         The X coordinate of the upper left pixel location.
 963      * @param y         The Y coordinate of the upper left pixel location.
 964      * @param w         The width of the pixel rectangle.
 965      * @param h         The height of the pixel rectangle.
 966      * @param b         The band to return.
 967      * @param iArray    If non-null, returns the samples in this array.
 968      * @param data      The DataBuffer containing the image data.
 969      * @return the samples for the specified band for the specified region
 970      *         of pixels.
 971      * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
 972      *
 973      * @throws NullPointerException if data is null.
 974      * @throws ArrayIndexOutOfBoundsException if the coordinates or
 975      * the band index are not in bounds, or if iArray is too small to
 976      * hold the output.
 977      */
 978     public int[] getSamples(int x, int y, int w, int h, int b,
 979                             int[] iArray, DataBuffer data) {
 980         int[] pixels;
 981         int Offset=0;
 982         int x1 = x + w;
 983         int y1 = y + h;
 984 
 985         if (x < 0 || x1 < x || x1 > width ||
 986             y < 0 || y1 < y || y1 > height)
 987         {
 988             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
 989         }
 990 
 991         if (iArray != null)
 992             pixels = iArray;
 993         else
 994             pixels = new int[w * h];
 995 
 996         for(int i=y; i<y1; i++) {
 997             for (int j=x; j<x1; j++) {
 998                 pixels[Offset++] = getSample(j, i, b, data);
 999             }
1000         }
1001 
1002         return pixels;
1003     }
1004 
1005     /**
1006      * Returns the samples for a specified band for the specified rectangle
1007      * of pixels in a float array, one sample per array element.
1008      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1009      * not in bounds.
1010      * @param x         The X coordinate of the upper left pixel location.
1011      * @param y         The Y coordinate of the upper left pixel location.
1012      * @param w         The width of the pixel rectangle.
1013      * @param h         The height of the pixel rectangle.
1014      * @param b         The band to return.
1015      * @param fArray    If non-null, returns the samples in this array.
1016      * @param data      The DataBuffer containing the image data.
1017      * @return the samples for the specified band for the specified region
1018      *         of pixels.
1019      * @see #setSamples(int, int, int, int, int, float[], DataBuffer)
1020      *
1021      * @throws NullPointerException if data is null.
1022      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1023      * the band index are not in bounds, or if fArray is too small to
1024      * hold the output.
1025      */
1026     public float[] getSamples(int x, int y, int w, int h,
1027                               int b, float[] fArray,
1028                               DataBuffer data) {
1029         float[] pixels;
1030         int   Offset=0;
1031         int x1 = x + w;
1032         int y1 = y + h;
1033 
1034         if (x < 0 || x1 < x || x1 > width ||
1035             y < 0 || y1 < y || y1 > height)
1036         {
1037             throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
1038         }
1039 
1040         if (fArray != null)
1041             pixels = fArray;
1042         else
1043             pixels = new float[w * h];
1044 
1045         for (int i=y; i<y1; i++) {
1046             for (int j=x; j<x1; j++) {
1047                 pixels[Offset++] = getSampleFloat(j, i, b, data);
1048             }
1049         }
1050 
1051         return pixels;
1052     }
1053 
1054     /**
1055      * Returns the samples for a specified band for a specified rectangle
1056      * of pixels in a double array, one sample per array element.
1057      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1058      * not in bounds.
1059      * @param x         The X coordinate of the upper left pixel location.
1060      * @param y         The Y coordinate of the upper left pixel location.
1061      * @param w         The width of the pixel rectangle.
1062      * @param h         The height of the pixel rectangle.
1063      * @param b         The band to return.
1064      * @param dArray    If non-null, returns the samples in this array.
1065      * @param data      The DataBuffer containing the image data.
1066      * @return the samples for the specified band for the specified region
1067      *         of pixels.
1068      * @see #setSamples(int, int, int, int, int, double[], DataBuffer)
1069      *
1070      * @throws NullPointerException if data is null.
1071      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1072      * the band index are not in bounds, or if dArray is too small to
1073      * hold the output.
1074      */
1075     public double[] getSamples(int x, int y, int w, int h,
1076                                int b, double[] dArray,
1077                                DataBuffer data) {
1078         double[] pixels;
1079         int    Offset=0;
1080         int x1 = x + w;
1081         int y1 = y + h;
1082 
1083         if (x < 0 || x1 < x || x1 > width ||
1084             y < 0 || y1 < y || y1 > height)
1085         {
1086             throw new ArrayIndexOutOfBoundsException("Invalid coordinates");
1087         }
1088 
1089         if (dArray != null)
1090             pixels = dArray;
1091         else
1092             pixels = new double[w * h];
1093 
1094         for (int i=y; i<y1; i++) {
1095             for (int j=x; j<x1; j++) {
1096                 pixels[Offset++] = getSampleDouble(j, i, b, data);
1097             }
1098         }
1099 
1100         return pixels;
1101     }
1102 
1103     /**
1104      * Sets a pixel in  the DataBuffer using an int array of samples for input.
1105      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1106      * not in bounds.
1107      * @param x         The X coordinate of the pixel location.
1108      * @param y         The Y coordinate of the pixel location.
1109      * @param iArray    The input samples in an int array.
1110      * @param data      The DataBuffer containing the image data.
1111      * @see #getPixel(int, int, int[], DataBuffer)
1112      *
1113      * @throws NullPointerException if iArray or data is null.
1114      * @throws ArrayIndexOutOfBoundsException if the coordinates are
1115      * not in bounds, or if iArray is too small to hold the input.
1116      */
1117     public void setPixel(int x, int y, int[] iArray, DataBuffer data) {
1118 
1119         for (int i=0; i<numBands; i++)
1120             setSample(x, y, i, iArray[i], data);
1121     }
1122 
1123     /**
1124      * Sets a pixel in the DataBuffer using a float array of samples for input.
1125      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1126      * not in bounds.
1127      * @param x         The X coordinate of the pixel location.
1128      * @param y         The Y coordinate of the pixel location.
1129      * @param fArray    The input samples in a float array.
1130      * @param data      The DataBuffer containing the image data.
1131      * @see #getPixel(int, int, float[], DataBuffer)
1132      *
1133      * @throws NullPointerException if fArray or data is null.
1134      * @throws ArrayIndexOutOfBoundsException if the coordinates are
1135      * not in bounds, or if fArray is too small to hold the input.
1136      */
1137     public void setPixel(int x, int y, float[] fArray, DataBuffer data) {
1138 
1139         for (int i=0; i<numBands; i++)
1140             setSample(x, y, i, fArray[i], data);
1141     }
1142 
1143     /**
1144      * Sets a pixel in the DataBuffer using a double array of samples
1145      * for input.
1146      * @param x         The X coordinate of the pixel location.
1147      * @param y         The Y coordinate of the pixel location.
1148      * @param dArray    The input samples in a double array.
1149      * @param data      The DataBuffer containing the image data.
1150      * @see #getPixel(int, int, double[], DataBuffer)
1151      *
1152      * @throws NullPointerException if dArray or data is null.
1153      * @throws ArrayIndexOutOfBoundsException if the coordinates are
1154      * not in bounds, or if fArray is too small to hold the input.
1155      */
1156     public void setPixel(int x, int y, double[] dArray, DataBuffer data) {
1157 
1158         for (int i=0; i<numBands; i++)
1159             setSample(x, y, i, dArray[i], data);
1160     }
1161 
1162     /**
1163      * Sets all samples for a rectangle of pixels from an int array containing
1164      * one sample per array element.
1165      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1166      * not in bounds.
1167      * @param x         The X coordinate of the upper left pixel location.
1168      * @param y         The Y coordinate of the upper left pixel location.
1169      * @param w         The width of the pixel rectangle.
1170      * @param h         The height of the pixel rectangle.
1171      * @param iArray    The input samples in an int array.
1172      * @param data      The DataBuffer containing the image data.
1173      * @see #getPixels(int, int, int, int, int[], DataBuffer)
1174      *
1175      * @throws NullPointerException if iArray or data is null.
1176      * @throws ArrayIndexOutOfBoundsException if the coordinates are
1177      * not in bounds, or if iArray is too small to hold the input.
1178      */
1179     public void setPixels(int x, int y, int w, int h,
1180                           int[] iArray, DataBuffer data) {
1181         int Offset=0;
1182         int x1 = x + w;
1183         int y1 = y + h;
1184 
1185         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
1186             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1187         {
1188             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
1189         }
1190 
1191         for (int i=y; i<y1; i++) {
1192             for (int j=x; j<x1; j++) {
1193                 for (int k=0; k<numBands; k++) {
1194                     setSample(j, i, k, iArray[Offset++], data);
1195                 }
1196             }
1197         }
1198     }
1199 
1200     /**
1201      * Sets all samples for a rectangle of pixels from a float array containing
1202      * one sample per array element.
1203      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1204      * not in bounds.
1205      * @param x         The X coordinate of the upper left pixel location.
1206      * @param y         The Y coordinate of the upper left pixel location.
1207      * @param w         The width of the pixel rectangle.
1208      * @param h         The height of the pixel rectangle.
1209      * @param fArray    The input samples in a float array.
1210      * @param data      The DataBuffer containing the image data.
1211      * @see #getPixels(int, int, int, int, float[], DataBuffer)
1212      *
1213      * @throws NullPointerException if fArray or data is null.
1214      * @throws ArrayIndexOutOfBoundsException if the coordinates are
1215      * not in bounds, or if fArray is too small to hold the input.
1216      */
1217     public void setPixels(int x, int y, int w, int h,
1218                           float[] fArray, DataBuffer data) {
1219         int Offset=0;
1220         int x1 = x + w;
1221         int y1 = y + h;
1222 
1223         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width||
1224             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1225         {
1226             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
1227         }
1228 
1229         for (int i=y; i<y1; i++) {
1230             for (int j=x; j<x1; j++) {
1231                 for(int k=0; k<numBands; k++) {
1232                     setSample(j, i, k, fArray[Offset++], data);
1233                 }
1234             }
1235         }
1236     }
1237 
1238     /**
1239      * Sets all samples for a rectangle of pixels from a double array
1240      * containing one sample per array element.
1241      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1242      * not in bounds.
1243      * @param x         The X coordinate of the upper left pixel location.
1244      * @param y         The Y coordinate of the upper left pixel location.
1245      * @param w         The width of the pixel rectangle.
1246      * @param h         The height of the pixel rectangle.
1247      * @param dArray    The input samples in a double array.
1248      * @param data      The DataBuffer containing the image data.
1249      * @see #getPixels(int, int, int, int, double[], DataBuffer)
1250      *
1251      * @throws NullPointerException if dArray or data is null.
1252      * @throws ArrayIndexOutOfBoundsException if the coordinates are
1253      * not in bounds, or if dArray is too small to hold the input.
1254      */
1255     public void setPixels(int x, int y, int w, int h,
1256                           double[] dArray, DataBuffer data) {
1257         int Offset=0;
1258         int x1 = x + w;
1259         int y1 = y + h;
1260 
1261         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
1262             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1263         {
1264             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
1265         }
1266 
1267         for (int i=y; i<y1; i++) {
1268             for (int j=x; j<x1; j++) {
1269                 for (int k=0; k<numBands; k++) {
1270                     setSample(j, i, k, dArray[Offset++], data);
1271                 }
1272             }
1273         }
1274     }
1275 
1276     /**
1277      * Sets a sample in the specified band for the pixel located at (x,y)
1278      * in the DataBuffer using an int for input.
1279      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1280      * not in bounds.
1281      * @param x         The X coordinate of the pixel location.
1282      * @param y         The Y coordinate of the pixel location.
1283      * @param b         The band to set.
1284      * @param s         The input sample as an int.
1285      * @param data      The DataBuffer containing the image data.
1286      * @see #getSample(int, int, int,  DataBuffer)
1287      *
1288      * @throws NullPointerException if data is null.
1289      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1290      * the band index are not in bounds.
1291      */
1292     public abstract void setSample(int x, int y, int b,
1293                                    int s,
1294                                    DataBuffer data);
1295 
1296     /**
1297      * Sets a sample in the specified band for the pixel located at (x,y)
1298      * in the DataBuffer using a float for input.
1299      * The default implementation of this method casts the input
1300      * float sample to an int and then calls the
1301      * {@code setSample(int, int, int, DataBuffer)} method using
1302      * that int value.
1303      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1304      * not in bounds.
1305      * @param x         The X coordinate of the pixel location.
1306      * @param y         The Y coordinate of the pixel location.
1307      * @param b         The band to set.
1308      * @param s         The input sample as a float.
1309      * @param data      The DataBuffer containing the image data.
1310      * @see #getSample(int, int, int, DataBuffer)
1311      *
1312      * @throws NullPointerException if data is null.
1313      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1314      * the band index are not in bounds.
1315      */
1316     public void setSample(int x, int y, int b,
1317                           float s ,
1318                           DataBuffer data) {
1319         int sample = (int)s;
1320 
1321         setSample(x, y, b, sample, data);
1322     }
1323 
1324     /**
1325      * Sets a sample in the specified band for the pixel located at (x,y)
1326      * in the DataBuffer using a double for input.
1327      * The default implementation of this method casts the input
1328      * double sample to an int and then calls the
1329      * {@code setSample(int, int, int, DataBuffer)} method using
1330      * that int value.
1331      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1332      * not in bounds.
1333      * @param x         The X coordinate of the pixel location.
1334      * @param y         The Y coordinate of the pixel location.
1335      * @param b         The band to set.
1336      * @param s         The input sample as a double.
1337      * @param data      The DataBuffer containing the image data.
1338      * @see #getSample(int, int, int, DataBuffer)
1339      *
1340      * @throws NullPointerException if data is null.
1341      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1342      * the band index are not in bounds.
1343      */
1344     public void setSample(int x, int y, int b,
1345                           double s,
1346                           DataBuffer data) {
1347         int sample = (int)s;
1348 
1349         setSample(x, y, b, sample, data);
1350     }
1351 
1352     /**
1353      * Sets the samples in the specified band for the specified rectangle
1354      * of pixels from an int array containing one sample per array element.
1355      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1356      * not in bounds.
1357      * @param x         The X coordinate of the upper left pixel location.
1358      * @param y         The Y coordinate of the upper left pixel location.
1359      * @param w         The width of the pixel rectangle.
1360      * @param h         The height of the pixel rectangle.
1361      * @param b         The band to set.
1362      * @param iArray    The input samples in an int array.
1363      * @param data      The DataBuffer containing the image data.
1364      * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
1365      *
1366      * @throws NullPointerException if iArray or data is null.
1367      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1368      * the band index are not in bounds, or if iArray is too small to
1369      * hold the input.
1370      */
1371     public void setSamples(int x, int y, int w, int h, int b,
1372                            int[] iArray, DataBuffer data) {
1373 
1374         int Offset=0;
1375         int x1 = x + w;
1376         int y1 = y + h;
1377         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
1378             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1379         {
1380             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
1381         }
1382 
1383         for (int i=y; i<y1; i++) {
1384             for (int j=x; j<x1; j++) {
1385                 setSample(j, i, b, iArray[Offset++], data);
1386             }
1387         }
1388     }
1389 
1390     /**
1391      * Sets the samples in the specified band for the specified rectangle
1392      * of pixels from a float array containing one sample per array element.
1393      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1394      * not in bounds.
1395      * @param x         The X coordinate of the upper left pixel location.
1396      * @param y         The Y coordinate of the upper left pixel location.
1397      * @param w         The width of the pixel rectangle.
1398      * @param h         The height of the pixel rectangle.
1399      * @param b         The band to set.
1400      * @param fArray    The input samples in a float array.
1401      * @param data      The DataBuffer containing the image data.
1402      * @see #getSamples(int, int, int, int, int, float[], DataBuffer)
1403      *
1404      * @throws NullPointerException if fArray or data is null.
1405      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1406      * the band index are not in bounds, or if fArray is too small to
1407      * hold the input.
1408      */
1409     public void setSamples(int x, int y, int w, int h, int b,
1410                            float[] fArray, DataBuffer data) {
1411         int Offset=0;
1412         int x1 = x + w;
1413         int y1 = y + h;
1414 
1415         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
1416             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1417         {
1418             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
1419         }
1420 
1421         for (int i=y; i<y1; i++) {
1422             for (int j=x; j<x1; j++) {
1423                 setSample(j, i, b, fArray[Offset++], data);
1424             }
1425         }
1426     }
1427 
1428     /**
1429      * Sets the samples in the specified band for the specified rectangle
1430      * of pixels from a double array containing one sample per array element.
1431      * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
1432      * not in bounds.
1433      * @param x         The X coordinate of the upper left pixel location.
1434      * @param y         The Y coordinate of the upper left pixel location.
1435      * @param w         The width of the pixel rectangle.
1436      * @param h         The height of the pixel rectangle.
1437      * @param b         The band to set.
1438      * @param dArray    The input samples in a double array.
1439      * @param data      The DataBuffer containing the image data.
1440      * @see #getSamples(int, int, int, int, int, double[], DataBuffer)
1441      *
1442      * @throws NullPointerException if dArray or data is null.
1443      * @throws ArrayIndexOutOfBoundsException if the coordinates or
1444      * the band index are not in bounds, or if dArray is too small to
1445      * hold the input.
1446      */
1447     public void setSamples(int x, int y, int w, int h, int b,
1448                            double[] dArray, DataBuffer data) {
1449         int Offset=0;
1450         int x1 = x + w;
1451         int y1 = y + h;
1452 
1453 
1454         if (x < 0 || x >= width || w > width || x1 < 0 || x1 > width ||
1455             y < 0 || y >= height || h > height || y1 < 0 || y1 > height)
1456         {
1457             throw new ArrayIndexOutOfBoundsException("Invalid coordinates.");
1458         }
1459 
1460         for (int i=y; i<y1; i++) {
1461             for (int j=x; j<x1; j++) {
1462                 setSample(j, i, b, dArray[Offset++], data);
1463             }
1464         }
1465     }
1466 
1467     /**
1468      *  Creates a SampleModel which describes data in this SampleModel's
1469      *  format, but with a different width and height.
1470      *  @param w the width of the image data
1471      *  @param h the height of the image data
1472      *  @return a {@code SampleModel} describing the same image
1473      *          data as this {@code SampleModel}, but with a
1474      *          different size.
1475      */
1476     public abstract SampleModel createCompatibleSampleModel(int w, int h);
1477 
1478     /**
1479      * Creates a new SampleModel
1480      * with a subset of the bands of this
1481      * SampleModel.
1482      * @param bands the subset of bands of this {@code SampleModel}
1483      * @return a {@code SampleModel} with a subset of bands of this
1484      *         {@code SampleModel}.
1485      */
1486     public abstract SampleModel createSubsetSampleModel(int[] bands);
1487 
1488     /**
1489      * Creates a DataBuffer that corresponds to this SampleModel.
1490      * The DataBuffer's width and height will match this SampleModel's.
1491      * @return a {@code DataBuffer} corresponding to this
1492      *         {@code SampleModel}.
1493      */
1494     public abstract DataBuffer createDataBuffer();
1495 
1496     /** Returns the size in bits of samples for all bands.
1497      *  @return the size of samples for all bands.
1498      */
1499     public abstract int[] getSampleSize();
1500 
1501     /** Returns the size in bits of samples for the specified band.
1502      *  @param band the specified band
1503      *  @return the size of the samples of the specified band.
1504      */
1505     public abstract int getSampleSize(int band);
1506 
1507 }