Merge from the pain train
[official-gcc.git] / libjava / java / awt / image / SinglePixelPackedSampleModel.java
blob32789fc635026a5116e2494ff66616016bd8ece1
1 /* Copyright (C) 2000, 2002, 2003, 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)
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.BitMaskExtent;
40 import gnu.java.awt.Buffers;
42 /**
43 * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
45 public class SinglePixelPackedSampleModel extends SampleModel
47 private int scanlineStride;
48 private int[] bitMasks;
49 private int[] bitOffsets;
50 private int[] sampleSize;
52 public SinglePixelPackedSampleModel(int dataType, int w, int h,
53 int[] bitMasks)
55 this(dataType, w, h, w, bitMasks);
58 public SinglePixelPackedSampleModel(int dataType, int w, int h,
59 int scanlineStride, int[] bitMasks)
61 super(dataType, w, h, bitMasks.length);
63 switch (dataType)
65 case DataBuffer.TYPE_BYTE:
66 case DataBuffer.TYPE_USHORT:
67 case DataBuffer.TYPE_INT:
68 break;
69 default:
70 throw new IllegalArgumentException("SinglePixelPackedSampleModel unsupported dataType");
73 this.scanlineStride = scanlineStride;
74 this.bitMasks = bitMasks;
76 bitOffsets = new int[numBands];
77 sampleSize = new int[numBands];
79 BitMaskExtent extent = new BitMaskExtent();
80 for (int b=0; b<numBands; b++)
82 extent.setMask(bitMasks[b]);
83 sampleSize[b] = extent.bitWidth;
84 bitOffsets[b] = extent.leastSignificantBit;
88 public int getNumDataElements()
90 return 1;
93 public SampleModel createCompatibleSampleModel(int w, int h)
95 /* FIXME: We can avoid recalculation of bit offsets and sample
96 sizes here by passing these from the current instance to a
97 special private constructor. */
98 return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
103 * Creates a DataBuffer for holding pixel data in the format and
104 * layout described by this SampleModel. The returned buffer will
105 * consist of one single bank.
107 public DataBuffer createDataBuffer()
109 int size;
111 // We can save (scanlineStride - width) pixels at the very end of
112 // the buffer. The Sun reference implementation (J2SE 1.3.1 and
113 // 1.4.1_01) seems to do this; tested with Mauve test code.
114 size = scanlineStride * (height - 1) + width;
116 return Buffers.createBuffer(getDataType(), size);
120 public int[] getSampleSize()
122 return sampleSize;
125 public int getSampleSize(int band)
127 return sampleSize[band];
130 public int getOffset(int x, int y)
132 return scanlineStride*y + x;
135 public int[] getBitOffsets()
137 return bitOffsets;
140 public int[] getBitMasks()
142 return bitMasks;
145 public int getScanlineStride()
147 return scanlineStride;
150 public SampleModel createSubsetSampleModel(int[] bands)
152 // FIXME: Is this the right way to interpret bands?
154 int numBands = bands.length;
156 int[] bitMasks = new int[numBands];
158 for (int b=0; b<numBands; b++)
159 bitMasks[b] = this.bitMasks[bands[b]];
161 return new SinglePixelPackedSampleModel(dataType, width, height,
162 scanlineStride, bitMasks);
165 public Object getDataElements(int x, int y, Object obj,
166 DataBuffer data)
168 int offset = scanlineStride*y + x + data.getOffset();
170 return Buffers.getData(data, offset, obj,
171 0, // destination offset,
172 1 // length
177 * This is a more efficient implementation of the default implementation in the super
178 * class.
179 * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
180 * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
181 * @param w The width of the pixel rectangle to store in <code>obj</code>.
182 * @param h The height of the pixel rectangle to store in <code>obj</code>.
183 * @param obj The primitive array to store the pixels into or null to force creation.
184 * @param data The DataBuffer that is the source of the pixel data.
185 * @return The primitive array containing the pixel data.
186 * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
188 public Object getDataElements(int x, int y, int w, int h, Object obj,
189 DataBuffer data)
191 int size = w*h;
192 int dataSize = size;
193 Object pixelData = null;
194 switch (getTransferType())
196 case DataBuffer.TYPE_BYTE:
197 pixelData = ((DataBufferByte) data).getData();
198 if (obj == null) obj = new byte[dataSize];
199 break;
200 case DataBuffer.TYPE_USHORT:
201 pixelData = ((DataBufferUShort) data).getData();
202 if (obj == null) obj = new short[dataSize];
203 break;
204 case DataBuffer.TYPE_INT:
205 pixelData = ((DataBufferInt) data).getData();
206 if (obj == null) obj = new int[dataSize];
207 break;
208 default:
209 // Seems like the only sensible thing to do.
210 throw new ClassCastException();
212 if(x==0 && scanlineStride == w)
214 // The full width need to be copied therefore we can copy in one shot.
215 System.arraycopy(pixelData, scanlineStride*y + data.getOffset(), obj, 0, size);
217 else
219 // Since we do not need the full width we need to copy line by line.
220 int outOffset = 0;
221 int dataOffset = scanlineStride*y + x + data.getOffset();
222 for (int yy = y; yy<(y+h); yy++)
224 System.arraycopy(pixelData, dataOffset, obj, outOffset, w);
225 dataOffset += scanlineStride;
226 outOffset += w;
229 return obj;
233 public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
235 int offset = scanlineStride*y + x;
236 if (iArray == null) iArray = new int[numBands];
237 int samples = data.getElem(offset);
239 for (int b=0; b<numBands; b++)
240 iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
242 return iArray;
245 public int[] getPixels(int x, int y, int w, int h, int[] iArray,
246 DataBuffer data)
248 int offset = scanlineStride*y + x;
249 if (iArray == null) iArray = new int[numBands*w*h];
250 int outOffset = 0;
251 for (y=0; y<h; y++)
253 int lineOffset = offset;
254 for (x=0; x<w; x++)
256 int samples = data.getElem(lineOffset++);
257 for (int b=0; b<numBands; b++)
258 iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
260 offset += scanlineStride;
262 return iArray;
265 public int getSample(int x, int y, int b, DataBuffer data)
267 int offset = scanlineStride*y + x;
268 int samples = data.getElem(offset);
269 return (samples & bitMasks[b]) >>> bitOffsets[b];
273 * This method implements a more efficient way to set data elements than the default
274 * implementation of the super class. It sets the data elements line by line instead
275 * of pixel by pixel.
276 * @param x The x-coordinate of the data elements in <code>obj</code>.
277 * @param y The y-coordinate of the data elements in <code>obj</code>.
278 * @param w The width of the data elements in <code>obj</code>.
279 * @param h The height of the data elements in <code>obj</code>.
280 * @param obj The primitive array containing the data elements to set.
281 * @param data The DataBuffer to store the data elements into.
282 * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
284 public void setDataElements(int x, int y, int w, int h,
285 Object obj, DataBuffer data)
288 Object pixelData;
289 switch (getTransferType())
291 case DataBuffer.TYPE_BYTE:
292 pixelData = ((DataBufferByte) data).getData();
293 break;
294 case DataBuffer.TYPE_USHORT:
295 pixelData = ((DataBufferUShort) data).getData();
296 break;
297 case DataBuffer.TYPE_INT:
298 pixelData = ((DataBufferInt) data).getData();
299 break;
300 default:
301 // Seems like the only sensible thing to do.
302 throw new ClassCastException();
305 int inOffset = 0;
306 int dataOffset = scanlineStride*y + x + data.getOffset();
307 for (int yy=y; yy<(y+h); yy++)
309 System.arraycopy(obj,inOffset,pixelData,dataOffset,w);
310 dataOffset += scanlineStride;
311 inOffset += w;
316 public void setDataElements(int x, int y, Object obj, DataBuffer data)
318 int offset = scanlineStride*y + x + data.getOffset();
320 int transferType = getTransferType();
321 if (getTransferType() != data.getDataType())
323 throw new IllegalArgumentException("transfer type ("+
324 getTransferType()+"), "+
325 "does not match data "+
326 "buffer type (" +
327 data.getDataType() +
328 ").");
333 switch (transferType)
335 case DataBuffer.TYPE_BYTE:
337 DataBufferByte out = (DataBufferByte) data;
338 byte[] in = (byte[]) obj;
339 out.getData()[offset] = in[0];
340 return;
342 case DataBuffer.TYPE_USHORT:
344 DataBufferUShort out = (DataBufferUShort) data;
345 short[] in = (short[]) obj;
346 out.getData()[offset] = in[0];
347 return;
349 case DataBuffer.TYPE_INT:
351 DataBufferInt out = (DataBufferInt) data;
352 int[] in = (int[]) obj;
353 out.getData()[offset] = in[0];
354 return;
356 // FIXME: Fill in the other possible types.
357 default:
358 throw new InternalError();
361 catch (ArrayIndexOutOfBoundsException aioobe)
363 String msg = "While writing data elements" +
364 ", x="+x+", y="+y+
365 ", width="+width+", height="+height+
366 ", scanlineStride="+scanlineStride+
367 ", offset="+offset+
368 ", data.getSize()="+data.getSize()+
369 ", data.getOffset()="+data.getOffset()+
370 ": " +
371 aioobe;
372 throw new ArrayIndexOutOfBoundsException(msg);
376 public void setPixel(int x, int y, int[] iArray, DataBuffer data)
378 int offset = scanlineStride*y + x;
380 int samples = 0;
381 for (int b=0; b<numBands; b++)
382 samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
384 data.setElem(offset, samples);
388 * This method implements a more efficient way to set pixels than the default
389 * implementation of the super class. It copies the pixel components directly
390 * from the input array instead of creating a intermediate buffer.
391 * @param x The x-coordinate of the pixel rectangle in <code>obj</code>.
392 * @param y The y-coordinate of the pixel rectangle in <code>obj</code>.
393 * @param w The width of the pixel rectangle in <code>obj</code>.
394 * @param h The height of the pixel rectangle in <code>obj</code>.
395 * @param iArray The primitive array containing the pixels to set.
396 * @param data The DataBuffer to store the pixels into.
397 * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[], java.awt.image.DataBuffer)
399 public void setPixels(int x, int y, int w, int h, int[] iArray,
400 DataBuffer data)
402 int inOffset = 0;
403 int[] pixel = new int[numBands];
404 for (int yy=y; yy<(y+h); yy++)
406 int offset = scanlineStride*yy + x;
407 for (int xx=x; xx<(x+w); xx++)
409 int samples = 0;
410 for (int b=0; b<numBands; b++)
411 samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
412 data.setElem(0, offset, samples);
413 inOffset += numBands;
414 offset += 1;
420 public void setSample(int x, int y, int b, int s, DataBuffer data)
422 int offset = scanlineStride*y + x;
423 int samples = data.getElem(offset);
424 int bitMask = bitMasks[b];
425 samples &= ~bitMask;
426 samples |= (s << bitOffsets[b]) & bitMask;
427 data.setElem(offset, samples);
431 * Creates a String with some information about this SampleModel.
432 * @return A String describing this SampleModel.
433 * @see java.lang.Object#toString()
435 public String toString()
437 StringBuffer result = new StringBuffer();
438 result.append(getClass().getName());
439 result.append("[");
440 result.append("scanlineStride=").append(scanlineStride);
441 for(int i=0; i < bitMasks.length; i+=1)
443 result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
446 result.append("]");
447 return result.toString();