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