KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > image > ComponentSampleModel


1 /*
2  * @(#)ComponentSampleModel.java 1.44 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 /* ****************************************************************
9  ******************************************************************
10  ******************************************************************
11  *** COPYRIGHT (c) Eastman Kodak Company, 1997
12  *** As an unpublished work pursuant to Title 17 of the United
13  *** States Code. All rights reserved.
14  ******************************************************************
15  ******************************************************************
16  ******************************************************************/

17
18 package java.awt.image;
19
20 import java.util.Arrays JavaDoc;
21
22 /**
23  * This class represents image data which is stored such that each sample
24  * of a pixel occupies one data element of the DataBuffer. It stores the
25  * N samples which make up a pixel in N separate data array elements.
26  * Different bands may be in different banks of the DataBuffer.
27  * Accessor methods are provided so that image data can be manipulated
28  * directly. This class can support different kinds of interleaving, e.g.
29  * band interleaving, scanline interleaving, and pixel interleaving.
30  * Pixel stride is the number of data array elements between two samples
31  * for the same band on the same scanline. Scanline stride is the number
32  * of data array elements between a given sample and the corresponding sample
33  * in the same column of the next scanline. Band offsets denote the number
34  * of data array elements from the first data array element of the bank
35  * of the DataBuffer holding each band to the first sample of the band.
36  * The bands are numbered from 0 to N-1. This class can represent image
37  * data for which each sample is an unsigned integral number which can be
38  * stored in 8, 16, or 32 bits (using <code>DataBuffer.TYPE_BYTE</code>,
39  * <code>DataBuffer.TYPE_USHORT</code>, or <code>DataBuffer.TYPE_INT</code>,
40  * respectively), data for which each sample is a signed integral number
41  * which can be stored in 16 bits (using <code>DataBuffer.TYPE_SHORT</code>),
42  * or data for which each sample is a signed float or double quantity
43  * (using <code>DataBuffer.TYPE_FLOAT</code> or
44  * <code>DataBuffer.TYPE_DOUBLE</code>, respectively).
45  * All samples of a given ComponentSampleModel
46  * are stored with the same precision. All strides and offsets must be
47  * non-negative. This class supports
48  * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
49  * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
50  * {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
51  * {@link DataBuffer#TYPE_INT TYPE_INT},
52  * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT},
53  * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE},
54  * @see java.awt.image.PixelInterleavedSampleModel
55  * @see java.awt.image.BandedSampleModel
56  */

57
58 public class ComponentSampleModel extends SampleModel JavaDoc
59 {
60     /** Offsets for all bands in data array elements. */
61     protected int bandOffsets[];
62
63     /** Index for each bank storing a band of image data. */
64     protected int[] bankIndices;
65
66     /**
67      * The number of bands in this
68      * <code>ComponentSampleModel</code>.
69      */

70     protected int numBands = 1;
71
72     /**
73      * The number of banks in this
74      * <code>ComponentSampleModel</code>.
75      */

76     protected int numBanks = 1;
77
78     /**
79      * Line stride (in data array elements) of the region of image
80      * data described by this ComponentSampleModel.
81      */

82     protected int scanlineStride;
83
84     /** Pixel stride (in data array elements) of the region of image
85      * data described by this ComponentSampleModel.
86      */

87     protected int pixelStride;
88
89     static private native void initIDs();
90     static {
91         ColorModel.loadLibraries();
92         initIDs();
93     }
94
95     /**
96      * Constructs a ComponentSampleModel with the specified parameters.
97      * The number of bands will be given by the length of the bandOffsets array.
98      * All bands will be stored in the first bank of the DataBuffer.
99      * @param dataType the data type for storing samples
100      * @param w the width (in pixels) of the region of
101      * image data described
102      * @param h the height (in pixels) of the region of
103      * image data described
104      * @param pixelStride the pixel stride of the region of image
105      * data described
106      * @param scanlineStride the line stride of the region of image
107      * data described
108      * @param bandOffsets the offsets of all bands
109      * @throws IllegalArgumentException if <code>w</code> or
110      * <code>h</code> is not greater than 0
111      * @throws IllegalArgumentException if <code>pixelStride</code>
112      * is less than 0
113      * @throws IllegalArgumentException if <code>scanlineStride</code>
114      * is less than 0
115      * @throws IllegalArgumentException if <code>numBands</code>
116      * is less than 1
117      * @throws IllegalArgumentException if the product of <code>w</code>
118      * and <code>h</code> is greater than
119      * <code>Integer.MAX_VALUE</code>
120      * @throws IllegalArgumentException if <code>dataType</code> is not
121      * one of the supported data types
122      */

123     public ComponentSampleModel(int dataType,
124                                 int w, int h,
125                                 int pixelStride,
126                                 int scanlineStride,
127                                 int bandOffsets[]) {
128     super(dataType, w, h, bandOffsets.length);
129     this.dataType = dataType;
130     this.pixelStride = pixelStride;
131     this.scanlineStride = scanlineStride;
132     this.bandOffsets = (int[])bandOffsets.clone();
133         numBands = bandOffsets.length;
134         if (pixelStride < 0) {
135             throw new IllegalArgumentException JavaDoc("Pixel stride must be >= 0");
136         }
137         // TODO - bug 4296691 - remove this check
138
if (scanlineStride < 0) {
139             throw new IllegalArgumentException JavaDoc("Scanline stride must be >= 0");
140         }
141         if (numBands < 1) {
142             throw new IllegalArgumentException JavaDoc("Must have at least one band.");
143         }
144         if ((dataType < DataBuffer.TYPE_BYTE) ||
145             (dataType > DataBuffer.TYPE_DOUBLE)) {
146             throw new IllegalArgumentException JavaDoc("Unsupported dataType.");
147         }
148     bankIndices = new int[numBands];
149     for (int i=0; i<numBands; i++) {
150         bankIndices[i] = 0;
151         }
152     }
153
154
155     /**
156      * Constructs a ComponentSampleModel with the specified parameters.
157      * The number of bands will be given by the length of the bandOffsets array.
158      * Different bands may be stored in different banks of the DataBuffer.
159      *
160      * @param dataType the data type for storing samples
161      * @param w the width (in pixels) of the region of
162      * image data described
163      * @param h the height (in pixels) of the region of
164      * image data described
165      * @param pixelStride the pixel stride of the region of image
166      * data described
167      * @param scanlineStride The line stride of the region of image
168      * data described
169      * @param bankIndices the bank indices of all bands
170      * @param bandOffsets the band offsets of all bands
171      * @throws IllegalArgumentException if <code>w</code> or
172      * <code>h</code> is not greater than 0
173      * @throws IllegalArgumentException if <code>pixelStride</code>
174      * is less than 0
175      * @throws IllegalArgumentException if <code>scanlineStride</code>
176      * is less than 0
177      * @throws IllegalArgumentException if the length of
178      * <code>bankIndices</code> does not equal the length of
179      * <code>bankOffsets</code>
180      * @throws IllegalArgumentException if any of the bank indices
181      * of <code>bandIndices</code> is less than 0
182      * @throws IllegalArgumentException if <code>dataType</code> is not
183      * one of the supported data types
184      */

185     public ComponentSampleModel(int dataType,
186                                 int w, int h,
187                                 int pixelStride,
188                                 int scanlineStride,
189                                 int bankIndices[],
190                                 int bandOffsets[]) {
191         super(dataType, w, h, bandOffsets.length);
192     this.dataType = dataType;
193     this.pixelStride = pixelStride;
194     this.scanlineStride = scanlineStride;
195     this.bandOffsets = (int[])bandOffsets.clone();
196         this.bankIndices = (int[]) bankIndices.clone();
197         if (pixelStride < 0) {
198             throw new IllegalArgumentException JavaDoc("Pixel stride must be >= 0");
199         }
200         // TODO - bug 4296691 - remove this check
201
if (scanlineStride < 0) {
202             throw new IllegalArgumentException JavaDoc("Scanline stride must be >= 0");
203         }
204         if ((dataType < DataBuffer.TYPE_BYTE) ||
205             (dataType > DataBuffer.TYPE_DOUBLE)) {
206             throw new IllegalArgumentException JavaDoc("Unsupported dataType.");
207         }
208         int maxBank = bankIndices[0];
209         if (maxBank < 0) {
210             throw new IllegalArgumentException JavaDoc("Index of bank 0 is less than "+
211                                                "0 ("+maxBank+")");
212         }
213         for (int i=1; i < bankIndices.length; i++) {
214             if (bankIndices[i] > maxBank) {
215                 maxBank = bankIndices[i];
216             }
217             else if (bankIndices[i] < 0) {
218                 throw new IllegalArgumentException JavaDoc("Index of bank "+i+
219                                                    " is less than 0 ("+
220                                                    maxBank+")");
221             }
222         }
223         numBanks = maxBank+1;
224         numBands = bandOffsets.length;
225         if (bandOffsets.length != bankIndices.length) {
226             throw new IllegalArgumentException JavaDoc("Length of bandOffsets must "+
227                                                "equal length of bankIndices.");
228         }
229     }
230
231     /**
232      * Returns the size of the data buffer (in data elements) needed
233      * for a data buffer that matches this ComponentSampleModel.
234      */

235      private long getBufferSize() {
236          int maxBandOff=bandOffsets[0];
237          for (int i=1; i<bandOffsets.length; i++)
238              maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
239
240          long size = 0;
241          if (maxBandOff >= 0)
242              size += maxBandOff+1;
243          if (pixelStride > 0)
244              size += pixelStride * (width-1);
245          if (scanlineStride > 0)
246              size += scanlineStride*(height-1);
247          return size;
248      }
249
250      /**
251       * Preserves band ordering with new step factor...
252       */

253     int []orderBands(int orig[], int step) {
254         int map[] = new int[orig.length];
255         int ret[] = new int[orig.length];
256
257         for (int i=0; i<map.length; i++) map[i] = i;
258
259         for (int i = 0; i < ret.length; i++) {
260             int index = i;
261             for (int j = i+1; j < ret.length; j++) {
262                 if (orig[map[index]] > orig[map[j]]) {
263                     index = j;
264                 }
265             }
266             ret[map[index]] = i*step;
267             map[index] = map[i];
268         }
269         return ret;
270     }
271
272     /**
273      * Creates a new <code>ComponentSampleModel</code> with the specified
274      * width and height. The new <code>SampleModel</code> will have the same
275      * number of bands, storage data type, interleaving scheme, and
276      * pixel stride as this <code>SampleModel</code>.
277      * @param w the width of the resulting <code>SampleModel</code>
278      * @param h the height of the resulting <code>SampleModel</code>
279      * @return a new <code>ComponentSampleModel</code> with the specified size
280      * @throws IllegalArgumentException if <code>w</code> or
281      * <code>h</code> is not greater than 0
282      */

283     public SampleModel JavaDoc createCompatibleSampleModel(int w, int h) {
284         SampleModel JavaDoc ret=null;
285         long size;
286         int minBandOff=bandOffsets[0];
287         int maxBandOff=bandOffsets[0];
288         for (int i=1; i<bandOffsets.length; i++) {
289             minBandOff = Math.min(minBandOff,bandOffsets[i]);
290             maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
291         }
292         maxBandOff -= minBandOff;
293
294         int bands = bandOffsets.length;
295         int bandOff[];
296         int pStride = Math.abs(pixelStride);
297         int lStride = Math.abs(scanlineStride);
298         int bStride = Math.abs(maxBandOff);
299
300         if (pStride > lStride) {
301             if (pStride > bStride) {
302                 if (lStride > bStride) { // pix > line > band
303
bandOff = new int[bandOffsets.length];
304                     for (int i=0; i<bands; i++)
305                         bandOff[i] = bandOffsets[i]-minBandOff;
306                     lStride = bStride+1;
307                     pStride = lStride*h;
308                 } else { // pix > band > line
309
bandOff = orderBands(bandOffsets,lStride*h);
310                     pStride = bands*lStride*h;
311                 }
312             } else { // band > pix > line
313
pStride = lStride*h;
314                 bandOff = orderBands(bandOffsets,pStride*w);
315             }
316         } else {
317             if (pStride > bStride) { // line > pix > band
318
bandOff = new int[bandOffsets.length];
319                 for (int i=0; i<bands; i++)
320                     bandOff[i] = bandOffsets[i]-minBandOff;
321                 pStride = bStride+1;
322                 lStride = pStride*w;
323             } else {
324                 if (lStride > bStride) { // line > band > pix
325
bandOff = orderBands(bandOffsets,pStride*w);
326                     lStride = bands*pStride*w;
327                 } else { // band > line > pix
328
lStride = pStride*w;
329                     bandOff = orderBands(bandOffsets,lStride*h);
330                 }
331             }
332         }
333
334         // make sure we make room for negative offsets...
335
int base = 0;
336         if (scanlineStride < 0) {
337             base += lStride*h;
338             lStride *= -1;
339         }
340         if (pixelStride < 0) {
341             base += pStride*w;
342             pStride *= -1;
343         }
344
345         for (int i=0; i<bands; i++)
346             bandOff[i] += base;
347         return new ComponentSampleModel JavaDoc(dataType, w, h, pStride,
348                                         lStride, bankIndices, bandOff);
349     }
350
351     /**
352      * Creates a new ComponentSampleModel with a subset of the bands
353      * of this ComponentSampleModel. The new ComponentSampleModel can be
354      * used with any DataBuffer that the existing ComponentSampleModel
355      * can be used with. The new ComponentSampleModel/DataBuffer
356      * combination will represent an image with a subset of the bands
357      * of the original ComponentSampleModel/DataBuffer combination.
358      * @param bands a subset of bands from this
359      * <code>ComponentSampleModel</code>
360      * @return a <code>ComponentSampleModel</code> created with a subset
361      * of bands from this <code>ComponentSampleModel</code>.
362      */

363     public SampleModel JavaDoc createSubsetSampleModel(int bands[]) {
364        if (bands.length > bankIndices.length)
365             throw new RasterFormatException JavaDoc("There are only " +
366                                             bankIndices.length +
367                                             " bands");
368         int newBankIndices[] = new int[bands.length];
369         int newBandOffsets[] = new int[bands.length];
370
371         for (int i=0; i<bands.length; i++) {
372             newBankIndices[i] = bankIndices[bands[i]];
373             newBandOffsets[i] = bandOffsets[bands[i]];
374         }
375
376         return new ComponentSampleModel JavaDoc(this.dataType, width, height,
377                                         this.pixelStride,
378                                         this.scanlineStride,
379                                         newBankIndices, newBandOffsets);
380     }
381
382     /**
383      * Creates a <code>DataBuffer</code> that corresponds to this
384      * <code>ComponentSampleModel</code>.
385      * The <code>DataBuffer</code> object's data type, number of banks,
386      * and size are be consistent with this <code>ComponentSampleModel</code>.
387      * @return a <code>DataBuffer</code> whose data type, number of banks
388      * and size are consistent with this
389      * <code>ComponentSampleModel</code>.
390      */

391     public DataBuffer JavaDoc createDataBuffer() {
392         DataBuffer JavaDoc dataBuffer = null;
393
394         int size = (int)getBufferSize();
395         switch (dataType) {
396         case DataBuffer.TYPE_BYTE:
397             dataBuffer = new DataBufferByte JavaDoc(size, numBanks);
398             break;
399         case DataBuffer.TYPE_USHORT:
400             dataBuffer = new DataBufferUShort JavaDoc(size, numBanks);
401             break;
402         case DataBuffer.TYPE_SHORT:
403             dataBuffer = new DataBufferShort JavaDoc(size, numBanks);
404             break;
405         case DataBuffer.TYPE_INT:
406             dataBuffer = new DataBufferInt JavaDoc(size, numBanks);
407             break;
408         case DataBuffer.TYPE_FLOAT:
409             dataBuffer = new DataBufferFloat JavaDoc(size, numBanks);
410             break;
411         case DataBuffer.TYPE_DOUBLE:
412             dataBuffer = new DataBufferDouble JavaDoc(size, numBanks);
413             break;
414         }
415
416         return dataBuffer;
417     }
418
419
420     /** Gets the offset for the first band of pixel (x,y).
421      * A sample of the first band can be retrieved from a
422      * <code>DataBuffer</code>
423      * <code>data</code> with a <code>ComponentSampleModel</code>
424      * <code>csm</code> as
425      * <pre>
426      * data.getElem(csm.getOffset(x, y));
427      * </pre>
428      * @param x,&nbsp;y the location of the pixel
429      * @return the offset for the first band of the specified pixel.
430      */

431     public int getOffset(int x, int y) {
432         int offset = y*scanlineStride + x*pixelStride + bandOffsets[0];
433         return offset;
434     }
435  
436     /** Gets the offset for band b of pixel (x,y).
437      * A sample of band <code>b</code> can be retrieved from a
438      * <code>DataBuffer</code> <code>data</code>
439      * with a <code>ComponentSampleModel</code> <code>csm</code> as
440      * <pre>
441      * data.getElem(csm.getOffset(x, y, b));
442      * </pre>
443      * @param x,&nbsp;y the location of the specified pixel
444      * @param b the specified band
445      * @return the offset for the specified band of the specified pixel.
446      */

447     public int getOffset(int x, int y, int b) {
448         int offset = y*scanlineStride + x*pixelStride + bandOffsets[b];
449         return offset;
450     }
451  
452     /** Returns the number of bits per sample for all bands.
453      * @return an array containing the number of bits per sample
454      * for all bands, where each element in the array
455      * represents a band.
456      */

457     public final int[] getSampleSize() {
458         int sampleSize[] = new int [numBands];
459         int sizeInBits = getSampleSize(0);
460
461         for (int i=0; i<numBands; i++)
462             sampleSize[i] = sizeInBits;
463
464         return sampleSize;
465     }
466
467     /** Returns the number of bits per sample for the specified band.
468      * @param band the specified band
469      * @return the number of bits per sample for the specified band.
470      */

471     public final int getSampleSize(int band) {
472         return DataBuffer.getDataTypeSize(dataType);
473     }
474
475     /** Returns the bank indices for all bands.
476      * @return the bank indices for all bands.
477      */

478     public final int [] getBankIndices() {
479         return (int[]) bankIndices.clone();
480     }
481
482     /** Returns the band offset for all bands.
483      * @return the band offsets for all bands.
484      */

485     public final int [] getBandOffsets() {
486         return (int[])bandOffsets.clone();
487     }
488
489     /** Returns the scanline stride of this ComponentSampleModel.
490      * @return the scanline stride of this <code>ComponentSampleModel</code>.
491      */

492     public final int getScanlineStride() {
493         return scanlineStride;
494     }
495
496     /** Returns the pixel stride of this ComponentSampleModel.
497      * @return the pixel stride of this <code>ComponentSampleModel</code>.
498      */

499     public final int getPixelStride() {
500         return pixelStride;
501     }
502
503     /**
504      * Returns the number of data elements needed to transfer a pixel
505      * with the
506      * {@link #getDataElements(int, int, Object, DataBuffer) } and
507      * {@link #setDataElements(int, int, Object, DataBuffer) }
508      * methods.
509      * For a <code>ComponentSampleModel</code>, this is identical to the
510      * number of bands.
511      * @return the number of data elements needed to transfer a pixel with
512      * the <code>getDataElements</code> and
513      * <code>setDataElements</code> methods.
514      * @see java.awt.image.SampleModel#getNumDataElements
515      * @see #getNumBands
516      */

517     public final int getNumDataElements() {
518     return getNumBands();
519     }
520
521     /**
522      * Returns data for a single pixel in a primitive array of type
523      * <code>TransferType</code>. For a <code>ComponentSampleModel</code>,
524      * this is the same as the data type, and samples are returned
525      * one per array element. Generally, <code>obj</code> should
526      * be passed in as <code>null</code>, so that the <code>Object</code>
527      * is created automatically and is the right primitive data type.
528      * <p>
529      * The following code illustrates transferring data for one pixel from
530      * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
531      * described by <code>ComponentSampleModel</code> <code>csm1</code>,
532      * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
533      * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
534      * The transfer is usually more efficient than using
535      * <code>getPixel</code> and <code>setPixel</code>.
536      * <pre>
537      * ComponentSampleModel csm1, csm2;
538      * DataBufferInt db1, db2;
539      * csm2.setDataElements(x, y,
540      * csm1.getDataElements(x, y, null, db1), db2);
541      * </pre>
542      *
543      * Using <code>getDataElements</code> and <code>setDataElements</code>
544      * to transfer between two <code>DataBuffer/SampleModel</code>
545      * pairs is legitimate if the <code>SampleModel</code> objects have
546      * the same number of bands, corresponding bands have the same number of
547      * bits per sample, and the <code>TransferType</code>s are the same.
548      * <p>
549      * If <code>obj</code> is not <code>null</code>, it should be a
550      * primitive array of type <code>TransferType</code>.
551      * Otherwise, a <code>ClassCastException</code> is thrown. An
552      * <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
553      * coordinates are not in bounds, or if <code>obj</code> is not
554      * <code>null</code> and is not large enough to hold
555      * the pixel data.
556      *
557      * @param x,&nbsp;y the coordinates of the pixel location
558      * @param obj if non-<code>null</code>, a primitive array
559      * in which to return the pixel data
560      * @param data the <code>DataBuffer</code> containing the image data
561      * @return the data of the specified pixel
562      * @see #setDataElements(int, int, Object, DataBuffer)
563      *
564      * @throws NullPointerException if data is null.
565      * @throws ArrayIndexOutOfBoundsException if the coordinates are
566      * not in bounds, or if obj is too small to hold the ouput.
567      */

568     public Object JavaDoc getDataElements(int x, int y, Object JavaDoc obj, DataBuffer JavaDoc data) {
569         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
570             throw new ArrayIndexOutOfBoundsException JavaDoc
571                 ("Coordinate out of bounds!");
572         }
573
574     int type = getTransferType();
575     int numDataElems = getNumDataElements();
576     int pixelOffset = y*scanlineStride + x*pixelStride;
577
578     switch(type) {
579
580     case DataBuffer.TYPE_BYTE:
581
582         byte[] bdata;
583
584         if (obj == null)
585         bdata = new byte[numDataElems];
586         else
587         bdata = (byte[])obj;
588
589         for (int i=0; i<numDataElems; i++) {
590         bdata[i] = (byte)data.getElem(bankIndices[i],
591                                               pixelOffset + bandOffsets[i]);
592         }
593
594         obj = (Object JavaDoc)bdata;
595         break;
596
597     case DataBuffer.TYPE_USHORT:
598         case DataBuffer.TYPE_SHORT:
599             
600         short[] sdata;
601
602         if (obj == null)
603         sdata = new short[numDataElems];
604         else
605         sdata = (short[])obj;
606
607         for (int i=0; i<numDataElems; i++) {
608         sdata[i] = (short)data.getElem(bankIndices[i],
609                                                pixelOffset + bandOffsets[i]);
610         }
611
612         obj = (Object JavaDoc)sdata;
613         break;
614
615     case DataBuffer.TYPE_INT:
616
617         int[] idata;
618
619         if (obj == null)
620         idata = new int[numDataElems];
621         else
622         idata = (int[])obj;
623
624         for (int i=0; i<numDataElems; i++) {
625         idata[i] = data.getElem(bankIndices[i],
626                                         pixelOffset + bandOffsets[i]);
627         }
628
629         obj = (Object JavaDoc)idata;
630         break;
631
632     case DataBuffer.TYPE_FLOAT:
633
634         float[] fdata;
635
636         if (obj == null)
637         fdata = new float[numDataElems];
638         else
639         fdata = (float[])obj;
640
641         for (int i=0; i<numDataElems; i++) {
642         fdata[i] = data.getElemFloat(bankIndices[i],
643                                              pixelOffset + bandOffsets[i]);
644         }
645
646         obj = (Object JavaDoc)fdata;
647         break;
648
649     case DataBuffer.TYPE_DOUBLE:
650
651         double[] ddata;
652
653         if (obj == null)
654         ddata = new double[numDataElems];
655         else
656         ddata = (double[])obj;
657
658         for (int i=0; i<numDataElems; i++) {
659         ddata[i] = data.getElemDouble(bankIndices[i],
660                                               pixelOffset + bandOffsets[i]);
661         }
662
663         obj = (Object JavaDoc)ddata;
664         break;
665         }
666         
667     return obj;
668     }
669
670     /**
671      * Returns all samples for the specified pixel in an int array,
672      * one sample per array element.
673      * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
674      * the coordinates are not in bounds.
675      * @param x,&nbsp;y The coordinates of the pixel location
676      * @param iArray If non-null, returns the samples in this array
677      * @param data The DataBuffer containing the image data
678      * @return the samples of the specified pixel.
679      * @see #setPixel(int, int, int[], DataBuffer)
680      *
681      * @throws NullPointerException if data is null.
682      * @throws ArrayIndexOutOfBoundsException if the coordinates are
683      * not in bounds, or if iArray is too small to hold the output.
684      */

685     public int[] getPixel(int x, int y, int iArray[], DataBuffer JavaDoc data) {
686         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
687             throw new ArrayIndexOutOfBoundsException JavaDoc
688                 ("Coordinate out of bounds!");
689         }
690         int pixels[];
691         if (iArray != null) {
692            pixels = iArray;
693         } else {
694            pixels = new int [numBands];
695         }
696         int pixelOffset = y*scanlineStride + x*pixelStride;
697         for (int i=0; i<numBands; i++) {
698             pixels[i] = data.getElem(bankIndices[i],
699                                      pixelOffset + bandOffsets[i]);
700         }
701         return pixels;
702     }
703
704     /**
705      * Returns all samples for the specified rectangle of pixels in
706      * an int array, one sample per array element.
707      * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
708      * the coordinates are not in bounds.
709      * @param x,&nbsp;y the coordinates of the upper left pixel location
710      * @param w The width of the pixel rectangle
711      * @param h The height of the pixel rectangle
712      * @param iArray If non-null, returns the samples in this array
713      * @param data The DataBuffer containing the image data
714      * @return the samples of the pixels within the specified region.
715      * @see #setPixels(int, int, int, int, int[], DataBuffer)
716      */

717     public int[] getPixels(int x, int y, int w, int h,
718                            int iArray[], DataBuffer JavaDoc data) {
719         if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
720             throw new ArrayIndexOutOfBoundsException JavaDoc
721                 ("Coordinate out of bounds!");
722         }
723         int pixels[];
724         if (iArray != null) {
725            pixels = iArray;
726         } else {
727            pixels = new int [w*h*numBands];
728         }
729         int lineOffset = y*scanlineStride + x*pixelStride;
730         int srcOffset = 0;
731
732         for (int i = 0; i < h; i++) {
733            int pixelOffset = lineOffset;
734            for (int j = 0; j < w; j++) {
735               for (int k=0; k < numBands; k++) {
736                  pixels[srcOffset++] =
737                     data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]);
738               }
739               pixelOffset += pixelStride;
740            }
741            lineOffset += scanlineStride;
742         }
743         return pixels;
744     }
745
746     /**
747      * Returns as int the sample in a specified band for the pixel
748      * located at (x,y).
749      * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
750      * the coordinates are not in bounds.
751      * @param x,&nbsp;y the coordinates of the pixel location
752      * @param b the band to return
753      * @param data the <code>DataBuffer</code> containing the image data
754      * @return the sample in a specified band for the specified pixel
755      * @see #setSample(int, int, int, int, DataBuffer)
756      */

757     public int getSample(int x, int y, int b, DataBuffer JavaDoc data) {
758         // Bounds check for 'b' will be performed automatically
759
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
760             throw new ArrayIndexOutOfBoundsException JavaDoc
761                 ("Coordinate out of bounds!");
762         }
763         int sample = data.getElem(bankIndices[b],
764                                   y*scanlineStride + x*pixelStride +
765                                   bandOffsets[b]);
766         return sample;
767     }
768
769     /**
770      * Returns the sample in a specified band
771      * for the pixel located at (x,y) as a float.
772      * An <code>ArrayIndexOutOfBoundsException</code> might be
773      * thrown if the coordinates are not in bounds.
774      * @param x,&nbsp;y The coordinates of the pixel location
775      * @param b The band to return
776      * @param data The DataBuffer containing the image data
777      * @return a float value representing the sample in the specified
778      * band for the specified pixel.
779      */

780     public float getSampleFloat(int x, int y, int b, DataBuffer JavaDoc data) {
781         // Bounds check for 'b' will be performed automatically
782
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
783             throw new ArrayIndexOutOfBoundsException JavaDoc
784                 ("Coordinate out of bounds!");
785         }
786
787         float sample = data.getElemFloat(bankIndices[b],
788                                          y*scanlineStride + x*pixelStride +
789                                          bandOffsets[b]);
790         return sample;
791     }
792
793     /**
794      * Returns the sample in a specified band
795      * for a pixel located at (x,y) as a double.
796      * An <code>ArrayIndexOutOfBoundsException</code> might be
797      * thrown if the coordinates are not in bounds.
798      * @param x,&nbsp;y The coordinates of the pixel location
799      * @param b The band to return
800      * @param data The DataBuffer containing the image data
801      * @return a double value representing the sample in the specified
802      * band for the specified pixel.
803      */

804     public double getSampleDouble(int x, int y, int b, DataBuffer JavaDoc data) {
805         // Bounds check for 'b' will be performed automatically
806
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
807             throw new ArrayIndexOutOfBoundsException JavaDoc
808                 ("Coordinate out of bounds!");
809         }
810
811         double sample = data.getElemDouble(bankIndices[b],
812                                            y*scanlineStride + x*pixelStride +
813                                            bandOffsets[b]);
814     return sample;
815     }
816
817     /**
818      * Returns the samples in a specified band for the specified rectangle
819      * of pixels in an int array, one sample per data array element.
820      * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
821      * the coordinates are not in bounds.
822      * @param x,&nbsp;y the coordinates of the upper left pixel location
823      * @param w the width of the pixel rectangle
824      * @param h the height of the pixel rectangle
825      * @param b the band to return
826      * @param iArray if non-<code>null</code>, returns the samples
827      * in this array
828      * @param data the <code>DataBuffer</code> containing the image data
829      * @return the samples in the specified band of the specified pixel
830      * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
831      */

832     public int[] getSamples(int x, int y, int w, int h, int b,
833                             int iArray[], DataBuffer JavaDoc data) {
834         // Bounds check for 'b' will be performed automatically
835
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
836             throw new ArrayIndexOutOfBoundsException JavaDoc
837                 ("Coordinate out of bounds!");
838         }
839         int samples[];
840         if (iArray != null) {
841            samples = iArray;
842         } else {
843            samples = new int [w*h];
844         }
845         int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
846         int srcOffset = 0;
847
848         for (int i = 0; i < h; i++) {
849            int sampleOffset = lineOffset;
850            for (int j = 0; j < w; j++) {
851               samples[srcOffset++] = data.getElem(bankIndices[b],
852                                                   sampleOffset);
853               sampleOffset += pixelStride;
854            }
855            lineOffset += scanlineStride;
856         }
857         return samples;
858     }
859
860     /**
861      * Sets the data for a single pixel in the specified
862      * <code>DataBuffer</code> from a primitive array of type
863      * <code>TransferType</code>. For a <code>ComponentSampleModel</code>,
864      * this is the same as the data type, and samples are transferred
865      * one per array element.
866      * <p>
867      * The following code illustrates transferring data for one pixel from
868      * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
869      * described by <code>ComponentSampleModel</code> <code>csm1</code>,
870      * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
871      * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
872      * The transfer is usually more efficient than using
873      * <code>getPixel</code> and <code>setPixel</code>.
874      * <pre>
875      * ComponentSampleModel csm1, csm2;
876      * DataBufferInt db1, db2;
877      * csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
878      * db2);
879      * </pre>
880      * Using <code>getDataElements</code> and <code>setDataElements</code>
881      * to transfer between two <code>DataBuffer/SampleModel</code> pairs
882      * is legitimate if the <code>SampleModel</code> objects have
883      * the same number of bands, corresponding bands have the same number of
884      * bits per sample, and the <code>TransferType</code>s are the same.
885      * <p>
886      * A <code>ClassCastException</code> is thrown if <code>obj</code> is not
887      * a primitive array of type <code>TransferType</code>.
888      * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
889      * the coordinates are not in bounds, or if <code>obj</code> is not large
890      * enough to hold the pixel data.
891      * @param x,&nbsp;y the coordinates of the pixel location
892      * @param obj a primitive array containing pixel data
893      * @param data the DataBuffer containing the image data
894      * @see #getDataElements(int, int, Object, DataBuffer)
895      */

896     public void setDataElements(int x, int y, Object JavaDoc obj, DataBuffer JavaDoc data) {
897         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
898             throw new ArrayIndexOutOfBoundsException JavaDoc
899                 ("Coordinate out of bounds!");
900         }
901
902     int type = getTransferType();
903     int numDataElems = getNumDataElements();
904     int pixelOffset = y*scanlineStride + x*pixelStride;
905
906     switch(type) {
907
908     case DataBuffer.TYPE_BYTE:
909
910         byte[] barray = (byte[])obj;
911
912         for (int i=0; i<numDataElems; i++) {
913         data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
914                ((int)barray[i])&0xff);
915         }
916         break;
917
918     case DataBuffer.TYPE_USHORT:
919         case DataBuffer.TYPE_SHORT:
920             
921         short[] sarray = (short[])obj;
922
923         for (int i=0; i<numDataElems; i++) {
924         data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
925                ((int)sarray[i])&0xffff);
926         }
927         break;
928
929     case DataBuffer.TYPE_INT:
930
931         int[] iarray = (int[])obj;
932
933         for (int i=0; i<numDataElems; i++) {
934         data.setElem(bankIndices[i],
935                              pixelOffset + bandOffsets[i], iarray[i]);
936         }
937         break;
938
939     case DataBuffer.TYPE_FLOAT:
940
941         float[] farray = (float[])obj;
942
943         for (int i=0; i<numDataElems; i++) {
944         data.setElemFloat(bankIndices[i],
945                              pixelOffset + bandOffsets[i], farray[i]);
946         }
947         break;
948
949     case DataBuffer.TYPE_DOUBLE:
950
951         double[] darray = (double[])obj;
952
953         for (int i=0; i<numDataElems; i++) {
954         data.setElemDouble(bankIndices[i],
955                              pixelOffset + bandOffsets[i], darray[i]);
956         }
957         break;
958
959     }
960     }
961
962     /**
963      * Sets a pixel in the <code>DataBuffer</code> using an int array of
964      * samples for input. An <code>ArrayIndexOutOfBoundsException</code>
965      * might be thrown if the coordinates are
966      * not in bounds.
967      * @param x,&nbsp;y The coordinates of the pixel location
968      * @param iArray The input samples in an int array
969      * @param data The DataBuffer containing the image data
970      * @see #getPixel(int, int, int[], DataBuffer)
971      */

972     public void setPixel(int x, int y, int iArray[], DataBuffer JavaDoc data) {
973         if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
974             throw new ArrayIndexOutOfBoundsException JavaDoc
975                 ("Coordinate out of bounds!");
976         }
977        int pixelOffset = y*scanlineStride + x*pixelStride;
978        for (int i=0; i<numBands; i++) {
979            data.setElem(bankIndices[i],
980                         pixelOffset + bandOffsets[i],iArray[i]);
981        }
982     }
983
984     /**
985      * Sets all samples for a rectangle of pixels from an int array containing
986      * one sample per array element.
987      * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
988      * coordinates are not in bounds.
989      * @param x,&nbsp;y The coordinates of the upper left pixel location
990      * @param w The width of the pixel rectangle
991      * @param h The height of the pixel rectangle
992      * @param iArray The input samples in an int array
993      * @param data The DataBuffer containing the image data
994      * @see #getPixels(int, int, int, int, int[], DataBuffer)
995      */

996     public void setPixels(int x, int y, int w, int h,
997                           int iArray[], DataBuffer JavaDoc data) {
998         if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
999             throw new ArrayIndexOutOfBoundsException JavaDoc
1000                ("Coordinate out of bounds!");
1001        }
1002
1003        int lineOffset = y*scanlineStride + x*pixelStride;
1004        int srcOffset = 0;
1005
1006        for (int i = 0; i < h; i++) {
1007           int pixelOffset = lineOffset;
1008           for (int j = 0; j < w; j++) {
1009              for (int k=0; k < numBands; k++) {
1010                 data.setElem(bankIndices[k], pixelOffset + bandOffsets[k],
1011                              iArray[srcOffset++]);
1012              }
1013              pixelOffset += pixelStride;
1014           }
1015           lineOffset += scanlineStride;
1016        }
1017    }
1018
1019    /**
1020     * Sets a sample in the specified band for the pixel located at (x,y)
1021     * in the <code>DataBuffer</code> using an int for input.
1022     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
1023     * coordinates are not in bounds.
1024     * @param x,&nbsp;y the coordinates of the pixel location
1025     * @param b the band to set
1026     * @param s the input sample as an int
1027     * @param data the DataBuffer containing the image data
1028     * @see #getSample(int, int, int, DataBuffer)
1029     */

1030    public void setSample(int x, int y, int b, int s,
1031                          DataBuffer JavaDoc data) {
1032        // Bounds check for 'b' will be performed automatically
1033
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1034            throw new ArrayIndexOutOfBoundsException JavaDoc
1035                ("Coordinate out of bounds!");
1036        }
1037        data.setElem(bankIndices[b],
1038                     y*scanlineStride + x*pixelStride + bandOffsets[b], s);
1039    }
1040
1041    /**
1042     * Sets a sample in the specified band for the pixel located at (x,y)
1043     * in the <code>DataBuffer</code> using a float for input.
1044     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
1045     * the coordinates are not in bounds.
1046     * @param x,&nbsp;y The coordinates of the pixel location
1047     * @param b The band to set
1048     * @param s The input sample as a float
1049     * @param data The DataBuffer containing the image data
1050     * @see #getSample(int, int, int, DataBuffer)
1051     */

1052    public void setSample(int x, int y, int b,
1053              float s ,
1054              DataBuffer JavaDoc data) {
1055        // Bounds check for 'b' will be performed automatically
1056
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1057            throw new ArrayIndexOutOfBoundsException JavaDoc
1058                ("Coordinate out of bounds!");
1059        }
1060        data.setElemFloat(bankIndices[b],
1061                          y*scanlineStride + x*pixelStride + bandOffsets[b],
1062                          s);
1063    }
1064
1065    /**
1066     * Sets a sample in the specified band for the pixel located at (x,y)
1067     * in the <code>DataBuffer</code> using a double for input.
1068     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
1069     * the coordinates are not in bounds.
1070     * @param x,&nbsp;y The coordinates of the pixel location
1071     * @param b The band to set
1072     * @param s The input sample as a double
1073     * @param data The DataBuffer containing the image data
1074     * @see #getSample(int, int, int, DataBuffer)
1075     */

1076    public void setSample(int x, int y, int b,
1077              double s,
1078              DataBuffer JavaDoc data) {
1079        // Bounds check for 'b' will be performed automatically
1080
if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
1081            throw new ArrayIndexOutOfBoundsException JavaDoc
1082                ("Coordinate out of bounds!");
1083        }
1084        data.setElemDouble(bankIndices[b],
1085                          y*scanlineStride + x*pixelStride + bandOffsets[b],
1086                          s);
1087    }
1088
1089    /**
1090     * Sets the samples in the specified band for the specified rectangle
1091     * of pixels from an int array containing one sample per data array element.
1092     * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
1093     * coordinates are not in bounds.
1094     * @param x,&nbsp;y The coordinates of the upper left pixel location
1095     * @param w The width of the pixel rectangle
1096     * @param h The height of the pixel rectangle
1097     * @param b The band to set
1098     * @param iArray The input samples in an int array
1099     * @param data The DataBuffer containing the image data
1100     * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
1101     */

1102    public void setSamples(int x, int y, int w, int h, int b,
1103                           int iArray[], DataBuffer JavaDoc data) {
1104        // Bounds check for 'b' will be performed automatically
1105
if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
1106            throw new ArrayIndexOutOfBoundsException JavaDoc
1107                ("Coordinate out of bounds!");
1108        }
1109        int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
1110        int srcOffset = 0;
1111
1112        for (int i = 0; i < h; i++) {
1113           int sampleOffset = lineOffset;
1114           for (int j = 0; j < w; j++) {
1115              data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]);
1116              sampleOffset += pixelStride;
1117           }
1118           lineOffset += scanlineStride;
1119        }
1120    }
1121
1122    public boolean equals(Object JavaDoc o) {
1123        if ((o == null) || !(o instanceof ComponentSampleModel JavaDoc)) {
1124            return false;
1125        }
1126
1127        ComponentSampleModel JavaDoc that = (ComponentSampleModel JavaDoc)o;
1128        return this.width == that.width &&
1129            this.height == that.height &&
1130            this.numBands == that.numBands &&
1131            this.dataType == that.dataType &&
1132            Arrays.equals(this.bandOffsets, that.bandOffsets) &&
1133            Arrays.equals(this.bankIndices, that.bankIndices) &&
1134            this.numBands == that.numBands &&
1135            this.numBanks == that.numBanks &&
1136            this.scanlineStride == that.scanlineStride &&
1137            this.pixelStride == that.pixelStride;
1138    }
1139
1140    // If we implement equals() we must also implement hashCode
1141
public int hashCode() {
1142        int hash = 0;
1143        hash = width;
1144        hash <<= 8;
1145        hash ^= height;
1146        hash <<= 8;
1147        hash ^= numBands;
1148        hash <<= 8;
1149        hash ^= dataType;
1150        hash <<= 8;
1151        for (int i = 0; i < bandOffsets.length; i++) {
1152            hash ^= bandOffsets[i];
1153            hash <<= 8;
1154        }
1155        for (int i = 0; i < bankIndices.length; i++) {
1156            hash ^= bankIndices[i];
1157            hash <<= 8;
1158        }
1159        hash ^= numBands;
1160        hash <<= 8;
1161        hash ^= numBanks;
1162        hash <<= 8;
1163        hash ^= scanlineStride;
1164        hash <<= 8;
1165        hash ^= pixelStride;
1166        return hash;
1167    }
1168}
1169
Popular Tags