Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / java / awt / image / ComponentSampleModel.java
blob86161e0ae39678e493608d207e0e2050282f052f
1 /* Copyright (C) 2000, 2002 Free Software Foundation
3 This file is part of GNU Classpath.
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
20 Linking this library statically or dynamically with other modules is
21 making a combined work based on this library. Thus, the terms and
22 conditions of the GNU General Public License cover the whole
23 combination.
25 As a special exception, the copyright holders of this library give you
26 permission to link this library with independent modules to produce an
27 executable, regardless of the license terms of these independent
28 modules, and to copy and distribute the resulting executable under
29 terms of your choice, provided that you also meet, for each linked
30 independent module, the terms and conditions of the license of that
31 module. An independent module is a module which is not derived from
32 or based on this library. If you modify this library, you may extend
33 this exception to your version of the library, but you are not
34 obligated to do so. If you do not wish to do so, delete this
35 exception statement from your version. */
37 package java.awt.image;
39 import gnu.java.awt.Buffers;
41 /* FIXME: This class does not yet support data type TYPE_SHORT */
43 /**
44 * ComponentSampleModel supports a flexible organization of pixel samples in
45 * memory, permitting pixel samples to be interleaved by band, by scanline,
46 * and by pixel.
48 * A DataBuffer for this sample model has K banks of data. Pixels have N
49 * samples, so there are N bands in the DataBuffer. Each band is completely
50 * contained in one bank of data, but a bank may contain more than one band.
51 * Each pixel sample is stored in a single data element.
53 * Within a bank, each band begins at an offset stored in bandOffsets. The
54 * banks containing the band is given by bankIndices. Within the bank, there
55 * are three dimensions - band, pixel, and scanline. The dimension ordering
56 * is controlled by bandOffset, pixelStride, and scanlineStride, which means
57 * that any combination of interleavings is supported.
59 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
61 public class ComponentSampleModel extends SampleModel
63 protected int[] bandOffsets;
64 protected int[] bankIndices;
66 // FIXME: Should we really shadow the numBands in the superclass?
67 //protected int numBands;
69 /** Used when creating data buffers. */
70 protected int numBanks;
72 protected int scanlineStride;
74 protected int pixelStride;
76 private boolean tightPixelPacking = false;
78 public ComponentSampleModel(int dataType,
79 int w, int h,
80 int pixelStride,
81 int scanlineStride,
82 int[] bandOffsets)
84 this(dataType, w, h, pixelStride, scanlineStride,
85 new int[bandOffsets.length], bandOffsets);
88 public ComponentSampleModel(int dataType,
89 int w, int h,
90 int pixelStride,
91 int scanlineStride,
92 int[] bankIndices,
93 int[] bandOffsets)
95 super(dataType, w, h, bandOffsets.length);
96 if ((pixelStride<0) || (scanlineStride<0) ||
97 (bandOffsets.length<1) ||
98 (bandOffsets.length != bankIndices.length))
99 throw new IllegalArgumentException();
101 this.bandOffsets = bandOffsets;
102 this.bankIndices = bankIndices;
104 this.numBanks = 0;
105 for (int b=0; b<bankIndices.length; b++)
106 this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
108 this.scanlineStride = scanlineStride;
109 this.pixelStride = pixelStride;
111 // See if we can use some speedups
113 /* FIXME: May these checks should be reserved for the
114 PixelInterleavedSampleModel? */
116 if (pixelStride == numBands)
118 tightPixelPacking = true;
119 for (int b=0; b<numBands; b++) {
120 if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
122 tightPixelPacking = false;
123 break;
129 public SampleModel createCompatibleSampleModel(int w, int h)
131 return new ComponentSampleModel(dataType, w, h, pixelStride,
132 scanlineStride, bankIndices,
133 bandOffsets);
136 public SampleModel createSubsetSampleModel(int[] bands)
138 int numBands = bands.length;
140 int[] bankIndices = new int[numBands];
141 int[] bandOffsets = new int[numBands];
142 for (int b=0; b<numBands; b++)
144 bankIndices[b] = this.bankIndices[bands[b]];
145 bandOffsets[b] = this.bandOffsets[bands[b]];
148 return new ComponentSampleModel(dataType, width, height, pixelStride,
149 scanlineStride, bankIndices,
150 bandOffsets);
153 public DataBuffer createDataBuffer()
155 // Maybe this value should be precalculated in the constructor?
156 int highestOffset = 0;
157 for (int b=0; b<numBands; b++)
159 highestOffset = Math.max(highestOffset, bandOffsets[b]);
161 int size = pixelStride*(width-1) + scanlineStride*(height-1) +
162 highestOffset + 1;
164 return Buffers.createBuffer(getDataType(), size, numBanks);
167 public int getOffset(int x, int y)
169 return getOffset(x, y, 0);
172 public int getOffset(int x, int y, int b)
174 return bandOffsets[b] + pixelStride*x + scanlineStride*y;
177 public final int[] getSampleSize()
179 int size = DataBuffer.getDataTypeSize(getDataType());
180 int[] sizes = new int[numBands];
182 java.util.Arrays.fill(sizes, size);
183 return sizes;
186 public final int getSampleSize(int band)
188 return DataBuffer.getDataTypeSize(getDataType());
191 public final int[] getBankIndices()
193 return bankIndices;
196 public final int[] getBandOffsets()
198 return bandOffsets;
201 public final int getScanlineStride()
203 return scanlineStride;
206 public final int getPixelStride()
208 return pixelStride;
211 public final int getNumDataElements()
213 return numBands;
216 public Object getDataElements(int x, int y, Object obj, DataBuffer data)
218 int xyOffset = pixelStride*x + scanlineStride*y;
220 int[] totalBandDataOffsets = new int[numBands];
222 /* Notice that band and bank offsets are different. Band offsets
223 are managed by the sample model, and bank offsets are managed
224 by the data buffer. Both must be accounted for. */
226 /* FIXME: For single pixels, it is probably easier to simple
227 call getElem instead of calculating the bank offset ourself.
229 On the other hand, then we need to push the value through
230 the int type returned by the getElem method. */
232 int[] bankOffsets = data.getOffsets();
234 for (int b=0; b<numBands; b++)
236 totalBandDataOffsets[b] =
237 bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
242 switch (getTransferType())
244 case DataBuffer.TYPE_BYTE:
245 DataBufferByte inByte = (DataBufferByte) data;
246 byte[] outByte = (byte[]) obj;
247 if (outByte == null) outByte = new byte[numBands];
249 for (int b=0; b<numBands; b++)
251 int dOffset = totalBandDataOffsets[b];
252 outByte[b] = inByte.getData(bankIndices[b])[dOffset];
254 return outByte;
256 case DataBuffer.TYPE_USHORT:
257 DataBufferUShort inUShort = (DataBufferUShort) data;
258 short[] outUShort = (short[]) obj;
259 if (outUShort == null) outUShort = new short[numBands];
261 for (int b=0; b<numBands; b++)
263 int dOffset = totalBandDataOffsets[b];
264 outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
266 return outUShort;
268 case DataBuffer.TYPE_SHORT:
269 DataBufferShort inShort = (DataBufferShort) data;
270 short[] outShort = (short[]) obj;
271 if (outShort == null) outShort = new short[numBands];
273 for (int b=0; b<numBands; b++)
275 int dOffset = totalBandDataOffsets[b];
276 outShort[b] = inShort.getData(bankIndices[b])[dOffset];
278 return outShort;
280 case DataBuffer.TYPE_INT:
281 DataBufferInt inInt = (DataBufferInt) data;
282 int[] outInt = (int[]) obj;
283 if (outInt == null) outInt = new int[numBands];
285 for (int b=0; b<numBands; b++)
287 int dOffset = totalBandDataOffsets[b];
288 outInt[b] = inInt.getData(bankIndices[b])[dOffset];
290 return outInt;
292 case DataBuffer.TYPE_FLOAT:
293 DataBufferFloat inFloat = (DataBufferFloat) data;
294 float[] outFloat = (float[]) obj;
295 if (outFloat == null) outFloat = new float[numBands];
297 for (int b=0; b<numBands; b++)
299 int dOffset = totalBandDataOffsets[b];
300 outFloat[b] = inFloat.getData(bankIndices[b])[dOffset];
302 return outFloat;
304 case DataBuffer.TYPE_DOUBLE:
305 DataBufferDouble inDouble = (DataBufferDouble) data;
306 double[] outDouble = (double[]) obj;
307 if (outDouble == null) outDouble = new double[numBands];
309 for (int b=0; b<numBands; b++)
311 int dOffset = totalBandDataOffsets[b];
312 outDouble[b] = inDouble.getData(bankIndices[b])[dOffset];
314 return outDouble;
316 default:
317 throw new IllegalStateException("unknown transfer type " +
318 getTransferType());
321 catch (ArrayIndexOutOfBoundsException aioobe)
323 String msg = "While reading data elements, " +
324 "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
325 ", data.getSize()=" + data.getSize() + ": " + aioobe;
326 throw new ArrayIndexOutOfBoundsException(msg);
330 public Object getDataElements(int x, int y, int w, int h, Object obj,
331 DataBuffer data)
333 if (!tightPixelPacking)
335 return super.getDataElements(x, y, w, h, obj, data);
338 // using get speedup
340 // We can copy whole rows
341 int rowSize = w*numBands;
342 int dataSize = rowSize*h;
344 DataBuffer transferBuffer =
345 Buffers.createBuffer(getTransferType(), obj, dataSize);
346 obj = Buffers.getData(transferBuffer);
348 int inOffset =
349 pixelStride*x +
350 scanlineStride*y +
351 data.getOffset(); // Assumes only one band is used
353 /* We don't add band offsets since we assume that bands have
354 offsets 0, 1, 2, ... */
356 // See if we can copy everything in one go
357 if (scanlineStride == rowSize)
359 // Collapse scan lines:
360 rowSize *= h;
361 // We ignore scanlineStride since it won't be of any use
362 h = 1;
365 int outOffset = 0;
366 Object inArray = Buffers.getData(data);
367 for (int yd = 0; yd<h; yd++)
369 System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
370 inOffset += scanlineStride;
371 outOffset += rowSize;
373 return obj;
376 public void setDataElements(int x, int y, int w, int h,
377 Object obj, DataBuffer data)
379 if (!tightPixelPacking)
381 super.setDataElements(x, y, w, h, obj, data);
382 return;
385 // using set speedup, we can copy whole rows
386 int rowSize = w*numBands;
387 int dataSize = rowSize*h;
389 DataBuffer transferBuffer =
390 Buffers.createBufferFromData(getTransferType(), obj, dataSize);
392 int[] bankOffsets = data.getOffsets();
394 int outOffset =
395 pixelStride*x +
396 scanlineStride*y +
397 bankOffsets[0]; // same assuptions as in get...
399 // See if we can copy everything in one go
400 if (scanlineStride == rowSize)
402 // Collapse scan lines:
403 rowSize *= h;
404 h = 1;
407 int inOffset = 0;
408 Object outArray = Buffers.getData(data);
409 for (int yd = 0; yd<h; yd++)
411 System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
412 outOffset += scanlineStride;
413 inOffset += rowSize;
417 public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
419 int offset = pixelStride*x + scanlineStride*y;
420 if (iArray == null) iArray = new int[numBands];
421 for (int b=0; b<numBands; b++)
423 iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
425 return iArray;
428 public int[] getPixels(int x, int y, int w, int h, int[] iArray,
429 DataBuffer data)
431 int offset = pixelStride*x + scanlineStride*y;
432 if (iArray == null) iArray = new int[numBands*w*h];
433 int outOffset = 0;
434 for (y=0; y<h; y++)
436 int lineOffset = offset;
437 for (x=0; x<w; x++)
439 for (int b=0; b<numBands; b++)
441 iArray[outOffset++] =
442 data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
444 lineOffset += pixelStride;
446 offset += scanlineStride;
448 return iArray;
451 public int getSample(int x, int y, int b, DataBuffer data)
453 return data.getElem(bankIndices[b], getOffset(x, y, b));
456 public void setDataElements(int x, int y, Object obj, DataBuffer data)
458 int offset = pixelStride*x + scanlineStride*y;
459 int[] totalBandDataOffsets = new int[numBands];
460 int[] bankOffsets = data.getOffsets();
461 for (int b=0; b<numBands; b++)
462 totalBandDataOffsets[b] =
463 bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
465 switch (getTransferType())
467 case DataBuffer.TYPE_BYTE:
469 DataBufferByte out = (DataBufferByte) data;
470 byte[] in = (byte[]) obj;
472 for (int b=0; b<numBands; b++)
473 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
475 return;
477 case DataBuffer.TYPE_USHORT:
479 DataBufferUShort out = (DataBufferUShort) data;
480 short[] in = (short[]) obj;
482 for (int b=0; b<numBands; b++)
483 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
485 return;
487 case DataBuffer.TYPE_SHORT:
489 DataBufferShort out = (DataBufferShort) data;
490 short[] in = (short[]) obj;
492 for (int b=0; b<numBands; b++)
493 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
495 return;
497 case DataBuffer.TYPE_INT:
499 DataBufferInt out = (DataBufferInt) data;
500 int[] in = (int[]) obj;
502 for (int b=0; b<numBands; b++)
503 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
505 return;
507 case DataBuffer.TYPE_FLOAT:
509 DataBufferFloat out = (DataBufferFloat) data;
510 float[] in = (float[]) obj;
512 for (int b=0; b<numBands; b++)
513 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
515 return;
517 case DataBuffer.TYPE_DOUBLE:
519 DataBufferDouble out = (DataBufferDouble) data;
520 double[] in = (double[]) obj;
522 for (int b=0; b<numBands; b++)
523 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
525 return;
527 default:
528 throw new UnsupportedOperationException("transfer type not " +
529 "implemented");
533 public void setPixel(int x, int y, int[] iArray, DataBuffer data)
535 int offset = pixelStride*x + scanlineStride*y;
536 for (int b=0; b<numBands; b++)
537 data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
540 public void setSample(int x, int y, int b, int s, DataBuffer data)
542 data.setElem(bankIndices[b], getOffset(x, y, b), s);