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 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
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 */
44 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
46 public class ComponentSampleModel
extends SampleModel
48 protected int[] bandOffsets
;
49 protected int[] bankIndices
;
51 // FIXME: Should we really shadow the numBands in the superclass?
52 //protected int numBands;
54 /** Used when creating data buffers. */
55 protected int numBanks
;
57 protected int scanlineStride
;
59 protected int pixelStride
;
61 private boolean tightPixelPacking
= false;
63 public ComponentSampleModel(int dataType
,
69 this(dataType
, w
, h
, pixelStride
, scanlineStride
,
70 new int[bandOffsets
.length
], bandOffsets
);
73 public ComponentSampleModel(int dataType
,
80 super(dataType
, w
, h
, bandOffsets
.length
);
81 if ((pixelStride
<0) || (scanlineStride
<0) ||
82 (bandOffsets
.length
<1) ||
83 (bandOffsets
.length
!= bankIndices
.length
))
84 throw new IllegalArgumentException();
86 this.bandOffsets
= bandOffsets
;
87 this.bankIndices
= bankIndices
;
89 for (int b
=0; b
<bankIndices
.length
; b
++)
90 this.numBanks
= Math
.max(this.numBanks
, bankIndices
[b
]+1);
92 this.scanlineStride
= scanlineStride
;
93 this.pixelStride
= pixelStride
;
95 // See if we can use some speedups
97 /* FIXME: May these checks should be reserved for the
98 PixelInterleavedSampleModel? */
100 if (pixelStride
== numBands
)
102 tightPixelPacking
= true;
103 for (int b
=0; b
<numBands
; b
++) {
104 if ((bandOffsets
[b
] != b
) || (bankIndices
[b
] !=0))
106 tightPixelPacking
= false;
113 public SampleModel
createCompatibleSampleModel(int w
, int h
)
115 return new ComponentSampleModel(dataType
, w
, h
, pixelStride
,
116 scanlineStride
, bankIndices
,
120 public SampleModel
createSubsetSampleModel(int[] bands
)
122 int numBands
= bands
.length
;
124 int[] bankIndices
= new int[numBands
];
125 int[] bandOffsets
= new int[numBands
];
126 for (int b
=0; b
<numBands
; b
++)
128 bankIndices
[b
] = this.bankIndices
[bands
[b
]];
129 bandOffsets
[b
] = this.bandOffsets
[bands
[b
]];
132 return new ComponentSampleModel(dataType
, width
, height
, pixelStride
,
133 scanlineStride
, bankIndices
,
137 public DataBuffer
createDataBuffer()
139 // Maybe this value should be precalculated in the constructor?
140 int highestOffset
= 0;
141 for (int b
=0; b
<numBands
; b
++)
143 highestOffset
= Math
.max(highestOffset
, bandOffsets
[b
]);
145 int size
= pixelStride
*(width
-1) + scanlineStride
*(height
-1) +
148 return Buffers
.createBuffer(getDataType(), size
, numBanks
);
151 public int getOffset(int x
, int y
)
153 return getOffset(x
, y
, 0);
156 public int getOffset(int x
, int y
, int b
)
158 return bandOffsets
[b
] + pixelStride
*x
+ scanlineStride
*y
;
161 public final int[] getSampleSize()
163 int size
= DataBuffer
.getDataTypeSize(getDataType());
164 int[] sizes
= new int[numBands
];
166 java
.util
.Arrays
.fill(sizes
, size
);
170 public final int getSampleSize(int band
)
172 return DataBuffer
.getDataTypeSize(getDataType());
175 public final int[] getBankIndices()
180 public final int[] getBandOffsets()
185 public final int getScanlineStride()
187 return scanlineStride
;
190 public final int getPixelStride()
195 public final int getNumDataElements()
200 public Object
getDataElements(int x
, int y
, Object obj
, DataBuffer data
)
202 int xyOffset
= pixelStride
*x
+ scanlineStride
*y
;
204 int[] totalBandDataOffsets
= new int[numBands
];
206 /* Notice that band and bank offsets are different. Band offsets
207 are managed by the sample model, and bank offsets are managed
208 by the data buffer. Both must be accounted for. */
210 /* FIXME: For single pixels, it is probably easier to simple
211 call getElem instead of calculating the bank offset ourself.
213 On the other hand, then we need to push the value through
214 the int type returned by the getElem method. */
216 int[] bankOffsets
= data
.getOffsets();
218 for (int b
=0; b
<numBands
; b
++)
220 totalBandDataOffsets
[b
] =
221 bandOffsets
[b
]+bankOffsets
[bankIndices
[b
]] + xyOffset
;
226 switch (getTransferType())
228 case DataBuffer
.TYPE_BYTE
:
229 DataBufferByte inByte
= (DataBufferByte
) data
;
230 byte[] outByte
= (byte[]) obj
;
231 if (outByte
== null) outByte
= new byte[numBands
];
233 for (int b
=0; b
<numBands
; b
++)
235 int dOffset
= totalBandDataOffsets
[b
];
236 outByte
[b
] = inByte
.getData(bankIndices
[b
])[dOffset
];
240 case DataBuffer
.TYPE_USHORT
:
241 DataBufferUShort inUShort
= (DataBufferUShort
) data
;
242 short[] outUShort
= (short[]) obj
;
243 if (outUShort
== null) outUShort
= new short[numBands
];
245 for (int b
=0; b
<numBands
; b
++)
247 int dOffset
= totalBandDataOffsets
[b
];
248 outUShort
[b
] = inUShort
.getData(bankIndices
[b
])[dOffset
];
252 case DataBuffer
.TYPE_INT
:
253 DataBufferInt inInt
= (DataBufferInt
) data
;
254 int[] outInt
= (int[]) obj
;
255 if (outInt
== null) outInt
= new int[numBands
];
257 for (int b
=0; b
<numBands
; b
++)
259 int dOffset
= totalBandDataOffsets
[b
];
260 outInt
[b
] = inInt
.getData(bankIndices
[b
])[dOffset
];
264 // FIXME: Fill in the other possible types.
266 throw new IllegalStateException("unknown transfer type " +
270 catch (ArrayIndexOutOfBoundsException aioobe
)
272 String msg
= "While reading data elements, " +
273 "x=" + x
+ ", y=" + y
+", " + ", xyOffset=" + xyOffset
+
274 ", data.getSize()=" + data
.getSize() + ": " + aioobe
;
275 throw new ArrayIndexOutOfBoundsException(msg
);
279 public Object
getDataElements(int x
, int y
, int w
, int h
, Object obj
,
282 if (!tightPixelPacking
)
284 return super.getDataElements(x
, y
, w
, h
, obj
, data
);
289 // We can copy whole rows
290 int rowSize
= w
*numBands
;
291 int dataSize
= rowSize
*h
;
293 DataBuffer transferBuffer
=
294 Buffers
.createBuffer(getTransferType(), obj
, dataSize
);
295 obj
= Buffers
.getData(transferBuffer
);
300 data
.getOffset(); // Assumes only one band is used
302 /* We don't add band offsets since we assume that bands have
303 offsets 0, 1, 2, ... */
305 // See if we can copy everything in one go
306 if (scanlineStride
== rowSize
)
308 // Collapse scan lines:
310 // We ignore scanlineStride since it won't be of any use
315 Object inArray
= Buffers
.getData(data
);
316 for (int yd
= 0; yd
<h
; yd
++)
318 System
.arraycopy(inArray
, inOffset
, obj
, outOffset
, rowSize
);
319 inOffset
+= scanlineStride
;
320 outOffset
+= rowSize
;
325 public void setDataElements(int x
, int y
, int w
, int h
,
326 Object obj
, DataBuffer data
)
328 if (!tightPixelPacking
)
330 super.setDataElements(x
, y
, w
, h
, obj
, data
);
334 // using set speedup, we can copy whole rows
335 int rowSize
= w
*numBands
;
336 int dataSize
= rowSize
*h
;
338 DataBuffer transferBuffer
=
339 Buffers
.createBufferFromData(getTransferType(), obj
, dataSize
);
341 int[] bankOffsets
= data
.getOffsets();
346 bankOffsets
[0]; // same assuptions as in get...
348 // See if we can copy everything in one go
349 if (scanlineStride
== rowSize
)
351 // Collapse scan lines:
352 scanlineStride
= rowSize
*= h
;
357 Object outArray
= Buffers
.getData(data
);
358 for (int yd
= 0; yd
<h
; yd
++)
360 System
.arraycopy(obj
, inOffset
, outArray
, outOffset
, rowSize
);
361 outOffset
+= scanlineStride
;
366 public int[] getPixel(int x
, int y
, int[] iArray
, DataBuffer data
)
368 int offset
= pixelStride
*x
+ scanlineStride
*y
;
369 if (iArray
== null) iArray
= new int[numBands
];
370 for (int b
=0; b
<numBands
; b
++)
372 iArray
[b
] = data
.getElem(bankIndices
[b
], offset
+bandOffsets
[b
]);
377 public int[] getPixels(int x
, int y
, int w
, int h
, int[] iArray
,
380 int offset
= pixelStride
*x
+ scanlineStride
*y
;
381 if (iArray
== null) iArray
= new int[numBands
*w
*h
];
385 int lineOffset
= offset
;
388 for (int b
=0; b
<numBands
; b
++)
390 iArray
[outOffset
++] =
391 data
.getElem(bankIndices
[b
], lineOffset
+bandOffsets
[b
]);
393 lineOffset
+= pixelStride
;
395 offset
+= scanlineStride
;
400 public int getSample(int x
, int y
, int b
, DataBuffer data
)
402 return data
.getElem(bankIndices
[b
], getOffset(x
, y
, b
));
405 public void setDataElements(int x
, int y
, Object obj
, DataBuffer data
)
407 int offset
= pixelStride
*x
+ scanlineStride
*y
;
408 int[] totalBandDataOffsets
= new int[numBands
];
409 int[] bankOffsets
= data
.getOffsets();
410 for (int b
=0; b
<numBands
; b
++)
411 totalBandDataOffsets
[b
] =
412 bandOffsets
[b
]+bankOffsets
[bankIndices
[b
]] + offset
;
414 switch (getTransferType())
416 case DataBuffer
.TYPE_BYTE
:
418 DataBufferByte out
= (DataBufferByte
) data
;
419 byte[] in
= (byte[]) obj
;
421 for (int b
=0; b
<numBands
; b
++)
422 out
.getData(bankIndices
[b
])[totalBandDataOffsets
[b
]] = in
[b
];
426 case DataBuffer
.TYPE_USHORT
:
428 DataBufferUShort out
= (DataBufferUShort
) data
;
429 short[] in
= (short[]) obj
;
431 for (int b
=0; b
<numBands
; b
++)
432 out
.getData(bankIndices
[b
])[totalBandDataOffsets
[b
]] = in
[b
];
436 case DataBuffer
.TYPE_INT
:
438 DataBufferInt out
= (DataBufferInt
) data
;
439 int[] in
= (int[]) obj
;
441 for (int b
=0; b
<numBands
; b
++)
442 out
.getData(bankIndices
[b
])[totalBandDataOffsets
[b
]] = in
[b
];
447 throw new UnsupportedOperationException("transfer type not " +
452 public void setPixel(int x
, int y
, int[] iArray
, DataBuffer data
)
454 int offset
= pixelStride
*x
+ scanlineStride
*y
;
455 for (int b
=0; b
<numBands
; b
++)
456 data
.setElem(bankIndices
[b
], offset
+bandOffsets
[b
], iArray
[b
]);
459 public void setSample(int x
, int y
, int b
, int s
, DataBuffer data
)
461 data
.setElem(bankIndices
[b
], getOffset(x
, y
, b
), s
);