< prev index next >

src/java.desktop/share/classes/java/awt/image/ComponentSampleModel.java

Print this page


   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


  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      */


 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         }


 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 "+


 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             }


 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}.


 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() {


 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;


 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 


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               }


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)) {


   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


  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      */


 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         }


 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 "+


 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             }


 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}.


 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() {


 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;


 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 


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               }


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)) {


< prev index next >