61 * {@link DataBuffer#TYPE_INT TYPE_INT}, 62 * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and 63 * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes 64 */ 65 66 67 public final class BandedSampleModel extends ComponentSampleModel 68 { 69 70 /** 71 * Constructs a BandedSampleModel with the specified parameters. 72 * The pixel stride will be one data element. The scanline stride 73 * will be the same as the width. Each band will be stored in 74 * a separate bank and all band offsets will be zero. 75 * @param dataType The data type for storing samples. 76 * @param w The width (in pixels) of the region of 77 * image data described. 78 * @param h The height (in pixels) of the region of image 79 * data described. 80 * @param numBands The number of bands for the image data. 81 * @throws IllegalArgumentException if <code>dataType</code> is not 82 * one of the supported data types 83 */ 84 public BandedSampleModel(int dataType, int w, int h, int numBands) { 85 super(dataType, w, h, 1, w, 86 BandedSampleModel.createIndicesArray(numBands), 87 BandedSampleModel.createOffsetArray(numBands)); 88 } 89 90 /** 91 * Constructs a BandedSampleModel with the specified parameters. 92 * The number of bands will be inferred from the lengths of the 93 * bandOffsets bankIndices arrays, which must be equal. The pixel 94 * stride will be one data element. 95 * @param dataType The data type for storing samples. 96 * @param w The width (in pixels) of the region of 97 * image data described. 98 * @param h The height (in pixels) of the region of 99 * image data described. 100 * @param scanlineStride The line stride of the of the image data. 101 * @param bankIndices The bank index for each band. 102 * @param bandOffsets The band offset for each band. 103 * @throws IllegalArgumentException if <code>dataType</code> is not 104 * one of the supported data types 105 */ 106 public BandedSampleModel(int dataType, 107 int w, int h, 108 int scanlineStride, 109 int bankIndices[], 110 int bandOffsets[]) { 111 112 super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets); 113 } 114 115 /** 116 * Creates a new BandedSampleModel with the specified 117 * width and height. The new BandedSampleModel will have the same 118 * number of bands, storage data type, and bank indices 119 * as this BandedSampleModel. The band offsets will be compressed 120 * such that the offset between bands will be w*pixelStride and 121 * the minimum of all of the band offsets is zero. 122 * @param w the width of the resulting <code>BandedSampleModel</code> 123 * @param h the height of the resulting <code>BandedSampleModel</code> 124 * @return a new <code>BandedSampleModel</code> with the specified 125 * width and height. 126 * @throws IllegalArgumentException if <code>w</code> or 127 * <code>h</code> equals either 128 * <code>Integer.MAX_VALUE</code> or 129 * <code>Integer.MIN_VALUE</code> 130 * @throws IllegalArgumentException if <code>dataType</code> is not 131 * one of the supported data types 132 */ 133 public SampleModel createCompatibleSampleModel(int w, int h) { 134 int[] bandOffs; 135 136 if (numBanks == 1) { 137 bandOffs = orderBands(bandOffsets, w*h); 138 } 139 else { 140 bandOffs = new int[bandOffsets.length]; 141 } 142 143 SampleModel sampleModel = 144 new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs); 145 return sampleModel; 146 } 147 148 /** 149 * Creates a new BandedSampleModel with a subset of the bands of this 150 * BandedSampleModel. The new BandedSampleModel can be 151 * used with any DataBuffer that the existing BandedSampleModel 152 * can be used with. The new BandedSampleModel/DataBuffer 153 * combination will represent an image with a subset of the bands 154 * of the original BandedSampleModel/DataBuffer combination. 155 * @throws RasterFormatException if the number of bands is greater than 156 * the number of banks in this sample model. 157 * @throws IllegalArgumentException if <code>dataType</code> is not 158 * one of the supported data types 159 */ 160 public SampleModel createSubsetSampleModel(int bands[]) { 161 if (bands.length > bankIndices.length) 162 throw new RasterFormatException("There are only " + 163 bankIndices.length + 164 " bands"); 165 int newBankIndices[] = new int[bands.length]; 166 int newBandOffsets[] = new int[bands.length]; 167 168 for (int i=0; i<bands.length; i++) { 169 newBankIndices[i] = bankIndices[bands[i]]; 170 newBandOffsets[i] = bandOffsets[bands[i]]; 171 } 172 173 return new BandedSampleModel(this.dataType, width, height, 174 this.scanlineStride, 175 newBankIndices, newBandOffsets); 176 } 177 178 /** 179 * Creates a DataBuffer that corresponds to this BandedSampleModel, 180 * The DataBuffer's data type, number of banks, and size 181 * will be consistent with this BandedSampleModel. 182 * @throws IllegalArgumentException if <code>dataType</code> is not 183 * one of the supported types. 184 */ 185 public DataBuffer createDataBuffer() { 186 DataBuffer dataBuffer = null; 187 188 int size = scanlineStride * height; 189 switch (dataType) { 190 case DataBuffer.TYPE_BYTE: 191 dataBuffer = new DataBufferByte(size, numBanks); 192 break; 193 case DataBuffer.TYPE_USHORT: 194 dataBuffer = new DataBufferUShort(size, numBanks); 195 break; 196 case DataBuffer.TYPE_SHORT: 197 dataBuffer = new DataBufferShort(size, numBanks); 198 break; 199 case DataBuffer.TYPE_INT: 200 dataBuffer = new DataBufferInt(size, numBanks); 201 break; 202 case DataBuffer.TYPE_FLOAT: 206 dataBuffer = new DataBufferDouble(size, numBanks); 207 break; 208 default: 209 throw new IllegalArgumentException("dataType is not one " + 210 "of the supported types."); 211 } 212 213 return dataBuffer; 214 } 215 216 217 /** 218 * Returns data for a single pixel in a primitive array of type 219 * TransferType. For a BandedSampleModel, this will be the same 220 * as the data type, and samples will be returned one per array 221 * element. Generally, obj 222 * should be passed in as null, so that the Object will be created 223 * automatically and will be of the right primitive data type. 224 * <p> 225 * The following code illustrates transferring data for one pixel from 226 * DataBuffer <code>db1</code>, whose storage layout is described by 227 * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>, 228 * whose storage layout is described by 229 * BandedSampleModel <code>bsm2</code>. 230 * The transfer will generally be more efficient than using 231 * getPixel/setPixel. 232 * <pre> 233 * BandedSampleModel bsm1, bsm2; 234 * DataBufferInt db1, db2; 235 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1), 236 * db2); 237 * </pre> 238 * Using getDataElements/setDataElements to transfer between two 239 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have 240 * the same number of bands, corresponding bands have the same number of 241 * bits per sample, and the TransferTypes are the same. 242 * <p> 243 * If obj is non-null, it should be a primitive array of type TransferType. 244 * Otherwise, a ClassCastException is thrown. An 245 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 246 * not in bounds, or if obj is non-null and is not large enough to hold 247 * the pixel data. 248 * @param x The X coordinate of the pixel location 249 * @param y The Y coordinate of the pixel location 548 int srcOffset = 0; 549 int bank = bankIndices[b]; 550 551 for (int i = 0; i < h; i++) { 552 int sampleOffset = lineOffset; 553 for (int j = 0; j < w; j++) { 554 samples[srcOffset++] = data.getElem(bank, sampleOffset++); 555 } 556 lineOffset += scanlineStride; 557 } 558 return samples; 559 } 560 561 /** 562 * Sets the data for a single pixel in the specified DataBuffer from a 563 * primitive array of type TransferType. For a BandedSampleModel, 564 * this will be the same as the data type, and samples are transferred 565 * one per array element. 566 * <p> 567 * The following code illustrates transferring data for one pixel from 568 * DataBuffer <code>db1</code>, whose storage layout is described by 569 * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>, 570 * whose storage layout is described by 571 * BandedSampleModel <code>bsm2</code>. 572 * The transfer will generally be more efficient than using 573 * getPixel/setPixel. 574 * <pre> 575 * BandedSampleModel bsm1, bsm2; 576 * DataBufferInt db1, db2; 577 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1), 578 * db2); 579 * </pre> 580 * Using getDataElements/setDataElements to transfer between two 581 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have 582 * the same number of bands, corresponding bands have the same number of 583 * bits per sample, and the TransferTypes are the same. 584 * <p> 585 * obj must be a primitive array of type TransferType. Otherwise, 586 * a ClassCastException is thrown. An 587 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 588 * not in bounds, or if obj is not large enough to hold the pixel data. 589 * @param x The X coordinate of the pixel location 590 * @param y The Y coordinate of the pixel location 591 * @param obj If non-null, returns the primitive array in this | 61 * {@link DataBuffer#TYPE_INT TYPE_INT}, 62 * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and 63 * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes 64 */ 65 66 67 public final class BandedSampleModel extends ComponentSampleModel 68 { 69 70 /** 71 * Constructs a BandedSampleModel with the specified parameters. 72 * The pixel stride will be one data element. The scanline stride 73 * will be the same as the width. Each band will be stored in 74 * a separate bank and all band offsets will be zero. 75 * @param dataType The data type for storing samples. 76 * @param w The width (in pixels) of the region of 77 * image data described. 78 * @param h The height (in pixels) of the region of image 79 * data described. 80 * @param numBands The number of bands for the image data. 81 * @throws IllegalArgumentException if {@code dataType} is not 82 * one of the supported data types 83 */ 84 public BandedSampleModel(int dataType, int w, int h, int numBands) { 85 super(dataType, w, h, 1, w, 86 BandedSampleModel.createIndicesArray(numBands), 87 BandedSampleModel.createOffsetArray(numBands)); 88 } 89 90 /** 91 * Constructs a BandedSampleModel with the specified parameters. 92 * The number of bands will be inferred from the lengths of the 93 * bandOffsets bankIndices arrays, which must be equal. The pixel 94 * stride will be one data element. 95 * @param dataType The data type for storing samples. 96 * @param w The width (in pixels) of the region of 97 * image data described. 98 * @param h The height (in pixels) of the region of 99 * image data described. 100 * @param scanlineStride The line stride of the of the image data. 101 * @param bankIndices The bank index for each band. 102 * @param bandOffsets The band offset for each band. 103 * @throws IllegalArgumentException if {@code dataType} is not 104 * one of the supported data types 105 */ 106 public BandedSampleModel(int dataType, 107 int w, int h, 108 int scanlineStride, 109 int bankIndices[], 110 int bandOffsets[]) { 111 112 super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets); 113 } 114 115 /** 116 * Creates a new BandedSampleModel with the specified 117 * width and height. The new BandedSampleModel will have the same 118 * number of bands, storage data type, and bank indices 119 * as this BandedSampleModel. The band offsets will be compressed 120 * such that the offset between bands will be w*pixelStride and 121 * the minimum of all of the band offsets is zero. 122 * @param w the width of the resulting {@code BandedSampleModel} 123 * @param h the height of the resulting {@code BandedSampleModel} 124 * @return a new {@code BandedSampleModel} with the specified 125 * width and height. 126 * @throws IllegalArgumentException if {@code w} or 127 * {@code h} equals either 128 * {@code Integer.MAX_VALUE} or 129 * {@code Integer.MIN_VALUE} 130 * @throws IllegalArgumentException if {@code dataType} is not 131 * one of the supported data types 132 */ 133 public SampleModel createCompatibleSampleModel(int w, int h) { 134 int[] bandOffs; 135 136 if (numBanks == 1) { 137 bandOffs = orderBands(bandOffsets, w*h); 138 } 139 else { 140 bandOffs = new int[bandOffsets.length]; 141 } 142 143 SampleModel sampleModel = 144 new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs); 145 return sampleModel; 146 } 147 148 /** 149 * Creates a new BandedSampleModel with a subset of the bands of this 150 * BandedSampleModel. The new BandedSampleModel can be 151 * used with any DataBuffer that the existing BandedSampleModel 152 * can be used with. The new BandedSampleModel/DataBuffer 153 * combination will represent an image with a subset of the bands 154 * of the original BandedSampleModel/DataBuffer combination. 155 * @throws RasterFormatException if the number of bands is greater than 156 * the number of banks in this sample model. 157 * @throws IllegalArgumentException if {@code dataType} is not 158 * one of the supported data types 159 */ 160 public SampleModel createSubsetSampleModel(int bands[]) { 161 if (bands.length > bankIndices.length) 162 throw new RasterFormatException("There are only " + 163 bankIndices.length + 164 " bands"); 165 int newBankIndices[] = new int[bands.length]; 166 int newBandOffsets[] = new int[bands.length]; 167 168 for (int i=0; i<bands.length; i++) { 169 newBankIndices[i] = bankIndices[bands[i]]; 170 newBandOffsets[i] = bandOffsets[bands[i]]; 171 } 172 173 return new BandedSampleModel(this.dataType, width, height, 174 this.scanlineStride, 175 newBankIndices, newBandOffsets); 176 } 177 178 /** 179 * Creates a DataBuffer that corresponds to this BandedSampleModel, 180 * The DataBuffer's data type, number of banks, and size 181 * will be consistent with this BandedSampleModel. 182 * @throws IllegalArgumentException if {@code dataType} is not 183 * one of the supported types. 184 */ 185 public DataBuffer createDataBuffer() { 186 DataBuffer dataBuffer = null; 187 188 int size = scanlineStride * height; 189 switch (dataType) { 190 case DataBuffer.TYPE_BYTE: 191 dataBuffer = new DataBufferByte(size, numBanks); 192 break; 193 case DataBuffer.TYPE_USHORT: 194 dataBuffer = new DataBufferUShort(size, numBanks); 195 break; 196 case DataBuffer.TYPE_SHORT: 197 dataBuffer = new DataBufferShort(size, numBanks); 198 break; 199 case DataBuffer.TYPE_INT: 200 dataBuffer = new DataBufferInt(size, numBanks); 201 break; 202 case DataBuffer.TYPE_FLOAT: 206 dataBuffer = new DataBufferDouble(size, numBanks); 207 break; 208 default: 209 throw new IllegalArgumentException("dataType is not one " + 210 "of the supported types."); 211 } 212 213 return dataBuffer; 214 } 215 216 217 /** 218 * Returns data for a single pixel in a primitive array of type 219 * TransferType. For a BandedSampleModel, this will be the same 220 * as the data type, and samples will be returned one per array 221 * element. Generally, obj 222 * should be passed in as null, so that the Object will be created 223 * automatically and will be of the right primitive data type. 224 * <p> 225 * The following code illustrates transferring data for one pixel from 226 * DataBuffer {@code db1}, whose storage layout is described by 227 * BandedSampleModel {@code bsm1}, to DataBuffer {@code db2}, 228 * whose storage layout is described by 229 * BandedSampleModel {@code bsm2}. 230 * The transfer will generally be more efficient than using 231 * getPixel/setPixel. 232 * <pre> 233 * BandedSampleModel bsm1, bsm2; 234 * DataBufferInt db1, db2; 235 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1), 236 * db2); 237 * </pre> 238 * Using getDataElements/setDataElements to transfer between two 239 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have 240 * the same number of bands, corresponding bands have the same number of 241 * bits per sample, and the TransferTypes are the same. 242 * <p> 243 * If obj is non-null, it should be a primitive array of type TransferType. 244 * Otherwise, a ClassCastException is thrown. An 245 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 246 * not in bounds, or if obj is non-null and is not large enough to hold 247 * the pixel data. 248 * @param x The X coordinate of the pixel location 249 * @param y The Y coordinate of the pixel location 548 int srcOffset = 0; 549 int bank = bankIndices[b]; 550 551 for (int i = 0; i < h; i++) { 552 int sampleOffset = lineOffset; 553 for (int j = 0; j < w; j++) { 554 samples[srcOffset++] = data.getElem(bank, sampleOffset++); 555 } 556 lineOffset += scanlineStride; 557 } 558 return samples; 559 } 560 561 /** 562 * Sets the data for a single pixel in the specified DataBuffer from a 563 * primitive array of type TransferType. For a BandedSampleModel, 564 * this will be the same as the data type, and samples are transferred 565 * one per array element. 566 * <p> 567 * The following code illustrates transferring data for one pixel from 568 * DataBuffer {@code db1}, whose storage layout is described by 569 * BandedSampleModel {@code bsm1}, to DataBuffer {@code db2}, 570 * whose storage layout is described by 571 * BandedSampleModel {@code bsm2}. 572 * The transfer will generally be more efficient than using 573 * getPixel/setPixel. 574 * <pre> 575 * BandedSampleModel bsm1, bsm2; 576 * DataBufferInt db1, db2; 577 * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1), 578 * db2); 579 * </pre> 580 * Using getDataElements/setDataElements to transfer between two 581 * DataBuffer/SampleModel pairs is legitimate if the SampleModels have 582 * the same number of bands, corresponding bands have the same number of 583 * bits per sample, and the TransferTypes are the same. 584 * <p> 585 * obj must be a primitive array of type TransferType. Otherwise, 586 * a ClassCastException is thrown. An 587 * ArrayIndexOutOfBoundsException may be thrown if the coordinates are 588 * not in bounds, or if obj is not large enough to hold the pixel data. 589 * @param x The X coordinate of the pixel location 590 * @param y The Y coordinate of the pixel location 591 * @param obj If non-null, returns the primitive array in this |