Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / java / awt / image / ComponentSampleModel.java
blobb4e9450b0606a94ed1a548b930a44c3b331876d3
1 /* Copyright (C) 2000, 2002, 2006, Free Software Foundation
3 This file is part of GNU Classpath.
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301 USA.
20 Linking this library statically or dynamically with other modules is
21 making a combined work based on this library. Thus, the terms and
22 conditions of the GNU General Public License cover the whole
23 combination.
25 As a special exception, the copyright holders of this library give you
26 permission to link this library with independent modules to produce an
27 executable, regardless of the license terms of these independent
28 modules, and to copy and distribute the resulting executable under
29 terms of your choice, provided that you also meet, for each linked
30 independent module, the terms and conditions of the license of that
31 module. An independent module is a module which is not derived from
32 or based on this library. If you modify this library, you may extend
33 this exception to your version of the library, but you are not
34 obligated to do so. If you do not wish to do so, delete this
35 exception statement from your version. */
37 package java.awt.image;
39 import gnu.java.awt.Buffers;
41 import java.util.Arrays;
43 /* FIXME: This class does not yet support data type TYPE_SHORT */
45 /**
46 * ComponentSampleModel supports a flexible organization of pixel samples in
47 * memory, permitting pixel samples to be interleaved by band, by scanline,
48 * and by pixel.
50 * A DataBuffer for this sample model has K banks of data. Pixels have N
51 * samples, so there are N bands in the DataBuffer. Each band is completely
52 * contained in one bank of data, but a bank may contain more than one band.
53 * Each pixel sample is stored in a single data element.
55 * Within a bank, each band begins at an offset stored in bandOffsets. The
56 * banks containing the band is given by bankIndices. Within the bank, there
57 * are three dimensions - band, pixel, and scanline. The dimension ordering
58 * is controlled by bandOffset, pixelStride, and scanlineStride, which means
59 * that any combination of interleavings is supported.
61 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
63 public class ComponentSampleModel extends SampleModel
65 /** The offsets to the first sample for each band. */
66 protected int[] bandOffsets;
68 /** The indices of the bank used to store each band in a data buffer. */
69 protected int[] bankIndices;
71 /**
72 * The number of bands in the image.
73 * @specnote This field shadows the protected numBands in SampleModel.
75 protected int numBands;
77 /** Used when creating data buffers. */
78 protected int numBanks;
80 /**
81 * The number of data elements between a sample in one row and the
82 * corresponding sample in the next row.
84 protected int scanlineStride;
86 /**
87 * The number of data elements between a sample for one pixel and the
88 * corresponding sample for the next pixel in the same row.
90 protected int pixelStride;
92 private boolean tightPixelPacking = false;
94 /**
95 * Creates a new sample model that assumes that all bands are stored in a
96 * single bank of the {@link DataBuffer}.
97 * <p>
98 * Note that the <code>bandOffsets</code> array is copied to internal storage
99 * to prevent subsequent changes to the array from affecting this object.
101 * @param dataType the data type (one of {@link DataBuffer#TYPE_BYTE},
102 * {@link DataBuffer#TYPE_USHORT}, {@link DataBuffer#TYPE_SHORT},
103 * {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT} or
104 * {@link DataBuffer#TYPE_DOUBLE}).
105 * @param w the width in pixels.
106 * @param h the height in pixels.
107 * @param pixelStride the number of data elements in the step from a sample
108 * in one pixel to the corresponding sample in the next pixel.
109 * @param scanlineStride the number of data elements in the step from a
110 * sample in a pixel to the corresponding sample in the pixel in the next
111 * row.
112 * @param bandOffsets the offset to the first element for each band, with
113 * the size of the array defining the number of bands (<code>null</code>
114 * not permitted).
116 * @throws IllegalArgumentException if <code>dataType</code> is not one of
117 * the specified values.
118 * @throws IllegalArgumentException if <code>w</code> is less than or equal
119 * to zero.
120 * @throws IllegalArgumentException if <code>h</code> is less than or equal
121 * to zero.
122 * @throws IllegalArgumentException if <code>w * h</code> exceeds
123 * {@link Integer#MAX_VALUE}.
124 * @throws IllegalArgumentException if <code>pixelStride</code> is negative.
125 * @throws IllegalArgumentException if <code>scanlineStride</code> is less
126 * than or equal to zero.
127 * @throws IllegalArgumentException if <code>bandOffsets</code> has zero
128 * length.
130 public ComponentSampleModel(int dataType,
131 int w, int h,
132 int pixelStride,
133 int scanlineStride,
134 int[] bandOffsets)
136 this(dataType, w, h, pixelStride, scanlineStride,
137 new int[bandOffsets.length], bandOffsets);
141 * Creates a new sample model that assumes that all bands are stored in a
142 * single bank of the {@link DataBuffer}.
144 * @param dataType the data type (one of {@link DataBuffer#TYPE_BYTE},
145 * {@link DataBuffer#TYPE_USHORT}, {@link DataBuffer#TYPE_SHORT},
146 * {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT} or
147 * {@link DataBuffer#TYPE_DOUBLE}).
148 * @param w the width in pixels.
149 * @param h the height in pixels.
150 * @param pixelStride the number of data elements in the step from a sample
151 * in one pixel to the corresponding sample in the next pixel.
152 * @param scanlineStride the number of data elements in the step from a
153 * sample in a pixel to the corresponding sample in the pixel in the next
154 * row.
155 * @param bankIndices the index of the bank in which each band is stored
156 * (<code>null</code> not permitted). This array is copied to internal
157 * storage so that subsequent updates to the array do not affect the sample
158 * model.
159 * @param bandOffsets the offset to the first element for each band, with
160 * the size of the array defining the number of bands (<code>null</code>
161 * not permitted). This array is copied to internal storage so that
162 * subsequent updates to the array do not affect the sample model.
164 * @throws IllegalArgumentException if <code>dataType</code> is not one of
165 * the specified values.
166 * @throws IllegalArgumentException if <code>w</code> is less than or equal
167 * to zero.
168 * @throws IllegalArgumentException if <code>h</code> is less than or equal
169 * to zero.
170 * @throws IllegalArgumentException if <code>w * h</code> exceeds
171 * {@link Integer#MAX_VALUE}.
172 * @throws IllegalArgumentException if <code>pixelStride</code> is negative.
173 * @throws IllegalArgumentException if <code>scanlineStride</code> is less
174 * than or equal to zero.
175 * @throws IllegalArgumentException if <code>bandOffsets</code> has zero
176 * length.
178 public ComponentSampleModel(int dataType,
179 int w, int h,
180 int pixelStride,
181 int scanlineStride,
182 int[] bankIndices,
183 int[] bandOffsets)
185 super(dataType, w, h, bandOffsets.length);
187 // super permits DataBuffer.TYPE_UNDEFINED but this class doesn't...
188 if (dataType == DataBuffer.TYPE_UNDEFINED)
189 throw new IllegalArgumentException("Unsupported dataType.");
191 if ((pixelStride < 0) || (scanlineStride < 0) || (bandOffsets.length < 1)
192 || (bandOffsets.length != bankIndices.length))
193 throw new IllegalArgumentException();
195 this.bandOffsets = (int[]) bandOffsets.clone();
196 this.bankIndices = (int[]) bankIndices.clone();
197 this.numBands = bandOffsets.length;
199 this.numBanks = 0;
200 for (int b = 0; b < bankIndices.length; b++)
201 this.numBanks = Math.max(this.numBanks, bankIndices[b] + 1);
203 this.scanlineStride = scanlineStride;
204 this.pixelStride = pixelStride;
206 // See if we can use some speedups
208 /* FIXME: May these checks should be reserved for the
209 PixelInterleavedSampleModel? */
211 if (pixelStride == numBands)
213 tightPixelPacking = true;
214 for (int b = 0; b < numBands; b++) {
215 if ((bandOffsets[b] != b) || (bankIndices[b] != 0))
217 tightPixelPacking = false;
218 break;
225 * Creates a new sample model that is compatible with this one, but with the
226 * specified dimensions.
228 * @param w the width (must be greater than zero).
229 * @param h the height (must be greater than zero).
231 * @return A new sample model.
233 public SampleModel createCompatibleSampleModel(int w, int h)
235 return new ComponentSampleModel(dataType, w, h, pixelStride,
236 scanlineStride, bankIndices,
237 bandOffsets);
241 * Creates a new sample model that provides access to a subset of the bands
242 * that this sample model supports.
244 * @param bands the bands (<code>null</code> not permitted).
246 * @return The new sample model.
248 public SampleModel createSubsetSampleModel(int[] bands)
250 int numBands = bands.length;
252 int[] bankIndices = new int[numBands];
253 int[] bandOffsets = new int[numBands];
254 for (int b = 0; b < numBands; b++)
256 bankIndices[b] = this.bankIndices[bands[b]];
257 bandOffsets[b] = this.bandOffsets[bands[b]];
260 return new ComponentSampleModel(dataType, width, height, pixelStride,
261 scanlineStride, bankIndices,
262 bandOffsets);
266 * Creates a new data buffer that is compatible with this sample model.
268 * @return The new data buffer.
270 public DataBuffer createDataBuffer()
272 // Maybe this value should be precalculated in the constructor?
273 int highestOffset = 0;
274 for (int b = 0; b < numBands; b++)
276 highestOffset = Math.max(highestOffset, bandOffsets[b]);
278 int size = pixelStride * (width - 1) + scanlineStride * (height - 1)
279 + highestOffset + 1;
281 return Buffers.createBuffer(getDataType(), size, numBanks);
285 * Returns the offset of the sample in band 0 for the pixel at location
286 * <code>(x, y)</code>. This offset can be used to read a sample value from
287 * a {@link DataBuffer}.
289 * @param x the x-coordinate.
290 * @param y the y-coordinate.
292 * @return The offset.
294 * @see #getOffset(int, int, int)
296 public int getOffset(int x, int y)
298 return getOffset(x, y, 0);
302 * Returns the offset of the sample in band <code>b</code> for the pixel at
303 * location <code>(x, y)</code>. This offset can be used to read a sample
304 * value from a {@link DataBuffer}.
306 * @param x the x-coordinate.
307 * @param y the y-coordinate.
308 * @param b the band index.
310 * @return The offset.
312 public int getOffset(int x, int y, int b)
314 return bandOffsets[b] + pixelStride * x + scanlineStride * y;
318 * Returns the size in bits for each sample (one per band). For this sample
319 * model, each band has the same sample size and this is determined by the
320 * data type for the sample model.
322 * @return The sample sizes.
324 * @see SampleModel#getDataType()
326 public final int[] getSampleSize()
328 int size = DataBuffer.getDataTypeSize(getDataType());
329 int[] sizes = new int[numBands];
331 java.util.Arrays.fill(sizes, size);
332 return sizes;
336 * Returns the size in bits for the samples in the specified band. In this
337 * class, the sample size is the same for every band and is determined from
338 * the data type for the model.
340 * @param band the band index (ignored here).
342 * @return The sample size in bits.
344 * @see SampleModel#getDataType()
346 public final int getSampleSize(int band)
348 return DataBuffer.getDataTypeSize(getDataType());
352 * Returns the indices of the bank(s) in the {@link DataBuffer} used to
353 * store the samples for each band. The returned array is a copy, so that
354 * altering it will not impact the sample model.
356 * @return The bank indices.
358 public final int[] getBankIndices()
360 return (int[]) bankIndices.clone();
364 * Returns the offsets to the first sample in each band. The returned array
365 * is a copy, so that altering it will not impact the sample model.
367 * @return The offsets.
369 public final int[] getBandOffsets()
371 return (int[]) bandOffsets.clone();
375 * Returns the distance (in terms of element indices) between the sample for
376 * one pixel and the corresponding sample for the equivalent pixel in the
377 * next row. This is used in the calculation of the element offset for
378 * retrieving samples from a {@link DataBuffer}.
380 * @return The distance between pixel samples in consecutive rows.
382 public final int getScanlineStride()
384 return scanlineStride;
388 * Returns the distance (in terms of element indices) between the sample for
389 * one pixel and the corresponding sample for the next pixel in a row. This
390 * is used in the calculation of the element offset for retrieving samples
391 * from a {@link DataBuffer}.
393 * @return The distance between pixel samples in the same row.
395 public final int getPixelStride()
397 return pixelStride;
401 * Returns the number of data elements used to store the samples for one
402 * pixel. In this model, this is the same as the number of bands.
404 * @return The number of data elements used to store the samples for one
405 * pixel.
407 public final int getNumDataElements()
409 return numBands;
413 * Returns the samples for the pixel at location <code>(x, y)</code> in
414 * a primitive array (the array type is determined by the data type for
415 * this model). The <code>obj</code> argument provides an option to supply
416 * an existing array to hold the result, if this is <code>null</code> a new
417 * array will be allocated.
419 * @param x the x-coordinate.
420 * @param y the y-coordinate.
421 * @param obj a primitive array that, if not <code>null</code>, will be
422 * used to store and return the sample values.
423 * @param data the data buffer (<code>null</code> not permitted).
425 * @return An array of sample values for the specified pixel.
427 public Object getDataElements(int x, int y, Object obj, DataBuffer data)
429 int xyOffset = pixelStride * x + scanlineStride * y;
431 int[] totalBandDataOffsets = new int[numBands];
433 /* Notice that band and bank offsets are different. Band offsets
434 are managed by the sample model, and bank offsets are managed
435 by the data buffer. Both must be accounted for. */
437 /* FIXME: For single pixels, it is probably easier to simple
438 call getElem instead of calculating the bank offset ourself.
440 On the other hand, then we need to push the value through
441 the int type returned by the getElem method. */
443 int[] bankOffsets = data.getOffsets();
445 for (int b = 0; b < numBands; b++)
447 totalBandDataOffsets[b] = bandOffsets[b] + bankOffsets[bankIndices[b]]
448 + xyOffset;
453 switch (getTransferType())
455 case DataBuffer.TYPE_BYTE:
456 DataBufferByte inByte = (DataBufferByte) data;
457 byte[] outByte = (byte[]) obj;
458 if (outByte == null)
459 outByte = new byte[numBands];
461 for (int b = 0; b < numBands; b++)
463 int dOffset = totalBandDataOffsets[b];
464 outByte[b] = inByte.getData(bankIndices[b])[dOffset];
466 return outByte;
468 case DataBuffer.TYPE_USHORT:
469 DataBufferUShort inUShort = (DataBufferUShort) data;
470 short[] outUShort = (short[]) obj;
471 if (outUShort == null)
472 outUShort = new short[numBands];
474 for (int b = 0; b < numBands; b++)
476 int dOffset = totalBandDataOffsets[b];
477 outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
479 return outUShort;
481 case DataBuffer.TYPE_SHORT:
482 DataBufferShort inShort = (DataBufferShort) data;
483 short[] outShort = (short[]) obj;
484 if (outShort == null)
485 outShort = new short[numBands];
487 for (int b = 0; b < numBands; b++)
489 int dOffset = totalBandDataOffsets[b];
490 outShort[b] = inShort.getData(bankIndices[b])[dOffset];
492 return outShort;
494 case DataBuffer.TYPE_INT:
495 DataBufferInt inInt = (DataBufferInt) data;
496 int[] outInt = (int[]) obj;
497 if (outInt == null)
498 outInt = new int[numBands];
500 for (int b = 0; b < numBands; b++)
502 int dOffset = totalBandDataOffsets[b];
503 outInt[b] = inInt.getData(bankIndices[b])[dOffset];
505 return outInt;
507 case DataBuffer.TYPE_FLOAT:
508 DataBufferFloat inFloat = (DataBufferFloat) data;
509 float[] outFloat = (float[]) obj;
510 if (outFloat == null)
511 outFloat = new float[numBands];
513 for (int b = 0; b < numBands; b++)
515 int dOffset = totalBandDataOffsets[b];
516 outFloat[b] = inFloat.getData(bankIndices[b])[dOffset];
518 return outFloat;
520 case DataBuffer.TYPE_DOUBLE:
521 DataBufferDouble inDouble = (DataBufferDouble) data;
522 double[] outDouble = (double[]) obj;
523 if (outDouble == null)
524 outDouble = new double[numBands];
526 for (int b = 0; b < numBands; b++)
528 int dOffset = totalBandDataOffsets[b];
529 outDouble[b] = inDouble.getData(bankIndices[b])[dOffset];
531 return outDouble;
533 default:
534 throw new IllegalStateException("unknown transfer type "
535 + getTransferType());
538 catch (ArrayIndexOutOfBoundsException aioobe)
540 String msg = "While reading data elements, " +
541 "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
542 ", data.getSize()=" + data.getSize() + ": " + aioobe;
543 throw new ArrayIndexOutOfBoundsException(msg);
548 * Returns the samples for the pixels in the region defined by
549 * <code>(x, y, w, h)</code> in a primitive array (the array type is
550 * determined by the data type for this model). The <code>obj</code>
551 * argument provides an option to supply an existing array to hold the
552 * result, if this is <code>null</code> a new array will be allocated.
554 * @param x the x-coordinate.
555 * @param y the y-coordinate.
556 * @param w the width.
557 * @param h the height.
558 * @param obj a primitive array that, if not <code>null</code>, will be
559 * used to store and return the sample values.
560 * @param data the data buffer (<code>null</code> not permitted).
562 * @return An array of sample values for the specified pixels.
564 * @see #setDataElements(int, int, int, int, Object, DataBuffer)
566 public Object getDataElements(int x, int y, int w, int h, Object obj,
567 DataBuffer data)
569 if (!tightPixelPacking)
571 return super.getDataElements(x, y, w, h, obj, data);
574 // using get speedup
576 // We can copy whole rows
577 int rowSize = w * numBands;
578 int dataSize = rowSize * h;
580 DataBuffer transferBuffer = Buffers.createBuffer(getTransferType(), obj,
581 dataSize);
582 obj = Buffers.getData(transferBuffer);
584 int inOffset = pixelStride * x + scanlineStride * y + data.getOffset();
585 // Assumes only one band is used
587 /* We don't add band offsets since we assume that bands have
588 offsets 0, 1, 2, ... */
590 // See if we can copy everything in one go
591 if (scanlineStride == rowSize)
593 // Collapse scan lines:
594 rowSize *= h;
595 // We ignore scanlineStride since it won't be of any use
596 h = 1;
599 int outOffset = 0;
600 Object inArray = Buffers.getData(data);
601 for (int yd = 0; yd < h; yd++)
603 System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
604 inOffset += scanlineStride;
605 outOffset += rowSize;
607 return obj;
611 * Sets the samples for the pixels in the region defined by
612 * <code>(x, y, w, h)</code> from a supplied primitive array (the array type
613 * must be consistent with the data type for this model).
615 * @param x the x-coordinate.
616 * @param y the y-coordinate.
617 * @param w the width.
618 * @param h the height.
619 * @param obj a primitive array containing the sample values.
620 * @param data the data buffer (<code>null</code> not permitted).
622 * @see #getDataElements(int, int, int, int, Object, DataBuffer)
624 public void setDataElements(int x, int y, int w, int h,
625 Object obj, DataBuffer data)
627 if (!tightPixelPacking)
629 super.setDataElements(x, y, w, h, obj, data);
630 return;
633 // using set speedup, we can copy whole rows
634 int rowSize = w * numBands;
635 int dataSize = rowSize * h;
637 DataBuffer transferBuffer
638 = Buffers.createBufferFromData(getTransferType(), obj, dataSize);
640 int[] bankOffsets = data.getOffsets();
642 int outOffset = pixelStride * x + scanlineStride * y + bankOffsets[0];
643 // same assumptions as in get...
645 // See if we can copy everything in one go
646 if (scanlineStride == rowSize)
648 // Collapse scan lines:
649 rowSize *= h;
650 h = 1;
653 int inOffset = 0;
654 Object outArray = Buffers.getData(data);
655 for (int yd = 0; yd < h; yd++)
657 System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
658 outOffset += scanlineStride;
659 inOffset += rowSize;
664 * Returns all the samples for the pixel at location <code>(x, y)</code>
665 * stored in the specified data buffer.
667 * @param x the x-coordinate.
668 * @param y the y-coordinate.
669 * @param iArray an array that will be populated with the sample values and
670 * returned as the result. The size of this array should be equal to the
671 * number of bands in the model. If the array is <code>null</code>, a new
672 * array is created.
673 * @param data the data buffer (<code>null</code> not permitted).
675 * @return The samples for the specified pixel.
677 * @see #setPixel(int, int, int[], DataBuffer)
679 public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
681 int offset = pixelStride * x + scanlineStride * y;
682 if (iArray == null)
683 iArray = new int[numBands];
684 for (int b = 0; b < numBands; b++)
686 iArray[b] = data.getElem(bankIndices[b], offset + bandOffsets[b]);
688 return iArray;
692 * Returns the samples for all the pixels in a rectangular region.
694 * @param x the x-coordinate.
695 * @param y the y-coordinate.
696 * @param w the width.
697 * @param h the height.
698 * @param iArray an array that if non-<code>null</code> will be populated
699 * with the sample values and returned as the result.
700 * @param data the data buffer (<code>null</code> not permitted).
702 * @return The samples for all the pixels in the rectangle.
704 public int[] getPixels(int x, int y, int w, int h, int[] iArray,
705 DataBuffer data)
707 int offset = pixelStride * x + scanlineStride * y;
708 if (iArray == null)
709 iArray = new int[numBands * w * h];
710 int outOffset = 0;
711 for (y = 0; y < h; y++)
713 int lineOffset = offset;
714 for (x = 0; x < w; x++)
716 for (int b = 0; b < numBands; b++)
718 iArray[outOffset++]
719 = data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
721 lineOffset += pixelStride;
723 offset += scanlineStride;
725 return iArray;
729 * Returns the sample for band <code>b</code> of the pixel at
730 * <code>(x, y)</code> that is stored in the specified data buffer.
732 * @param x the x-coordinate.
733 * @param y the y-coordinate.
734 * @param b the band index.
735 * @param data the data buffer (<code>null</code> not permitted).
737 * @return The sample value.
739 * @see #setSample(int, int, int, int, DataBuffer)
741 public int getSample(int x, int y, int b, DataBuffer data)
743 return data.getElem(bankIndices[b], getOffset(x, y, b));
747 * Sets the samples for the pixel at location <code>(x, y)</code> from the
748 * supplied primitive array (the array type must be consistent with the data
749 * type for this model).
751 * @param x the x-coordinate.
752 * @param y the y-coordinate.
753 * @param obj a primitive array containing the pixel's sample values.
754 * @param data the data buffer (<code>null</code> not permitted).
756 * @see #setDataElements(int, int, Object, DataBuffer)
758 public void setDataElements(int x, int y, Object obj, DataBuffer data)
760 int offset = pixelStride * x + scanlineStride * y;
761 int[] totalBandDataOffsets = new int[numBands];
762 int[] bankOffsets = data.getOffsets();
763 for (int b = 0; b < numBands; b++)
764 totalBandDataOffsets[b] = bandOffsets[b] + bankOffsets[bankIndices[b]]
765 + offset;
767 switch (getTransferType())
769 case DataBuffer.TYPE_BYTE:
771 DataBufferByte out = (DataBufferByte) data;
772 byte[] in = (byte[]) obj;
774 for (int b = 0; b < numBands; b++)
775 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
777 return;
779 case DataBuffer.TYPE_USHORT:
781 DataBufferUShort out = (DataBufferUShort) data;
782 short[] in = (short[]) obj;
784 for (int b = 0; b < numBands; b++)
785 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
787 return;
789 case DataBuffer.TYPE_SHORT:
791 DataBufferShort out = (DataBufferShort) data;
792 short[] in = (short[]) obj;
794 for (int b = 0; b < numBands; b++)
795 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
797 return;
799 case DataBuffer.TYPE_INT:
801 DataBufferInt out = (DataBufferInt) data;
802 int[] in = (int[]) obj;
804 for (int b = 0; b < numBands; b++)
805 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
807 return;
809 case DataBuffer.TYPE_FLOAT:
811 DataBufferFloat out = (DataBufferFloat) data;
812 float[] in = (float[]) obj;
814 for (int b = 0; b < numBands; b++)
815 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
817 return;
819 case DataBuffer.TYPE_DOUBLE:
821 DataBufferDouble out = (DataBufferDouble) data;
822 double[] in = (double[]) obj;
824 for (int b = 0; b < numBands; b++)
825 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
827 return;
829 default:
830 throw new UnsupportedOperationException("transfer type not " +
831 "implemented");
836 * Sets the sample values for the pixel at location <code>(x, y)</code>
837 * stored in the specified data buffer.
839 * @param x the x-coordinate.
840 * @param y the y-coordinate.
841 * @param iArray the pixel sample values (<code>null</code> not permitted).
842 * @param data the data buffer (<code>null</code> not permitted).
844 * @see #getPixel(int, int, int[], DataBuffer)
846 public void setPixel(int x, int y, int[] iArray, DataBuffer data)
848 int offset = pixelStride * x + scanlineStride * y;
849 for (int b = 0; b < numBands; b++)
850 data.setElem(bankIndices[b], offset + bandOffsets[b], iArray[b]);
854 * Sets the sample value for band <code>b</code> of the pixel at location
855 * <code>(x, y)</code> in the specified data buffer.
857 * @param x the x-coordinate.
858 * @param y the y-coordinate.
859 * @param b the band index.
860 * @param s the sample value.
861 * @param data the data buffer (<code>null</code> not permitted).
863 * @see #getSample(int, int, int, DataBuffer)
865 public void setSample(int x, int y, int b, int s, DataBuffer data)
867 data.setElem(bankIndices[b], getOffset(x, y, b), s);
871 * Tests this sample model for equality with an arbitrary object. Returns
872 * <code>true</code> if and only if:
873 * <ul>
874 * <li><code>obj</code> is not <code>null</code>;</li>
875 * <li><code>obj</code> is an instance of <code>ComponentSampleModel</code>;
876 * </li>
877 * <li>both models have the same values for the <code>dataType</code>,
878 * <code>width</code>, <code>height</code>, <code>pixelStride</code>,
879 * <code>scanlineStride</code>, <code>bandOffsets</code> and
880 * <code>bankIndices</code> fields.</li>
881 * </ul>
883 * @param obj the object to test (<code>null</code> permitted).
885 * @return <code>true</code> if this sample model is equal to
886 * <code>obj</code>, and <code>false</code> otherwise.
888 public boolean equals(Object obj)
890 if (obj == null)
891 return false;
892 if (! (obj instanceof ComponentSampleModel))
893 return false;
894 ComponentSampleModel that = (ComponentSampleModel) obj;
895 if (this.dataType != that.dataType)
896 return false;
897 if (this.width != that.width)
898 return false;
899 if (this.height != that.height)
900 return false;
901 if (this.pixelStride != that.pixelStride)
902 return false;
903 if (this.scanlineStride != that.scanlineStride)
904 return false;
905 if (! Arrays.equals(this.bandOffsets, that.bandOffsets))
906 return false;
907 if (! Arrays.equals(this.bankIndices, that.bankIndices))
908 return false;
909 // couldn't find any difference, so...
910 return true;
914 * Returns a hash code for this sample model.
916 * @return The hash code.
918 public int hashCode()
920 // this computation is based on the method described in Chapter 3
921 // of Joshua Bloch's Effective Java...
922 int result = 17;
923 result = 37 * result + dataType;
924 result = 37 * result + width;
925 result = 37 * result + height;
926 result = 37 * result + pixelStride;
927 result = 37 * result + scanlineStride;
928 for (int i = 0; i < bandOffsets.length; i++)
929 result = 37 * result + bandOffsets[i];
930 for (int i = 0; i < bankIndices.length; i++)
931 result = 37 * result + bankIndices[i];
932 return result;