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;
40 * MultiPixelPackedSampleModel provides a single band model that supports
41 * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit
44 * @author Jerry Quinn <jlquinn@optonline.net>
46 public final class BandedSampleModel extends ComponentSampleModel
48 private int[] bitMasks;
49 private int[] bitOffsets;
50 private int[] sampleSize;
51 private int dataBitOffset;
53 private int numberOfBits;
56 public BandedSampleModel(int dataType, int w, int h, int numBands)
58 super(dataType, w, h, 1, w, new int[numBands]);
61 public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
62 int[] bankIndices, int[] bandOffsets)
64 super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
67 public SampleModel createCompatibleSampleModel(int w, int h)
69 // NOTE: blackdown 1.4.1 sets all offsets to 0. Sun's 1.4.2 docs
72 // Compress offsets so minimum is 0, others w*scanlineStride
73 int[] newoffsets = new int[bandOffsets.length];
74 int[] order = new int[bandOffsets.length];
75 for (int i=0; i < bandOffsets.length; i++)
77 // FIXME: This is N^2, but not a big issue, unless there's a lot of
79 for (int i=0; i < bandOffsets.length; i++)
80 for (int j=i+1; j < bandOffsets.length; i++)
81 if (bankIndices[order[i]] > bankIndices[order[j]]
82 || (bankIndices[order[i]] == bankIndices[order[j]]
83 && bandOffsets[order[i]] > bandOffsets[order[j]]))
85 int t = order[i]; order[i] = order[j]; order[j] = t;
89 for (int i=0; i < bandOffsets.length; i++)
91 if (bankIndices[order[i]] != bank)
93 bank = bankIndices[order[i]];
96 newoffsets[order[i]] = offset;
97 offset += w * scanlineStride;
100 return new BandedSampleModel(dataType, w, h, scanlineStride, bankIndices, newoffsets);
104 public SampleModel createSubsetSampleModel(int[] bands)
106 int[] newoff = new int[bands.length];
107 int[] newbanks = new int[bands.length];
108 for (int i=0; i < bands.length; i++)
111 newoff[i] = bandOffsets[b];
112 newbanks[i] = bankIndices[b];
115 if (bands.length > bankIndices.length)
117 RasterFormatException("BandedSampleModel createSubsetSampleModel too"
120 return new BandedSampleModel(dataType, width, height, scanlineStride,
125 * Extract all samples of one pixel and return in an array of transfer type.
127 * Extracts the pixel at x, y from data and stores samples into the array
128 * obj. If obj is null, a new array of getTransferType() is created.
130 * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
131 * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
132 * @param obj The primitive array to store the pixels into or null to force creation.
133 * @param data The DataBuffer that is the source of the pixel data.
134 * @return The primitive array containing the pixel data.
135 * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer)
137 public Object getDataElements(int x, int y, Object obj,
140 int pixel = getSample(x, y, 0, data);
141 switch (getTransferType())
143 case DataBuffer.TYPE_BYTE:
145 byte[] b = (byte[])obj;
146 if (b == null) b = new byte[numBands];
147 for (int i=0; i < numBands; i++)
148 b[i] = (byte)getSample(x, y, i, data);
151 case DataBuffer.TYPE_SHORT:
152 case DataBuffer.TYPE_USHORT:
154 short[] b = (short[])obj;
155 if (b == null) b = new short[numBands];
156 for (int i=0; i < numBands; i++)
157 b[i] = (short)getSample(x, y, i, data);
160 case DataBuffer.TYPE_INT:
162 int[] b = (int[])obj;
163 if (b == null) b = new int[numBands];
164 for (int i=0; i < numBands; i++)
165 b[i] = getSample(x, y, i, data);
168 case DataBuffer.TYPE_FLOAT:
170 float[] b = (float[])obj;
171 if (b == null) b = new float[numBands];
172 for (int i=0; i < numBands; i++)
173 b[i] = getSampleFloat(x, y, i, data);
176 case DataBuffer.TYPE_DOUBLE:
178 double[] b = (double[])obj;
179 if (b == null) b = new double[numBands];
180 for (int i=0; i < numBands; i++)
181 b[i] = getSample(x, y, i, data);
186 // Seems like the only sensible thing to do.
187 throw new ClassCastException();
191 public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
193 if (iArray == null) iArray = new int[numBands];
194 for (int i=0; i < numBands; i++)
195 iArray[i] = getSample(x, y, 0, data);
201 * Copy pixels from a region into an array.
203 * Copies the samples of the pixels in the rectangle starting at x, y that
204 * is w pixels wide and h scanlines high. When there is more than one band,
205 * the samples stored in order before the next pixel. This ordering isn't
206 * well specified in Sun's docs as of 1.4.2.
208 * If iArray is null, a new array is allocated, filled, and returned.
210 * @param x The x-coordinate of the pixel rectangle to store in
211 * <code>iArray</code>.
212 * @param y The y-coordinate of the pixel rectangle to store in
213 * <code>iArray</code>.
214 * @param w The width in pixels of the rectangle.
215 * @param h The height in pixels of the rectangle.
216 * @param iArray The int array to store the pixels into or null to force
218 * @param data The DataBuffer that is the source of the pixel data.
219 * @return The primitive array containing the pixel data.
221 public int[] getPixels(int x, int y, int w, int h, int[] iArray,
224 if (iArray == null) iArray = new int[w*h*numBands];
230 for (int b=0; b < numBands; b++)
232 int offset = bandOffsets[b] + y * scanlineStride + x;
233 iArray[outOffset++] =
234 data.getElem(bankIndices[b], offset);
241 public int getSample(int x, int y, int b, DataBuffer data)
243 int offset = bandOffsets[b] + y * scanlineStride + x;
244 return data.getElem(bankIndices[b], offset);
247 public float getSampleFloat(int x, int y, int b, DataBuffer data)
249 int offset = bandOffsets[b] + y * scanlineStride + x;
250 return data.getElemFloat(bankIndices[b], offset);
253 public double getSampleDouble(int x, int y, int b, DataBuffer data)
255 int offset = bandOffsets[b] + y * scanlineStride + x;
256 return data.getElemDouble(bankIndices[b], offset);
260 * Copy one band's samples from a region into an array.
262 * Copies from one band the samples of the pixels in the rectangle starting
263 * at x, y that is w pixels wide and h scanlines high.
265 * If iArray is null, a new array is allocated, filled, and returned.
267 * @param x The x-coordinate of the pixel rectangle to store in
268 * <code>iArray</code>.
269 * @param y The y-coordinate of the pixel rectangle to store in
270 * <code>iArray</code>.
271 * @param w The width in pixels of the rectangle.
272 * @param h The height in pixels of the rectangle.
273 * @param b The band to retrieve.
274 * @param iArray The int array to store the pixels into or null to force
276 * @param data The DataBuffer that is the source of the pixel data.
277 * @return The primitive array containing the pixel data.
279 public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray,
282 if (iArray == null) iArray = new int[w*h];
288 int offset = bandOffsets[b] + y * scanlineStride + x;
289 iArray[outOffset++] =
290 data.getElem(bankIndices[b], offset);
298 * Set the pixel at x, y to the value in the first element of the primitive
301 * @param x The x-coordinate of the data elements in <code>obj</code>.
302 * @param y The y-coordinate of the data elements in <code>obj</code>.
303 * @param obj The primitive array containing the data elements to set.
304 * @param data The DataBuffer to store the data elements into.
305 * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
307 public void setDataElements(int x, int y, Object obj, DataBuffer data)
309 int transferType = getTransferType();
310 if (getTransferType() != data.getDataType())
312 throw new IllegalArgumentException("transfer type ("+
313 getTransferType()+"), "+
314 "does not match data "+
320 int offset = y * scanlineStride + x;
324 switch (transferType)
326 case DataBuffer.TYPE_BYTE:
328 DataBufferByte out = (DataBufferByte) data;
329 byte[] in = (byte[]) obj;
330 for (int i=0; i < numBands; i++)
331 out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
334 case DataBuffer.TYPE_SHORT:
336 DataBufferShort out = (DataBufferShort) data;
337 short[] in = (short[]) obj;
338 for (int i=0; i < numBands; i++)
339 out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
342 case DataBuffer.TYPE_USHORT:
344 DataBufferUShort out = (DataBufferUShort) data;
345 short[] in = (short[]) obj;
346 for (int i=0; i < numBands; i++)
347 out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
350 case DataBuffer.TYPE_INT:
352 DataBufferInt out = (DataBufferInt) data;
353 int[] in = (int[]) obj;
354 for (int i=0; i < numBands; i++)
355 out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
358 case DataBuffer.TYPE_FLOAT:
360 DataBufferFloat out = (DataBufferFloat) data;
361 float[] in = (float[]) obj;
362 for (int i=0; i < numBands; i++)
363 out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
366 case DataBuffer.TYPE_DOUBLE:
368 DataBufferDouble out = (DataBufferDouble) data;
369 double[] in = (double[]) obj;
370 for (int i=0; i < numBands; i++)
371 out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[0];
375 throw new ClassCastException("Unsupported data type");
378 catch (ArrayIndexOutOfBoundsException aioobe)
380 String msg = "While writing data elements" +
382 ", width="+width+", height="+height+
383 ", scanlineStride="+scanlineStride+
385 ", data.getSize()="+data.getSize()+
386 ", data.getOffset()="+data.getOffset()+
389 throw new ArrayIndexOutOfBoundsException(msg);
393 public void setPixel(int x, int y, int[] iArray, DataBuffer data)
395 for (int b=0; b < numBands; b++)
396 data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
400 public void setPixels(int x, int y, int w, int h, int[] iArray,
404 for (int hh = 0; hh < h; hh++)
406 for (int ww = 0; ww < w; ww++)
408 int offset = y * scanlineStride + (x + ww);
409 for (int b=0; b < numBands; b++)
410 data.setElem(bankIndices[b], bandOffsets[b] + offset,
417 public void setSample(int x, int y, int b, int s, DataBuffer data)
419 data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
422 public void setSample(int x, int y, int b, float s, DataBuffer data)
424 data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
427 public void setSample(int x, int y, int b, double s, DataBuffer data)
429 data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
432 public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
437 switch (getTransferType())
439 case DataBuffer.TYPE_BYTE:
441 DataBufferByte out = (DataBufferByte) data;
442 byte[] bank = out.getData(bankIndices[b]);
443 for (int hh = 0; hh < h; hh++)
445 for (int ww = 0; ww < w; ww++)
447 int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
448 bank[offset] = (byte)iArray[inOffset++];
454 case DataBuffer.TYPE_SHORT:
456 DataBufferShort out = (DataBufferShort) data;
457 short[] bank = out.getData(bankIndices[b]);
458 for (int hh = 0; hh < h; hh++)
460 for (int ww = 0; ww < w; ww++)
462 int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
463 bank[offset] = (short)iArray[inOffset++];
469 case DataBuffer.TYPE_USHORT:
471 DataBufferShort out = (DataBufferShort) data;
472 short[] bank = out.getData(bankIndices[b]);
473 for (int hh = 0; hh < h; hh++)
475 for (int ww = 0; ww < w; ww++)
477 int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
478 bank[offset] = (short)iArray[inOffset++];
484 case DataBuffer.TYPE_INT:
486 DataBufferInt out = (DataBufferInt) data;
487 int[] bank = out.getData(bankIndices[b]);
488 for (int hh = 0; hh < h; hh++)
490 for (int ww = 0; ww < w; ww++)
492 int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
493 bank[offset] = iArray[inOffset++];
499 case DataBuffer.TYPE_FLOAT:
500 case DataBuffer.TYPE_DOUBLE:
503 throw new ClassCastException("Unsupported data type");
506 // Default implementation probably slower for float and double
507 for (int hh = 0; hh < h; hh++)
509 for (int ww = 0; ww < w; ww++)
511 int offset = bandOffsets[b] + y * scanlineStride + (x + ww);
512 data.setElem(bankIndices[b], offset, iArray[inOffset++]);
519 * Creates a String with some information about this SampleModel.
520 * @return A String describing this SampleModel.
521 * @see java.lang.Object#toString()
523 public String toString()
525 StringBuffer result = new StringBuffer();
526 result.append(getClass().getName());
528 result.append("scanlineStride=").append(scanlineStride);
529 for(int i=0; i < bitMasks.length; i+=1)
531 result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
535 return result.toString();