Merge from the pain train
[official-gcc.git] / libjava / java / awt / image / MultiPixelPackedSampleModel.java
blobab971c0e675b7f963c90880753073ad8e1124118
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)
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.Buffers;
41 /**
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
44 * per data element.
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;
55 private int elemBits;
56 private int numberOfBits;
57 private int numElems;
59 public MultiPixelPackedSampleModel(int dataType, int w, int h,
60 int numberOfBits)
62 this(dataType, w, h, numberOfBits, 0, 0);
65 public MultiPixelPackedSampleModel(int dataType, int w, int h,
66 int numberOfBits, int scanlineStride,
67 int dataBitOffset)
69 super(dataType, w, h, 1);
71 switch (dataType)
73 case DataBuffer.TYPE_BYTE:
74 elemBits = 8;
75 break;
76 case DataBuffer.TYPE_USHORT:
77 elemBits = 16;
78 break;
79 case DataBuffer.TYPE_INT:
80 elemBits = 32;
81 break;
82 default:
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");
93 switch (numberOfBits)
95 case 1: case 2: case 4: case 8: case 16: case 32: break;
96 default:
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()
137 int size;
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()
152 return 1;
155 public int[] getSampleSize()
157 return sampleSize;
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()
187 return numberOfBits;
191 public SampleModel createSubsetSampleModel(int[] bands)
193 int numBands = bands.length;
194 if (numBands != 1)
195 throw new RasterFormatException("MultiPixelPackedSampleModel only"
196 + " supports one band");
198 return new MultiPixelPackedSampleModel(dataType, width, height,
199 numberOfBits, scanlineStride,
200 dataBitOffset);
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,
218 DataBuffer data)
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;
226 return obj;
227 case DataBuffer.TYPE_USHORT:
228 if (obj == null) obj = new short[1];
229 ((short[])obj)[0] = (short)pixel;
230 return obj;
231 case DataBuffer.TYPE_INT:
232 if (obj == null) obj = new int[1];
233 ((int[])obj)[0] = pixel;
234 return obj;
235 default:
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);
246 return iArray;
249 public int[] getPixels(int x, int y, int w, int h, int[] iArray,
250 DataBuffer data)
252 int offset = getOffset(x, y);
253 if (iArray == null) iArray = new int[w*h];
254 int outOffset = 0;
255 for (y=0; y<h; y++)
257 int lineOffset = offset;
258 for (x=0; x<w;)
260 int samples = data.getElem(lineOffset++);
261 for (int b=0; b<numElems && x<w; b++)
263 iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
264 x++;
267 offset += scanlineStride;
269 return iArray;
272 public int getSample(int x, int y, int b, DataBuffer data)
274 int pos =
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
283 * array obj.
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 "+
299 "buffer type (" +
300 data.getDataType() +
301 ").");
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];
315 return;
317 case DataBuffer.TYPE_USHORT:
319 DataBufferUShort out = (DataBufferUShort) data;
320 short[] in = (short[]) obj;
321 out.getData()[offset] = in[0];
322 return;
324 case DataBuffer.TYPE_INT:
326 DataBufferInt out = (DataBufferInt) data;
327 int[] in = (int[]) obj;
328 out.getData()[offset] = in[0];
329 return;
331 default:
332 throw new ClassCastException("Unsupported data type");
335 catch (ArrayIndexOutOfBoundsException aioobe)
337 String msg = "While writing data elements" +
338 ", x="+x+", y="+y+
339 ", width="+width+", height="+height+
340 ", scanlineStride="+scanlineStride+
341 ", offset="+offset+
342 ", data.getSize()="+data.getSize()+
343 ", data.getOffset()="+data.getOffset()+
344 ": " +
345 aioobe;
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)
357 int bitpos =
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);
365 sample |= s;
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());
378 result.append("[");
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]));
385 result.append("]");
386 return result.toString();