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)
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
20 As a special exception, if you link this library with other files to
21 produce an executable, this library does not by itself cause the
22 resulting executable to be covered by the GNU General Public License.
23 This exception does not however invalidate any other reasons why the
24 executable file might be covered by the GNU General Public License. */
26 package java.awt.image;
28 import gnu.java.awt.Buffers;
30 /* FIXME: This class does not yet support data type TYPE_SHORT */
33 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
35 public class ComponentSampleModel extends SampleModel
37 protected int[] bandOffsets;
38 protected int[] bankIndices;
40 // FIXME: Should we really shadow the numBands in the superclass?
41 //protected int numBands;
43 /** Used when creating data buffers. */
44 protected int numBanks;
46 protected int scanlineStride;
48 protected int pixelStride;
50 private boolean tightPixelPacking = false;
52 public ComponentSampleModel(int dataType,
58 this(dataType, w, h, pixelStride, scanlineStride,
59 new int[bandOffsets.length], bandOffsets);
62 public ComponentSampleModel(int dataType,
69 super(dataType, w, h, bandOffsets.length);
70 if ((pixelStride<0) || (scanlineStride<0) ||
71 (bandOffsets.length<1) ||
72 (bandOffsets.length != bankIndices.length))
73 throw new IllegalArgumentException();
75 this.bandOffsets = bandOffsets;
76 this.bankIndices = bankIndices;
78 for (int b=0; b<bankIndices.length; b++)
79 this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
81 this.scanlineStride = scanlineStride;
82 this.pixelStride = pixelStride;
84 // See if we can use some speedups
86 /* FIXME: May these checks should be reserved for the
87 PixelInterleavedSampleModel? */
89 if (pixelStride == numBands)
91 tightPixelPacking = true;
92 for (int b=0; b<numBands; b++) {
93 if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
95 tightPixelPacking = false;
102 public SampleModel createCompatibleSampleModel(int w, int h)
104 return new ComponentSampleModel(dataType, w, h, pixelStride,
105 scanlineStride, bankIndices,
109 public SampleModel createSubsetSampleModel(int[] bands)
111 int numBands = bands.length;
113 int[] bankIndices = new int[numBands];
114 int[] bandOffsets = new int[numBands];
115 for (int b=0; b<numBands; b++)
117 bankIndices[b] = this.bankIndices[bands[b]];
118 bandOffsets[b] = this.bandOffsets[bands[b]];
121 return new ComponentSampleModel(dataType, width, height, pixelStride,
122 scanlineStride, bankIndices,
126 public DataBuffer createDataBuffer()
128 // Maybe this value should be precalculated in the constructor?
129 int highestOffset = 0;
130 for (int b=0; b<numBands; b++)
132 highestOffset = Math.max(highestOffset, bandOffsets[b]);
134 int size = pixelStride*(width-1) + scanlineStride*(height-1) +
137 return Buffers.createBuffer(getDataType(), size, numBanks);
140 public int getOffset(int x, int y)
142 return getOffset(x, y, 0);
145 public int getOffset(int x, int y, int b)
147 return bandOffsets[b] + pixelStride*x + scanlineStride*y;
150 public final int[] getSampleSize()
152 int size = DataBuffer.getDataTypeSize(getDataType());
153 int[] sizes = new int[numBands];
155 java.util.Arrays.fill(sizes, size);
159 public final int getSampleSize(int band)
161 return DataBuffer.getDataTypeSize(getDataType());
164 public final int[] getBankIndices()
169 public final int[] getBandOffsets()
174 public final int getScanlineStride()
176 return scanlineStride;
179 public final int getPixelStride()
184 public final int getNumDataElements()
189 public Object getDataElements(int x, int y, Object obj, DataBuffer data)
191 int xyOffset = pixelStride*x + scanlineStride*y;
193 int[] totalBandDataOffsets = new int[numBands];
195 /* Notice that band and bank offsets are different. Band offsets
196 are managed by the sample model, and bank offsets are managed
197 by the data buffer. Both must be accounted for. */
199 /* FIXME: For single pixels, it is probably easier to simple
200 call getElem instead of calculating the bank offset ourself.
202 On the other hand, then we need to push the value through
203 the int type returned by the getElem method. */
205 int[] bankOffsets = data.getOffsets();
207 for (int b=0; b<numBands; b++)
209 totalBandDataOffsets[b] =
210 bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
215 switch (getTransferType())
217 case DataBuffer.TYPE_BYTE:
218 DataBufferByte inByte = (DataBufferByte) data;
219 byte[] outByte = (byte[]) obj;
220 if (outByte == null) outByte = new byte[numBands];
222 for (int b=0; b<numBands; b++)
224 int dOffset = totalBandDataOffsets[b];
225 outByte[b] = inByte.getData(bankIndices[b])[dOffset];
229 case DataBuffer.TYPE_USHORT:
230 DataBufferUShort inUShort = (DataBufferUShort) data;
231 short[] outUShort = (short[]) obj;
232 if (outUShort == null) outUShort = new short[numBands];
234 for (int b=0; b<numBands; b++)
236 int dOffset = totalBandDataOffsets[b];
237 outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
241 case DataBuffer.TYPE_INT:
242 DataBufferInt inInt = (DataBufferInt) data;
243 int[] outInt = (int[]) obj;
244 if (outInt == null) outInt = new int[numBands];
246 for (int b=0; b<numBands; b++)
248 int dOffset = totalBandDataOffsets[b];
249 outInt[b] = inInt.getData(bankIndices[b])[dOffset];
253 // FIXME: Fill in the other possible types.
255 throw new IllegalStateException("unknown transfer type " +
259 catch (ArrayIndexOutOfBoundsException aioobe)
261 String msg = "While reading data elements, " +
262 "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
263 ", data.getSize()=" + data.getSize() + ": " + aioobe;
264 throw new ArrayIndexOutOfBoundsException(msg);
268 public Object getDataElements(int x, int y, int w, int h, Object obj,
271 if (!tightPixelPacking)
273 return super.getDataElements(x, y, w, h, obj, data);
278 // We can copy whole rows
279 int rowSize = w*numBands;
280 int dataSize = rowSize*h;
282 DataBuffer transferBuffer =
283 Buffers.createBuffer(getTransferType(), obj, dataSize);
284 obj = Buffers.getData(transferBuffer);
289 data.getOffset(); // Assumes only one band is used
291 /* We don't add band offsets since we assume that bands have
292 offsets 0, 1, 2, ... */
294 // See if we can copy everything in one go
295 if (scanlineStride == rowSize)
297 // Collapse scan lines:
299 // We ignore scanlineStride since it won't be of any use
304 Object inArray = Buffers.getData(data);
305 for (int yd = 0; yd<h; yd++)
307 System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
308 inOffset += scanlineStride;
309 outOffset += rowSize;
314 public void setDataElements(int x, int y, int w, int h,
315 Object obj, DataBuffer data)
317 if (!tightPixelPacking)
319 super.setDataElements(x, y, w, h, obj, data);
323 // using set speedup, we can copy whole rows
324 int rowSize = w*numBands;
325 int dataSize = rowSize*h;
327 DataBuffer transferBuffer =
328 Buffers.createBufferFromData(getTransferType(), obj, dataSize);
330 int[] bankOffsets = data.getOffsets();
335 bankOffsets[0]; // same assuptions as in get...
337 // See if we can copy everything in one go
338 if (scanlineStride == rowSize)
340 // Collapse scan lines:
341 scanlineStride = rowSize *= h;
346 Object outArray = Buffers.getData(data);
347 for (int yd = 0; yd<h; yd++)
349 System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
350 outOffset += scanlineStride;
355 public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
357 int offset = pixelStride*x + scanlineStride*y;
358 if (iArray == null) iArray = new int[numBands];
359 for (int b=0; b<numBands; b++)
361 iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
366 public int[] getPixels(int x, int y, int w, int h, int[] iArray,
369 int offset = pixelStride*x + scanlineStride*y;
370 if (iArray == null) iArray = new int[numBands*w*h];
374 int lineOffset = offset;
377 for (int b=0; b<numBands; b++)
379 iArray[outOffset++] =
380 data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
382 lineOffset += pixelStride;
384 offset += scanlineStride;
389 public int getSample(int x, int y, int b, DataBuffer data)
391 return data.getElem(bankIndices[b], getOffset(x, y, b));
394 public void setDataElements(int x, int y, Object obj, DataBuffer data)
396 int offset = pixelStride*x + scanlineStride*y;
397 int[] totalBandDataOffsets = new int[numBands];
398 int[] bankOffsets = data.getOffsets();
399 for (int b=0; b<numBands; b++)
400 totalBandDataOffsets[b] =
401 bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
403 switch (getTransferType())
405 case DataBuffer.TYPE_BYTE:
407 DataBufferByte out = (DataBufferByte) data;
408 byte[] in = (byte[]) obj;
410 for (int b=0; b<numBands; b++)
411 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
415 case DataBuffer.TYPE_USHORT:
417 DataBufferUShort out = (DataBufferUShort) data;
418 short[] in = (short[]) obj;
420 for (int b=0; b<numBands; b++)
421 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
425 case DataBuffer.TYPE_INT:
427 DataBufferInt out = (DataBufferInt) data;
428 int[] in = (int[]) obj;
430 for (int b=0; b<numBands; b++)
431 out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
436 throw new UnsupportedOperationException("transfer type not " +
441 public void setPixel(int x, int y, int[] iArray, DataBuffer data)
443 int offset = pixelStride*x + scanlineStride*y;
444 for (int b=0; b<numBands; b++)
445 data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
448 public void setSample(int x, int y, int b, int s, DataBuffer data)
450 data.setElem(bankIndices[b], getOffset(x, y, b), s);