2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 * @author Igor V. Stolyarov
21 package java.awt.image;
23 import java.util.Arrays;
25 import org.apache.harmony.awt.internal.nls.Messages;
28 * The SinglePixelPackedSampleModel class represents pixel data
29 * where several samples combine to create a single pixel and
30 * are stored in a single data array element. This class
31 * supports TYPE_BYTE, TYPE_USHORT, TYPE_INT data types.
33 public class SinglePixelPackedSampleModel extends SampleModel {
36 private int bitMasks[];
38 /** The bit offsets. */
39 private int bitOffsets[];
42 private int bitSizes[];
44 /** The scanline stride. */
45 private int scanlineStride;
47 /** The max bit size. */
48 private int maxBitSize;
51 * Instantiates a new SinglePixelPackedSampleModel with the specified
54 * @param dataType the data type of samples.
55 * @param w the width of the image data.
56 * @param h the height of the image data.
57 * @param bitMasks the bit masks for all the bands.
59 public SinglePixelPackedSampleModel(int dataType, int w, int h,
61 this(dataType, w, h, w, bitMasks);
65 * Instantiates a new SinglePixelPackedSampleModel with the specified
68 * @param dataType the data type of the samples.
69 * @param w the width of the image data.
70 * @param h the height of the image data.
71 * @param scanlineStride The scanline stride of the image data.
72 * @param bitMasks the bit masks for all the bands.
74 public SinglePixelPackedSampleModel(int dataType, int w, int h,
75 int scanlineStride, int bitMasks[]) {
77 super(dataType, w, h, bitMasks.length);
79 if (dataType != DataBuffer.TYPE_BYTE &&
80 dataType != DataBuffer.TYPE_USHORT &&
81 dataType != DataBuffer.TYPE_INT) {
82 // awt.61=Unsupported data type: {0}
83 throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
87 this.scanlineStride = scanlineStride;
88 this.bitMasks = bitMasks.clone();
89 this.bitOffsets = new int[this.numBands];
90 this.bitSizes = new int[this.numBands];
94 for (int i = 0; i < this.numBands; i++) {
97 int mask = bitMasks[i];
100 while ((mask & 1) == 0) {
105 while ((mask & 1) == 1) {
111 // awt.62=Wrong mask : {0}
112 throw new IllegalArgumentException(Messages.getString(
113 "awt.62", bitMasks[i])); //$NON-NLS-1$
117 this.bitOffsets[i] = offset;
118 this.bitSizes[i] = size;
120 if (this.maxBitSize < size) {
121 this.maxBitSize = size;
129 public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
130 if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
131 // awt.63=Coordinates are not in bounds
132 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
134 switch (getTransferType()) {
135 case DataBuffer.TYPE_BYTE:
140 bdata = (byte[]) obj;
143 bdata[0] = (byte) data.getElem(y * scanlineStride + x);
146 case DataBuffer.TYPE_USHORT:
149 sdata = new short[1];
151 sdata = (short[]) obj;
154 sdata[0] = (short) data.getElem(y * scanlineStride + x);
157 case DataBuffer.TYPE_INT:
165 idata[0] = data.getElem(y * scanlineStride + x);
173 public void setDataElements(int x, int y, Object obj, DataBuffer data) {
174 if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
175 // awt.63=Coordinates are not in bounds
176 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
178 switch (getTransferType()) {
179 case DataBuffer.TYPE_BYTE:
180 data.setElem(y * scanlineStride + x, ((byte[]) obj)[0] & 0xff);
182 case DataBuffer.TYPE_USHORT:
183 data.setElem(y * scanlineStride + x, ((short[]) obj)[0] & 0xffff);
185 case DataBuffer.TYPE_INT:
186 data.setElem(y * scanlineStride + x, ((int[]) obj)[0]);
192 * Compares this SinglePixelPackedSampleModel object with
193 * the specified object.
195 * @param o the Object to be compared.
197 * @return true, if this SinglePixelPackedSampleModel object is
198 * equal to the specified object, false otherwise.
201 public boolean equals(Object o) {
202 if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
206 SinglePixelPackedSampleModel model = (SinglePixelPackedSampleModel) o;
207 return this.width == model.width &&
208 this.height == model.height &&
209 this.numBands == model.numBands &&
210 this.dataType == model.dataType &&
211 Arrays.equals(this.bitMasks, model.bitMasks) &&
212 Arrays.equals(this.bitOffsets, model.bitOffsets) &&
213 Arrays.equals(this.bitSizes, model.bitSizes) &&
214 this.scanlineStride == model.scanlineStride;
218 public SampleModel createSubsetSampleModel(int bands[]) {
219 if (bands.length > this.numBands) {
220 // awt.64=The number of the bands in the subset is greater than the number of bands in the sample model
221 throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
224 int masks[] = new int[bands.length];
225 for (int i = 0; i < bands.length; i++) {
226 masks[i] = this.bitMasks[bands[i]];
228 return new SinglePixelPackedSampleModel(this.dataType, this.width,
229 this.height, this.scanlineStride, masks);
233 public SampleModel createCompatibleSampleModel(int w, int h) {
234 return new SinglePixelPackedSampleModel(this.dataType, w, h,
239 public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
240 if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
241 // awt.63=Coordinates are not in bounds
242 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
245 if (iArray == null) {
246 pixel = new int[this.numBands];
251 for (int i = 0; i < this.numBands; i++) {
252 pixel[i] = getSample(x, y, i, data);
259 public void setPixel(int x, int y, int iArray[], DataBuffer data) {
260 if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
261 // awt.63=Coordinates are not in bounds
262 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
264 for (int i = 0; i < this.numBands; i++) {
265 setSample(x, y, i, iArray[i], data);
270 public int getSample(int x, int y, int b, DataBuffer data) {
271 if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
272 // awt.63=Coordinates are not in bounds
273 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
275 int sample = data.getElem(y * scanlineStride + x);
276 return ((sample & this.bitMasks[b]) >>> this.bitOffsets[b]);
280 public int[] getPixels(int x, int y, int w, int h, int iArray[],
282 if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
283 || ((long) y + (long) h > this.height)) {
284 // awt.63=Coordinates are not in bounds
285 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
290 if (iArray == null) {
291 pixels = new int[w * h * this.numBands];
298 for (int i = y; i < y + h; i++) {
299 for (int j = x; j < x + w; j++) {
300 for (int n = 0; n < this.numBands; n++) {
301 pixels[idx++] = getSample(j, i, n, data);
309 public void setPixels(int x, int y, int w, int h, int iArray[],
311 if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
312 || ((long) y + (long) h > this.height)) {
313 // awt.63=Coordinates are not in bounds
314 throw new ArrayIndexOutOfBoundsException(Messages
315 .getString("awt.63")); //$NON-NLS-1$
320 for (int i = y; i < y + h; i++) {
321 for (int j = x; j < x + w; j++) {
322 for (int n = 0; n < this.numBands; n++) {
323 setSample(j, i, n, iArray[idx++], data);
330 public void setSample(int x, int y, int b, int s, DataBuffer data) {
331 if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
332 // awt.63=Coordinates are not in bounds
333 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
335 int tmp = data.getElem(y * scanlineStride + x);
336 tmp &= ~this.bitMasks[b];
337 tmp |= (s << this.bitOffsets[b]) & this.bitMasks[b];
338 data.setElem(y * scanlineStride + x, tmp);
342 public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
344 if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
345 || ((long) y + (long) h > this.height)) {
346 // awt.63=Coordinates are not in bounds
347 throw new ArrayIndexOutOfBoundsException(Messages
348 .getString("awt.63")); //$NON-NLS-1$
354 if (iArray == null) {
355 samples = new int[w * h];
360 for (int i = y; i < y + h; i++) {
361 for (int j = x; j < x + w; j++) {
362 samples[idx++] = getSample(j, i, b, data);
370 public void setSamples(int x, int y, int w, int h, int b, int iArray[],
372 if ((x < 0) || (y < 0) || ((long) x + (long) w > this.width)
373 || ((long) y + (long) h > this.height)) {
374 // awt.63=Coordinates are not in bounds
375 throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
379 for (int i = y; i < y + h; i++) {
380 for (int j = x; j < x + w; j++) {
381 setSample(x + j, y + i, b, iArray[idx++], data);
387 public DataBuffer createDataBuffer() {
388 DataBuffer data = null;
389 int size = (this.height - 1) * scanlineStride + width;
391 switch (this.dataType) {
392 case DataBuffer.TYPE_BYTE:
393 data = new DataBufferByte(size);
395 case DataBuffer.TYPE_USHORT:
396 data = new DataBufferUShort(size);
398 case DataBuffer.TYPE_INT:
399 data = new DataBufferInt(size);
406 * Gets the offset of the specified pixel in the data array.
408 * @param x the X coordinate of the specified pixel.
409 * @param y the Y coordinate of the specified pixel.
411 * @return the offset of the specified pixel.
413 public int getOffset(int x, int y) {
414 return (y * scanlineStride + x);
418 public int getSampleSize(int band) {
419 return bitSizes[band];
423 public int[] getSampleSize() {
424 return bitSizes.clone();
428 * Gets an array of the bit offsets of the data array elements.
430 * @return an array of the bit offsets.
432 public int[] getBitOffsets() {
433 return bitOffsets.clone();
437 * Gets an array of the bit masks for all bands.
439 * @return an array of the bit masks for all bands.
441 public int[] getBitMasks() {
442 return bitMasks.clone();
446 * Returns a hash code of this MultiPixelPackedSampleModel class.
448 * @return the hash code of this MultiPixelPackedSampleModel class.
451 public int hashCode() {
471 for (int element : bitMasks) {
477 for (int element : bitOffsets) {
483 for (int element : bitSizes) {
489 hash ^= scanlineStride;
494 * Gets the scanline stride.
496 * @return the scanline stride
498 public int getScanlineStride() {
499 return this.scanlineStride;
503 public int getNumDataElements() {