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 * ComponentSampleModel supports a flexible organization of pixel samples in
45 * memory, permitting pixel samples to be interleaved by band, by scanline,
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
,
84 this(dataType
, w
, h
, pixelStride
, scanlineStride
,
85 new int[bandOffsets
.length
], bandOffsets
);
88 public ComponentSampleModel(int dataType
,
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
;
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;
129 public SampleModel
createCompatibleSampleModel(int w
, int h
)
131 return new ComponentSampleModel(dataType
, w
, h
, pixelStride
,
132 scanlineStride
, bankIndices
,
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
,
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) +
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
);
186 public final int getSampleSize(int band
)
188 return DataBuffer
.getDataTypeSize(getDataType());
191 public final int[] getBankIndices()
196 public final int[] getBandOffsets()
201 public final int getScanlineStride()
203 return scanlineStride
;
206 public final int getPixelStride()
211 public final int getNumDataElements()
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
];
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
];
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
];
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
];
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
];
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
];
317 throw new IllegalStateException("unknown transfer type " +
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
,
333 if (!tightPixelPacking
)
335 return super.getDataElements(x
, y
, w
, h
, obj
, data
);
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
);
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:
361 // We ignore scanlineStride since it won't be of any use
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
;
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
);
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();
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:
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
;
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
]);
428 public int[] getPixels(int x
, int y
, int w
, int h
, int[] iArray
,
431 int offset
= pixelStride
*x
+ scanlineStride
*y
;
432 if (iArray
== null) iArray
= new int[numBands
*w
*h
];
436 int lineOffset
= offset
;
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
;
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
];
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
];
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
];
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
];
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
];
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
];
528 throw new UnsupportedOperationException("transfer type not " +
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
);