~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/sun/awt/image/ShortComponentRaster.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
 
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
4
 *
 
5
 * This code is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 only, as
 
7
 * published by the Free Software Foundation.  Oracle designates this
 
8
 * particular file as subject to the "Classpath" exception as provided
 
9
 * by Oracle in the LICENSE file that accompanied this code.
 
10
 *
 
11
 * This code is distributed in the hope that it will be useful, but WITHOUT
 
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
14
 * version 2 for more details (a copy is included in the LICENSE file that
 
15
 * accompanied this code).
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License version
 
18
 * 2 along with this work; if not, write to the Free Software Foundation,
 
19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 *
 
21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
22
 * or visit www.oracle.com if you need additional information or have any
 
23
 * questions.
 
24
 */
 
25
 
 
26
package sun.awt.image;
 
27
import java.awt.image.Raster;
 
28
import java.awt.image.WritableRaster;
 
29
import java.awt.image.RasterFormatException;
 
30
import java.awt.image.SampleModel;
 
31
import java.awt.image.ComponentSampleModel;
 
32
import java.awt.image.SinglePixelPackedSampleModel;
 
33
import java.awt.image.DataBuffer;
 
34
import java.awt.image.DataBufferUShort;
 
35
import java.awt.Rectangle;
 
36
import java.awt.Point;
 
37
 
 
38
/**
 
39
 * This class defines a Raster with pixels consisting of one or more 16-bit
 
40
 * data elements stored in close proximity to each other in a short integer
 
41
 * array.  The bit precision per data element is that
 
42
 * of the data type (that is, the bit precision for this Raster is 16).
 
43
 * There is only one pixel stride and one scanline stride for all
 
44
 * bands.  This type of Raster can be used with a
 
45
 * ComponentColorModel if there are multiple bands, or a
 
46
 * IndexColorModel if there is only one band.
 
47
 * <p>
 
48
 * For example, 5-6-5 RGB image data can be represented by a
 
49
 * ShortComponentRaster using a SinglePixelPackedSampleModel and
 
50
 * a ComponentColorModel.
 
51
 *
 
52
 *
 
53
 */
 
54
public class ShortComponentRaster extends SunWritableRaster {
 
55
 
 
56
    /** private band offset for use by native code */
 
57
    protected int bandOffset;
 
58
 
 
59
    /** Data offsets for each band of image data. */
 
60
    protected int[]         dataOffsets;
 
61
 
 
62
    /** Scanline stride of the image data contained in this Raster. */
 
63
    protected int           scanlineStride;
 
64
 
 
65
    /** Pixel stride of the image data contained in this Raster. */
 
66
    protected int           pixelStride;
 
67
 
 
68
    /** The image data array. */
 
69
    protected short[]       data;
 
70
 
 
71
    int type;
 
72
 
 
73
    /** A cached copy of minX + width for use in bounds checks. */
 
74
    private int maxX;
 
75
 
 
76
    /** A cached copy of minY + height for use in bounds checks. */
 
77
    private int maxY;
 
78
 
 
79
    /**
 
80
     *  Constructs a ShortComponentRaster with the given SampleModel.
 
81
     *  The Raster's upper left corner is origin and it is the same
 
82
     *  size as the SampleModel.  A DataBuffer large enough to describe the
 
83
     *  Raster is automatically created.  SampleModel must be of type
 
84
     *  ComponentSampleModel or SinglePixelPackedSampleModel.
 
85
     *  @param sampleModel     The SampleModel that specifies the layout.
 
86
     *  @param origin          The Point that specified the origin.
 
87
     */
 
88
    public ShortComponentRaster(SampleModel sampleModel, Point origin) {
 
89
        this(sampleModel,
 
90
             sampleModel.createDataBuffer(),
 
91
             new Rectangle(origin.x,
 
92
                           origin.y,
 
93
                           sampleModel.getWidth(),
 
94
                           sampleModel.getHeight()),
 
95
             origin,
 
96
             null);
 
97
    }
 
98
 
 
99
    /**
 
100
     * Constructs a ShortComponentRaster with the given SampleModel
 
101
     * and DataBuffer.  The Raster's upper left corner is origin and
 
102
     * it is the same sizes the SampleModel.  The DataBuffer is not
 
103
     * initialized and must be a DataBufferUShort compatible with SampleModel.
 
104
     * SampleModel must be of type ComponentSampleModel or
 
105
     * SinglePixelPackedSampleModel.
 
106
     * @param sampleModel     The SampleModel that specifies the layout.
 
107
     * @param dataBuffer      The DataBufferUShort that contains the image data.
 
108
     * @param origin          The Point that specifies the origin.
 
109
     */
 
110
    public ShortComponentRaster(SampleModel sampleModel,
 
111
                                   DataBuffer dataBuffer,
 
112
                                   Point origin) {
 
113
        this(sampleModel,
 
114
             dataBuffer,
 
115
             new Rectangle(origin.x,
 
116
                           origin.y,
 
117
                           sampleModel.getWidth(),
 
118
                           sampleModel.getHeight()),
 
119
             origin,
 
120
             null);
 
121
    }
 
122
 
 
123
    /**
 
124
     * Constructs a ShortComponentRaster with the given SampleModel,
 
125
     * DataBuffer, and parent.  DataBuffer must be a DataBufferUShort and
 
126
     * SampleModel must be of type ComponentSampleModel or
 
127
     * SinglePixelPackedSampleModel.  When translated into the base Raster's
 
128
     * coordinate system, aRegion must be contained by the base Raster.
 
129
     * Origin is the coodinate in the new Raster's coordinate system of
 
130
     * the origin of the base Raster.  (The base Raster is the Raster's
 
131
     * ancestor which has no parent.)
 
132
     *
 
133
     * Note that this constructor should generally be called by other
 
134
     * constructors or create methods, it should not be used directly.
 
135
     * @param sampleModel     The SampleModel that specifies the layout.
 
136
     * @param dataBuffer      The DataBufferUShort that contains the image data.
 
137
     * @param aRegion         The Rectangle that specifies the image area.
 
138
     * @param origin          The Point that specifies the origin.
 
139
     * @param parent          The parent (if any) of this raster.
 
140
     */
 
141
    public ShortComponentRaster(SampleModel sampleModel,
 
142
                                   DataBuffer dataBuffer,
 
143
                                   Rectangle aRegion,
 
144
                                   Point origin,
 
145
                                   ShortComponentRaster parent) {
 
146
 
 
147
        super(sampleModel, dataBuffer, aRegion, origin, parent);
 
148
        this.maxX = minX + width;
 
149
        this.maxY = minY + height;
 
150
 
 
151
        if(!(dataBuffer instanceof DataBufferUShort)) {
 
152
            throw new RasterFormatException("ShortComponentRasters must have "+
 
153
                                            "short DataBuffers");
 
154
        }
 
155
 
 
156
        DataBufferUShort dbus = (DataBufferUShort)dataBuffer;
 
157
        this.data = stealData(dbus, 0);
 
158
        if (dbus.getNumBanks() != 1) {
 
159
            throw new
 
160
                RasterFormatException("DataBuffer for ShortComponentRasters"+
 
161
                                      " must only have 1 bank.");
 
162
        }
 
163
        int dbOffset = dbus.getOffset();
 
164
 
 
165
        if (sampleModel instanceof ComponentSampleModel) {
 
166
            ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
 
167
            this.type = IntegerComponentRaster.TYPE_USHORT_SAMPLES;
 
168
            this.scanlineStride = csm.getScanlineStride();
 
169
            this.pixelStride = csm.getPixelStride();
 
170
            this.dataOffsets = csm.getBandOffsets();
 
171
            int xOffset = aRegion.x - origin.x;
 
172
            int yOffset = aRegion.y - origin.y;
 
173
            for (int i = 0; i < getNumDataElements(); i++) {
 
174
                dataOffsets[i] += dbOffset +
 
175
                    xOffset*pixelStride+yOffset*scanlineStride;
 
176
            }
 
177
        } else if (sampleModel instanceof SinglePixelPackedSampleModel) {
 
178
            SinglePixelPackedSampleModel sppsm =
 
179
                    (SinglePixelPackedSampleModel)sampleModel;
 
180
            this.type = IntegerComponentRaster.TYPE_USHORT_PACKED_SAMPLES;
 
181
            this.scanlineStride = sppsm.getScanlineStride();
 
182
            this.pixelStride    = 1;
 
183
            this.dataOffsets = new int[1];
 
184
            this.dataOffsets[0] = dbOffset;
 
185
            int xOffset = aRegion.x - origin.x;
 
186
            int yOffset = aRegion.y - origin.y;
 
187
            dataOffsets[0] += xOffset+yOffset*scanlineStride;
 
188
        } else {
 
189
            throw new RasterFormatException("ShortComponentRasters must have"+
 
190
                "ComponentSampleModel or SinglePixelPackedSampleModel");
 
191
        }
 
192
        this.bandOffset = this.dataOffsets[0];
 
193
 
 
194
        verify(false);
 
195
    }
 
196
 
 
197
    /**
 
198
     * Returns a copy of the data offsets array. For each band the data offset
 
199
     * is the index into the band's data array, of the first sample of the
 
200
     * band.
 
201
     */
 
202
    public int[] getDataOffsets() {
 
203
        return (int[]) dataOffsets.clone();
 
204
    }
 
205
 
 
206
    /**
 
207
     * Returns the data offset for the specified band.  The data offset
 
208
     * is the index into the data array in which the first sample
 
209
     * of the first scanline is stored.
 
210
     * @param band  The band whose offset is returned.
 
211
     */
 
212
    public int getDataOffset(int band) {
 
213
        return dataOffsets[band];
 
214
    }
 
215
 
 
216
    /**
 
217
     * Returns the scanline stride -- the number of data array elements between
 
218
     * a given sample and the same sample in the same column of the next row.
 
219
     */
 
220
    public int getScanlineStride() {
 
221
        return scanlineStride;
 
222
    }
 
223
 
 
224
    /**
 
225
     * Returns pixel stride -- the number of data array elements  between two
 
226
     * samples for the same band on the same scanline.
 
227
     */
 
228
    public int getPixelStride() {
 
229
        return pixelStride;
 
230
    }
 
231
 
 
232
    /**
 
233
     * Returns a reference to the data array.
 
234
     */
 
235
    public short[] getDataStorage() {
 
236
        return data;
 
237
    }
 
238
 
 
239
    /**
 
240
     * Returns the data elements for all bands at the specified
 
241
     * location.
 
242
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
243
     * if the pixel coordinate is out of bounds.
 
244
     * A ClassCastException will be thrown if the input object is non null
 
245
     * and references anything other than an array of transferType.
 
246
     * @param x        The X coordinate of the pixel location.
 
247
     * @param y        The Y coordinate of the pixel location.
 
248
     * @param outData  An object reference to an array of type defined by
 
249
     *                 getTransferType() and length getNumDataElements().
 
250
     *                 If null an array of appropriate type and size will be
 
251
     *                 allocated.
 
252
     * @return         An object reference to an array of type defined by
 
253
     *                 getTransferType() with the request pixel data.
 
254
     */
 
255
    public Object getDataElements(int x, int y, Object obj) {
 
256
        if ((x < this.minX) || (y < this.minY) ||
 
257
            (x >= this.maxX) || (y >= this.maxY)) {
 
258
            throw new ArrayIndexOutOfBoundsException
 
259
                ("Coordinate out of bounds!");
 
260
        }
 
261
        short outData[];
 
262
        if (obj == null) {
 
263
            outData = new short[numDataElements];
 
264
        } else {
 
265
            outData = (short[])obj;
 
266
        }
 
267
        int off = (y-minY)*scanlineStride +
 
268
                  (x-minX)*pixelStride;
 
269
 
 
270
        for (int band = 0; band < numDataElements; band++) {
 
271
            outData[band] = data[dataOffsets[band] + off];
 
272
        }
 
273
 
 
274
        return outData;
 
275
    }
 
276
 
 
277
    /**
 
278
     * Returns an array  of data elements from the specified rectangular
 
279
     * region.
 
280
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
281
     * if the pixel coordinates are out of bounds.
 
282
     * A ClassCastException will be thrown if the input object is non null
 
283
     * and references anything other than an array of transferType.
 
284
     * <pre>
 
285
     *       short[] bandData = (short[])Raster.getDataElements(x, y, w, h, null);
 
286
     *       int numDataElements = Raster.getBands();
 
287
     *       short[] pixel = new short[numDataElements];
 
288
     *       // To find the data element at location (x2, y2)
 
289
     *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
 
290
     *                        pixel, 0, numDataElements);
 
291
     * </pre>
 
292
     * @param x        The X coordinate of the upper left pixel location.
 
293
     * @param y        The Y coordinate of the upper left pixel location.
 
294
     * @param width    Width of the pixel rectangle.
 
295
     * @param height   Height of the pixel rectangle.
 
296
     * @param outData  An object reference to an array of type defined by
 
297
     *                 getTransferType() and length w*h*getNumDataElements().
 
298
     *                 If null an array of appropriate type and size will be
 
299
     *                 allocated.
 
300
     * @return         An object reference to an array of type defined by
 
301
     *                 getTransferType() with the request pixel data.
 
302
     */
 
303
    public Object getDataElements(int x, int y, int w, int h, Object obj) {
 
304
        if ((x < this.minX) || (y < this.minY) ||
 
305
            (x + w > this.maxX) || (y + h > this.maxY)) {
 
306
            throw new ArrayIndexOutOfBoundsException
 
307
                ("Coordinate out of bounds!");
 
308
        }
 
309
        short outData[];
 
310
        if (obj == null) {
 
311
            outData = new short[w*h*numDataElements];
 
312
        } else {
 
313
            outData = (short[])obj;
 
314
        }
 
315
        int yoff = (y-minY)*scanlineStride +
 
316
                   (x-minX)*pixelStride;
 
317
 
 
318
        int xoff;
 
319
        int off = 0;
 
320
        int xstart;
 
321
        int ystart;
 
322
 
 
323
        for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
324
            xoff = yoff;
 
325
            for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
 
326
                for (int c = 0; c < numDataElements; c++) {
 
327
                    outData[off++] = data[dataOffsets[c] + xoff];
 
328
                }
 
329
            }
 
330
        }
 
331
 
 
332
        return outData;
 
333
    }
 
334
 
 
335
    /**
 
336
     * Returns a short integer array of data elements from the
 
337
     * specified rectangular region.
 
338
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
339
     * if the pixel coordinates are out of bounds.
 
340
     * <pre>
 
341
     *       short[] bandData = Raster.getShortData(x, y, w, h, null);
 
342
     *       // To find the data element at location (x2, y2)
 
343
     *       short dataElenent = bandData[((y2-y)*w + (x2-x))];
 
344
     * </pre>
 
345
     * @param x        The X coordinate of the upper left pixel location.
 
346
     * @param y        The Y coordinate of the upper left pixel location.
 
347
     * @param width    Width of the sample rectangle.
 
348
     * @param height   Height of the sample rectangle.
 
349
     * @param band     The band to return.
 
350
     * @param outData  If non-null, data elements for all bands
 
351
     *                 at the specified location are returned in this array.
 
352
     * @return         Data array with data elements for all bands.
 
353
     */
 
354
    public short[] getShortData(int x, int y, int w, int h,
 
355
                               int band, short[] outData) {
 
356
        // Bounds check for 'band' will be performed automatically
 
357
        if ((x < this.minX) || (y < this.minY) ||
 
358
            (x + w > this.maxX) || (y + h > this.maxY)) {
 
359
            throw new ArrayIndexOutOfBoundsException
 
360
                ("Coordinate out of bounds!");
 
361
        }
 
362
        if (outData == null) {
 
363
            outData = new short[numDataElements*w*h];
 
364
        }
 
365
        int yoff =  (y-minY)*scanlineStride +
 
366
                    (x-minX)*pixelStride+ dataOffsets[band];
 
367
        int xoff;
 
368
        int off = 0;
 
369
        int xstart;
 
370
        int ystart;
 
371
 
 
372
        if (pixelStride == 1) {
 
373
            if (scanlineStride == w) {
 
374
                System.arraycopy(data, yoff, outData, 0, w*h);
 
375
            }
 
376
            else {
 
377
                for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
378
                    System.arraycopy(data, yoff, outData, off, w);
 
379
                    off += w;
 
380
                }
 
381
            }
 
382
        }
 
383
        else {
 
384
            for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
385
                xoff = yoff;
 
386
                for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
 
387
                    outData[off++] = data[xoff];
 
388
                }
 
389
            }
 
390
        }
 
391
 
 
392
        return outData;
 
393
    }
 
394
 
 
395
    /**
 
396
     * Returns a short integer array  of data elements from the
 
397
     * specified rectangular region.
 
398
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
399
     * if the pixel coordinates are out of bounds.
 
400
     * <pre>
 
401
     *       short[] bandData = Raster.getShortData(x, y, w, h, null);
 
402
     *       int numDataElements = Raster.getNumBands();
 
403
     *       short[] pixel = new short[numDataElements];
 
404
     *       // To find the data element at location (x2, y2)
 
405
     *       System.arraycopy(bandData, ((y2-y)*w + (x2-x))*numDataElements,
 
406
     *                        pixel, 0, numDataElements);
 
407
     * </pre>
 
408
     * @param x        The X coordinate of the upper left pixel location.
 
409
     * @param y        The Y coordinate of the upper left pixel location.
 
410
     * @param width    Width of the pixel rectangle.
 
411
     * @param height   Height of the pixel rectangle.
 
412
     * @param outData  If non-null, data elements for all bands
 
413
     *                 at the specified location are returned in this array.
 
414
     * @return         Data array with data elements for all bands.
 
415
     */
 
416
    public short[] getShortData(int x, int y, int w, int h, short[] outData) {
 
417
        if ((x < this.minX) || (y < this.minY) ||
 
418
            (x + w > this.maxX) || (y + h > this.maxY)) {
 
419
            throw new ArrayIndexOutOfBoundsException
 
420
                ("Coordinate out of bounds!");
 
421
        }
 
422
        if (outData == null) {
 
423
            outData = new short[numDataElements*w*h];
 
424
        }
 
425
        int yoff = (y-minY)*scanlineStride +
 
426
                   (x-minX)*pixelStride;
 
427
        int xoff;
 
428
        int off = 0;
 
429
        int xstart;
 
430
        int ystart;
 
431
 
 
432
        for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
433
            xoff = yoff;
 
434
            for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
 
435
                for (int c = 0; c < numDataElements; c++) {
 
436
                    outData[off++] = data[dataOffsets[c] + xoff];
 
437
                }
 
438
            }
 
439
        }
 
440
 
 
441
        return outData;
 
442
    }
 
443
 
 
444
    /**
 
445
     * Stores the data elements for all bands at the specified location.
 
446
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
447
     * if the pixel coordinate is out of bounds.
 
448
     * A ClassCastException will be thrown if the input object is non null
 
449
     * and references anything other than an array of transferType.
 
450
     * @param x        The X coordinate of the pixel location.
 
451
     * @param y        The Y coordinate of the pixel location.
 
452
     * @param inData   An object reference to an array of type defined by
 
453
     *                 getTransferType() and length getNumDataElements()
 
454
     *                 containing the pixel data to place at x,y.
 
455
     */
 
456
    public void setDataElements(int x, int y, Object obj) {
 
457
        if ((x < this.minX) || (y < this.minY) ||
 
458
            (x >= this.maxX) || (y >= this.maxY)) {
 
459
            throw new ArrayIndexOutOfBoundsException
 
460
                ("Coordinate out of bounds!");
 
461
        }
 
462
        short inData[] = (short[])obj;
 
463
        int off = (y-minY)*scanlineStride +
 
464
                  (x-minX)*pixelStride;
 
465
        for (int i = 0; i < numDataElements; i++) {
 
466
            data[dataOffsets[i] + off] = (short) inData[i];
 
467
        }
 
468
 
 
469
        markDirty();
 
470
    }
 
471
 
 
472
    /**
 
473
     * Stores the Raster data at the specified location.
 
474
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
475
     * if the pixel coordinates are out of bounds.
 
476
     * @param x          The X coordinate of the pixel location.
 
477
     * @param y          The Y coordinate of the pixel location.
 
478
     * @param inRaster   Raster of data to place at x,y location.
 
479
     */
 
480
    public void setDataElements(int x, int y, Raster inRaster) {
 
481
        int dstOffX = x + inRaster.getMinX();
 
482
        int dstOffY = y + inRaster.getMinY();
 
483
        int width  = inRaster.getWidth();
 
484
        int height = inRaster.getHeight();
 
485
        if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
 
486
            (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) {
 
487
            throw new ArrayIndexOutOfBoundsException
 
488
                ("Coordinate out of bounds!");
 
489
        }
 
490
 
 
491
        setDataElements(dstOffX, dstOffY, width, height, inRaster);
 
492
    }
 
493
 
 
494
    /**
 
495
     * Stores the Raster data at the specified location.
 
496
     * @param dstX The absolute X coordinate of the destination pixel
 
497
     * that will receive a copy of the upper-left pixel of the
 
498
     * inRaster
 
499
     * @param dstY The absolute Y coordinate of the destination pixel
 
500
     * that will receive a copy of the upper-left pixel of the
 
501
     * inRaster
 
502
     * @param width      The number of pixels to store horizontally
 
503
     * @param height     The number of pixels to store vertically
 
504
     * @param inRaster   Raster of data to place at x,y location.
 
505
     */
 
506
    private void setDataElements(int dstX, int dstY,
 
507
                                 int width, int height,
 
508
                                 Raster inRaster) {
 
509
        // Assume bounds checking has been performed previously
 
510
        if (width <= 0 || height <= 0) {
 
511
            return;
 
512
        }
 
513
 
 
514
        // Write inRaster (minX, minY) to (dstX, dstY)
 
515
 
 
516
        int srcOffX = inRaster.getMinX();
 
517
        int srcOffY = inRaster.getMinY();
 
518
        Object tdata = null;
 
519
 
 
520
//      // REMIND: Do something faster!
 
521
//      if (inRaster instanceof ShortComponentRaster) {
 
522
//      }
 
523
 
 
524
        for (int startY=0; startY < height; startY++) {
 
525
            // Grab one scanline at a time
 
526
            tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
 
527
                                             width, 1, tdata);
 
528
            setDataElements(dstX, dstY + startY, width, 1, tdata);
 
529
        }
 
530
    }
 
531
 
 
532
    /**
 
533
     * Stores an array of data elements into the specified rectangular
 
534
     * region.
 
535
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
536
     * if the pixel coordinates are out of bounds.
 
537
     * A ClassCastException will be thrown if the input object is non null
 
538
     * and references anything other than an array of transferType.
 
539
     * The data elements in the
 
540
     * data array are assumed to be packed.  That is, a data element
 
541
     * for the nth band at location (x2, y2) would be found at:
 
542
     * <pre>
 
543
     *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
 
544
     * </pre>
 
545
     * @param x        The X coordinate of the upper left pixel location.
 
546
     * @param y        The Y coordinate of the upper left pixel location.
 
547
     * @param w        Width of the pixel rectangle.
 
548
     * @param h        Height of the pixel rectangle.
 
549
     * @param inData   An object reference to an array of type defined by
 
550
     *                 getTransferType() and length w*h*getNumDataElements()
 
551
     *                 containing the pixel data to place between x,y and
 
552
     *                 x+h, y+h.
 
553
     */
 
554
    public void setDataElements(int x, int y, int w, int h, Object obj) {
 
555
        if ((x < this.minX) || (y < this.minY) ||
 
556
            (x + w > this.maxX) || (y + h > this.maxY)) {
 
557
            throw new ArrayIndexOutOfBoundsException
 
558
                ("Coordinate out of bounds!");
 
559
        }
 
560
        short inData[] = (short[])obj;
 
561
        int yoff = (y-minY)*scanlineStride +
 
562
                   (x-minX)*pixelStride;
 
563
        int xoff;
 
564
        int off = 0;
 
565
        int xstart;
 
566
        int ystart;
 
567
 
 
568
        for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
569
            xoff = yoff;
 
570
            for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
 
571
                for (int c = 0; c < numDataElements; c++) {
 
572
                    data[dataOffsets[c] + xoff] = (short) inData[off++];
 
573
                }
 
574
            }
 
575
        }
 
576
 
 
577
        markDirty();
 
578
    }
 
579
 
 
580
    /**
 
581
     * Stores a short integer array of data elements into the
 
582
     * specified rectangular region.
 
583
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
584
     * if the pixel coordinates are out of bounds.
 
585
     * The data elements in the
 
586
     * data array are assumed to be packed.  That is, a data element
 
587
     * at location (x2, y2) would be found at:
 
588
     * <pre>
 
589
     *      inData[((y2-y)*w + (x2-x))]
 
590
     * </pre>
 
591
     * @param x        The X coordinate of the upper left pixel location.
 
592
     * @param y        The Y coordinate of the upper left pixel location.
 
593
     * @param w        Width of the pixel rectangle.
 
594
     * @param h        Height of the pixel rectangle.
 
595
     * @param band     The band to set.
 
596
     * @param inData   The data elements to be stored.
 
597
     */
 
598
    public void putShortData(int x, int y, int w, int h,
 
599
                             int band, short[] inData) {
 
600
        // Bounds check for 'band' will be performed automatically
 
601
        if ((x < this.minX) || (y < this.minY) ||
 
602
            (x + w > this.maxX) || (y + h > this.maxY)) {
 
603
            throw new ArrayIndexOutOfBoundsException
 
604
                ("Coordinate out of bounds!");
 
605
        }
 
606
        int yoff =  (y-minY)*scanlineStride +
 
607
                    (x-minX)*pixelStride + dataOffsets[band];
 
608
        int xoff;
 
609
        int off = 0;
 
610
        int xstart;
 
611
        int ystart;
 
612
 
 
613
        if (pixelStride == 1) {
 
614
            if (scanlineStride == w) {
 
615
                System.arraycopy(inData, 0, data, yoff, w*h);
 
616
            }
 
617
            else {
 
618
                for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
619
                    System.arraycopy(inData, off, data, yoff, w);
 
620
                    off += w;
 
621
                }
 
622
            }
 
623
        }
 
624
        else {
 
625
            for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
626
                xoff = yoff;
 
627
                for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
 
628
                    data[xoff] = inData[off++];
 
629
                }
 
630
            }
 
631
        }
 
632
 
 
633
        markDirty();
 
634
    }
 
635
 
 
636
    /**
 
637
     * Stores a short integer array of data elements into the
 
638
     * specified rectangular region.
 
639
     * An ArrayIndexOutOfBounds exception will be thrown at runtime
 
640
     * if the pixel coordinates are out of bounds.
 
641
     * The data elements in the
 
642
     * data array are assumed to be packed.  That is, a data element
 
643
     * for the nth band at location (x2, y2) would be found at:
 
644
     * <pre>
 
645
     *      inData[((y2-y)*w + (x2-x))*numDataElements + n]
 
646
     * </pre>
 
647
     * @param x        The X coordinate of the upper left pixel location.
 
648
     * @param y        The Y coordinate of the upper left pixel location.
 
649
     * @param w        Width of the pixel rectangle.
 
650
     * @param h        Height of the pixel rectangle.
 
651
     * @param inData   The data elements to be stored.
 
652
     */
 
653
    public void putShortData(int x, int y, int w, int h, short[] inData) {
 
654
        if ((x < this.minX) || (y < this.minY) ||
 
655
            (x + w > this.maxX) || (y + h > this.maxY)) {
 
656
            throw new ArrayIndexOutOfBoundsException
 
657
                ("Coordinate out of bounds!");
 
658
        }
 
659
        int yoff = (y-minY)*scanlineStride +
 
660
                   (x-minX)*pixelStride;
 
661
        int xoff;
 
662
        int off = 0;
 
663
        int xstart;
 
664
        int ystart;
 
665
 
 
666
        for (ystart=0; ystart < h; ystart++, yoff += scanlineStride) {
 
667
            xoff = yoff;
 
668
            for (xstart=0; xstart < w; xstart++, xoff += pixelStride) {
 
669
                for (int c = 0; c < numDataElements; c++) {
 
670
                    data[dataOffsets[c] + xoff] = inData[off++];
 
671
                }
 
672
            }
 
673
        }
 
674
 
 
675
        markDirty();
 
676
    }
 
677
 
 
678
    /**
 
679
     * Creates a subraster given a region of the raster.  The x and y
 
680
     * coordinates specify the horizontal and vertical offsets
 
681
     * from the upper-left corner of this raster to the upper-left corner
 
682
     * of the subraster.  A subset of the bands of the parent Raster may
 
683
     * be specified.  If this is null, then all the bands are present in the
 
684
     * subRaster. A translation to the subRaster may also be specified.
 
685
     * Note that the subraster will reference the same
 
686
     * band objects as the parent raster, but using different offsets.
 
687
     * @param x               X offset.
 
688
     * @param y               Y offset.
 
689
     * @param width           Width (in pixels) of the subraster.
 
690
     * @param height          Height (in pixels) of the subraster.
 
691
     * @param x0              Translated X origin of the subraster.
 
692
     * @param y0              Translated Y origin of the subraster.
 
693
     * @param bandList        Array of band indices.
 
694
     * @exception RasterFormatException
 
695
     *            if the specified bounding box is outside of the parent raster.
 
696
     */
 
697
    public Raster createChild (int x, int y,
 
698
                               int width, int height,
 
699
                               int x0, int y0, int[] bandList) {
 
700
        WritableRaster newRaster = createWritableChild(x, y,
 
701
                                                       width, height,
 
702
                                                       x0, y0,
 
703
                                                       bandList);
 
704
        return (Raster) newRaster;
 
705
    }
 
706
 
 
707
    /**
 
708
     * Creates a Writable subRaster given a region of the Raster. The x and y
 
709
     * coordinates specify the horizontal and vertical offsets
 
710
     * from the upper-left corner of this Raster to the upper-left corner
 
711
     * of the subRaster.  A subset of the bands of the parent Raster may
 
712
     * be specified.  If this is null, then all the bands are present in the
 
713
     * subRaster. A translation to the subRaster may also be specified.
 
714
     * Note that the subRaster will reference the same
 
715
     * DataBuffers as the parent Raster, but using different offsets.
 
716
     * @param x               X offset.
 
717
     * @param y               Y offset.
 
718
     * @param width           Width (in pixels) of the subraster.
 
719
     * @param height          Height (in pixels) of the subraster.
 
720
     * @param x0              Translated X origin of the subraster.
 
721
     * @param y0              Translated Y origin of the subraster.
 
722
     * @param bandList        Array of band indices.
 
723
     * @exception RasterFormatException
 
724
     *            if the specified bounding box is outside of the parent Raster.
 
725
     */
 
726
    public WritableRaster createWritableChild(int x, int y,
 
727
                                              int width, int height,
 
728
                                              int x0, int y0,
 
729
                                              int[] bandList) {
 
730
        if (x < this.minX) {
 
731
            throw new RasterFormatException("x lies outside the raster");
 
732
        }
 
733
        if (y < this.minY) {
 
734
            throw new RasterFormatException("y lies outside the raster");
 
735
        }
 
736
        if ((x+width < x) || (x+width > this.minX + this.width)) {
 
737
            throw new RasterFormatException("(x + width) is outside of Raster");
 
738
        }
 
739
        if ((y+height < y) || (y+height > this.minY + this.height)) {
 
740
            throw new RasterFormatException("(y + height) is outside of Raster");
 
741
        }
 
742
 
 
743
        SampleModel sm;
 
744
 
 
745
        if (bandList != null)
 
746
            sm = sampleModel.createSubsetSampleModel(bandList);
 
747
        else
 
748
            sm = sampleModel;
 
749
 
 
750
        int deltaX = x0 - x;
 
751
        int deltaY = y0 - y;
 
752
 
 
753
        return new ShortComponentRaster(sm,
 
754
                                       dataBuffer,
 
755
                                       new Rectangle(x0, y0, width, height),
 
756
                                       new Point(sampleModelTranslateX+deltaX,
 
757
                                                 sampleModelTranslateY+deltaY),
 
758
                                       this);
 
759
    }
 
760
 
 
761
    /**
 
762
     * Creates a Raster with the same layout but using a different
 
763
     * width and height, and with new zeroed data arrays.
 
764
     */
 
765
    public WritableRaster createCompatibleWritableRaster(int w, int h) {
 
766
        if (w <= 0 || h <=0) {
 
767
            throw new RasterFormatException("negative "+
 
768
                                          ((w <= 0) ? "width" : "height"));
 
769
        }
 
770
 
 
771
        SampleModel sm = sampleModel.createCompatibleSampleModel(w, h);
 
772
 
 
773
        return new ShortComponentRaster(sm, new Point(0, 0));
 
774
    }
 
775
 
 
776
    /**
 
777
     * Creates a Raster with the same layout and the same
 
778
     * width and height, and with new zeroed data arrays.  If
 
779
     * the Raster is a subRaster, this will call
 
780
     * createCompatibleRaster(width, height).
 
781
     */
 
782
    public WritableRaster createCompatibleWritableRaster() {
 
783
        return createCompatibleWritableRaster(width,height);
 
784
    }
 
785
 
 
786
    /**
 
787
     * Verify that the layout parameters are consistent with
 
788
     * the data.  If strictCheck
 
789
     * is false, this method will check for ArrayIndexOutOfBounds conditions.  If
 
790
     * strictCheck is true, this method will check for additional error
 
791
     * conditions such as line wraparound (width of a line greater than
 
792
     * the scanline stride).
 
793
     * @return   String   Error string, if the layout is incompatible with
 
794
     *                    the data.  Otherwise returns null.
 
795
     */
 
796
    private void verify (boolean strictCheck) {
 
797
        // Make sure data for Raster is in a legal range
 
798
        for (int i=0; i < dataOffsets.length; i++) {
 
799
            if (dataOffsets[i] < 0) {
 
800
                throw new RasterFormatException("Data offsets for band "+i+
 
801
                                                "("+dataOffsets[i]+
 
802
                                                ") must be >= 0");
 
803
            }
 
804
        }
 
805
 
 
806
        int maxSize = 0;
 
807
        int size;
 
808
 
 
809
        for (int i=0; i < numDataElements; i++) {
 
810
            size = (height-1)*scanlineStride + (width-1)*pixelStride +
 
811
                dataOffsets[i];
 
812
            if (size > maxSize) {
 
813
                maxSize = size;
 
814
            }
 
815
        }
 
816
        if (data.length < maxSize) {
 
817
            throw new RasterFormatException("Data array too small (should be "+
 
818
                                          maxSize+" )");
 
819
        }
 
820
    }
 
821
 
 
822
    public String toString() {
 
823
        return new String ("ShortComponentRaster: width = "+width
 
824
                           +" height = " + height
 
825
                           +" #numDataElements "+numDataElements);
 
826
                           // +" xOff = "+xOffset+" yOff = "+yOffset);
 
827
    }
 
828
 
 
829
}