1 /* Copyright (C) 2004 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
;
42 * MultiPixelPackedSampleModel provides a single band model that supports
43 * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit
46 * @author Jerry Quinn (jlquinn@optonline.net)
48 public class MultiPixelPackedSampleModel
extends SampleModel
50 private int scanlineStride
;
51 private int[] bitMasks
;
52 private int[] bitOffsets
;
53 private int[] sampleSize
;
54 private int dataBitOffset
;
56 private int numberOfBits
;
59 public MultiPixelPackedSampleModel(int dataType
, int w
, int h
,
62 this(dataType
, w
, h
, numberOfBits
, 0, 0);
65 public MultiPixelPackedSampleModel(int dataType
, int w
, int h
,
66 int numberOfBits
, int scanlineStride
,
69 super(dataType
, w
, h
, 1);
73 case DataBuffer
.TYPE_BYTE
:
76 case DataBuffer
.TYPE_USHORT
:
79 case DataBuffer
.TYPE_INT
:
83 throw new IllegalArgumentException("MultiPixelPackedSampleModel"
84 + " unsupported dataType");
87 this.dataBitOffset
= dataBitOffset
;
89 this.numberOfBits
= numberOfBits
;
90 if (numberOfBits
> elemBits
)
91 throw new RasterFormatException("MultiPixelPackedSampleModel pixel size"
92 + " larger than dataType");
95 case 1: case 2: case 4: case 8: case 16: case 32: break;
97 throw new RasterFormatException("MultiPixelPackedSampleModel pixel"
98 + " size not 2^n bits");
100 numElems
= elemBits
/ numberOfBits
;
102 // Compute scan line large enough for w pixels.
103 if (scanlineStride
== 0)
104 scanlineStride
= ((dataBitOffset
+ w
* numberOfBits
) / elemBits
);
105 this.scanlineStride
= scanlineStride
;
108 sampleSize
= new int[1];
109 sampleSize
[0] = numberOfBits
;
111 bitMasks
= new int[numElems
];
112 bitOffsets
= new int[numElems
];
113 for (int i
=0; i
< numElems
; i
++)
115 bitOffsets
[numElems
- i
- 1] = numberOfBits
* i
;
116 bitMasks
[numElems
- i
- 1] = ((1 << numberOfBits
) - 1) <<
117 bitOffsets
[numElems
- i
- 1];
121 public SampleModel
createCompatibleSampleModel(int w
, int h
)
123 /* FIXME: We can avoid recalculation of bit offsets and sample
124 sizes here by passing these from the current instance to a
125 special private constructor. */
126 return new MultiPixelPackedSampleModel(dataType
, w
, h
, numberOfBits
);
131 * Creates a DataBuffer for holding pixel data in the format and
132 * layout described by this SampleModel. The returned buffer will
133 * consist of one single bank.
135 public DataBuffer
createDataBuffer()
139 // FIXME: The comment refers to SinglePixelPackedSampleModel. See if the
140 // same can be done for MultiPixelPackedSampleModel.
141 // We can save (scanlineStride - width) pixels at the very end of
142 // the buffer. The Sun reference implementation (J2SE 1.3.1 and
143 // 1.4.1_01) seems to do this; tested with Mauve test code.
144 size
= scanlineStride
* height
;
146 return Buffers
.createBuffer(getDataType(), size
);
150 public int getNumDataElements()
155 public int[] getSampleSize()
160 public int getSampleSize(int band
)
162 return sampleSize
[0];
165 public int getOffset(int x
, int y
)
167 return scanlineStride
* y
+ ((dataBitOffset
+ x
*numberOfBits
) / elemBits
);
170 public int getBitOffset(int x
)
172 return (dataBitOffset
+ x
*numberOfBits
) % elemBits
;
175 public int getDataBitOffset()
177 return dataBitOffset
;
180 public int getScanlineStride()
182 return scanlineStride
;
185 public int getPixelBitStride()
191 public SampleModel
createSubsetSampleModel(int[] bands
)
193 int numBands
= bands
.length
;
195 throw new RasterFormatException("MultiPixelPackedSampleModel only"
196 + " supports one band");
198 return new MultiPixelPackedSampleModel(dataType
, width
, height
,
199 numberOfBits
, scanlineStride
,
204 * Extract one pixel and return in an array of transfer type.
206 * Extracts the pixel at x, y from data and stores into the 0th index of the
207 * array obj, since there is only one band. If obj is null, a new array of
208 * getTransferType() is created.
210 * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
211 * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
212 * @param obj The primitive array to store the pixels into or null to force creation.
213 * @param data The DataBuffer that is the source of the pixel data.
214 * @return The primitive array containing the pixel data.
215 * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer)
217 public Object
getDataElements(int x
, int y
, Object obj
,
220 int pixel
= getSample(x
, y
, 0, data
);
221 switch (getTransferType())
223 case DataBuffer
.TYPE_BYTE
:
224 if (obj
== null) obj
= new byte[1];
225 ((byte[])obj
)[0] = (byte)pixel
;
227 case DataBuffer
.TYPE_USHORT
:
228 if (obj
== null) obj
= new short[1];
229 ((short[])obj
)[0] = (short)pixel
;
231 case DataBuffer
.TYPE_INT
:
232 if (obj
== null) obj
= new int[1];
233 ((int[])obj
)[0] = pixel
;
236 // Seems like the only sensible thing to do.
237 throw new ClassCastException();
241 public int[] getPixel(int x
, int y
, int[] iArray
, DataBuffer data
)
243 if (iArray
== null) iArray
= new int[1];
244 iArray
[0] = getSample(x
, y
, 0, data
);
249 public int[] getPixels(int x
, int y
, int w
, int h
, int[] iArray
,
252 int offset
= getOffset(x
, y
);
253 if (iArray
== null) iArray
= new int[w
*h
];
257 int lineOffset
= offset
;
260 int samples
= data
.getElem(lineOffset
++);
261 for (int b
=0; b
<numElems
&& x
<w
; b
++)
263 iArray
[outOffset
++] = (samples
& bitMasks
[b
]) >>> bitOffsets
[b
];
267 offset
+= scanlineStride
;
272 public int getSample(int x
, int y
, int b
, DataBuffer data
)
275 ((dataBitOffset
+ x
* numberOfBits
) % elemBits
) / numberOfBits
;
276 int offset
= getOffset(x
, y
);
277 int samples
= data
.getElem(offset
);
278 return (samples
& bitMasks
[pos
]) >>> bitOffsets
[pos
];
282 * Set the pixel at x, y to the value in the first element of the primitive
285 * @param x The x-coordinate of the data elements in <code>obj</code>.
286 * @param y The y-coordinate of the data elements in <code>obj</code>.
287 * @param obj The primitive array containing the data elements to set.
288 * @param data The DataBuffer to store the data elements into.
289 * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
291 public void setDataElements(int x
, int y
, Object obj
, DataBuffer data
)
293 int transferType
= getTransferType();
294 if (getTransferType() != data
.getDataType())
296 throw new IllegalArgumentException("transfer type ("+
297 getTransferType()+"), "+
298 "does not match data "+
304 int offset
= getOffset(x
, y
);
308 switch (transferType
)
310 case DataBuffer
.TYPE_BYTE
:
312 DataBufferByte out
= (DataBufferByte
) data
;
313 byte[] in
= (byte[]) obj
;
314 out
.getData()[offset
] = in
[0];
317 case DataBuffer
.TYPE_USHORT
:
319 DataBufferUShort out
= (DataBufferUShort
) data
;
320 short[] in
= (short[]) obj
;
321 out
.getData()[offset
] = in
[0];
324 case DataBuffer
.TYPE_INT
:
326 DataBufferInt out
= (DataBufferInt
) data
;
327 int[] in
= (int[]) obj
;
328 out
.getData()[offset
] = in
[0];
332 throw new ClassCastException("Unsupported data type");
335 catch (ArrayIndexOutOfBoundsException aioobe
)
337 String msg
= "While writing data elements" +
339 ", width="+width
+", height="+height
+
340 ", scanlineStride="+scanlineStride
+
342 ", data.getSize()="+data
.getSize()+
343 ", data.getOffset()="+data
.getOffset()+
346 throw new ArrayIndexOutOfBoundsException(msg
);
350 public void setPixel(int x
, int y
, int[] iArray
, DataBuffer data
)
352 setSample(x
, y
, 0, iArray
[0], data
);
355 public void setSample(int x
, int y
, int b
, int s
, DataBuffer data
)
358 ((dataBitOffset
+ x
* numberOfBits
) % elemBits
) / numberOfBits
;
359 int offset
= getOffset(x
, y
);
361 s
= s
<< bitOffsets
[bitpos
];
362 s
= s
& bitMasks
[bitpos
];
364 int sample
= data
.getElem(offset
);
366 data
.setElem(offset
, sample
);
370 * Creates a String with some information about this SampleModel.
371 * @return A String describing this SampleModel.
372 * @see java.lang.Object#toString()
374 public String
toString()
376 StringBuffer result
= new StringBuffer();
377 result
.append(getClass().getName());
379 result
.append("scanlineStride=").append(scanlineStride
);
380 for(int i
=0; i
< bitMasks
.length
; i
+=1)
382 result
.append(", mask[").append(i
).append("]=0x").append(Integer
.toHexString(bitMasks
[i
]));
386 return result
.toString();