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       &nb