OSDN Git Service

Initial Contribution
[android-x86/frameworks-native.git] / awt / java / awt / image / SinglePixelPackedSampleModel.java
1 /*
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 /**
18  * @author Igor V. Stolyarov
19  * @version $Revision$
20  */
21 package java.awt.image;
22
23 import java.util.Arrays;
24
25 import org.apache.harmony.awt.internal.nls.Messages;
26
27 /**
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. 
32  */
33 public class SinglePixelPackedSampleModel extends SampleModel {
34
35     /** The bit masks. */
36     private int bitMasks[];
37
38     /** The bit offsets. */
39     private int bitOffsets[];
40
41     /** The bit sizes. */
42     private int bitSizes[];
43
44     /** The scanline stride. */
45     private int scanlineStride;
46
47     /** The max bit size. */
48     private int maxBitSize;
49
50     /**
51      * Instantiates a new SinglePixelPackedSampleModel with the specified
52      * parameters.
53      * 
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.
58      */
59     public SinglePixelPackedSampleModel(int dataType, int w, int h,
60             int bitMasks[]) {
61         this(dataType, w, h, w, bitMasks);
62     }
63
64     /**
65      * Instantiates a new SinglePixelPackedSampleModel with the specified
66      * parameters.
67      * 
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.
73      */
74     public SinglePixelPackedSampleModel(int dataType, int w, int h,
75             int scanlineStride, int bitMasks[]) {
76
77         super(dataType, w, h, bitMasks.length);
78
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$
84                     dataType));
85         }
86
87         this.scanlineStride = scanlineStride;
88         this.bitMasks = bitMasks.clone();
89         this.bitOffsets = new int[this.numBands];
90         this.bitSizes = new int[this.numBands];
91
92         this.maxBitSize = 0;
93
94         for (int i = 0; i < this.numBands; i++) {
95             int offset = 0;
96             int size = 0;
97             int mask = bitMasks[i];
98
99             if (mask != 0) {
100                 while ((mask & 1) == 0) {
101                     mask >>>= 1;
102                     offset++;
103                 }
104
105                 while ((mask & 1) == 1) {
106                     mask >>>= 1;
107                     size++;
108                 }
109
110                 if (mask != 0) {
111                     // awt.62=Wrong mask : {0}
112                     throw new IllegalArgumentException(Messages.getString(
113                             "awt.62", bitMasks[i])); //$NON-NLS-1$
114                 }
115             }
116
117             this.bitOffsets[i] = offset;
118             this.bitSizes[i] = size;
119
120             if (this.maxBitSize < size) {
121                 this.maxBitSize = size;
122             }
123
124         }
125
126     }
127
128     @Override
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$
133         }
134         switch (getTransferType()) {
135         case DataBuffer.TYPE_BYTE:
136             byte bdata[];
137             if (obj == null) {
138                 bdata = new byte[1];
139             } else {
140                 bdata = (byte[]) obj;
141             }
142
143             bdata[0] = (byte) data.getElem(y * scanlineStride + x);
144             obj = bdata;
145             break;
146         case DataBuffer.TYPE_USHORT:
147             short sdata[];
148             if (obj == null) {
149                 sdata = new short[1];
150             } else {
151                 sdata = (short[]) obj;
152             }
153
154             sdata[0] = (short) data.getElem(y * scanlineStride + x);
155             obj = sdata;
156             break;
157         case DataBuffer.TYPE_INT:
158             int idata[];
159             if (obj == null) {
160                 idata = new int[1];
161             } else {
162                 idata = (int[]) obj;
163             }
164
165             idata[0] = data.getElem(y * scanlineStride + x);
166             obj = idata;
167             break;
168         }
169         return obj;
170     }
171
172     @Override
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$
177         }
178         switch (getTransferType()) {
179         case DataBuffer.TYPE_BYTE:
180             data.setElem(y * scanlineStride + x, ((byte[]) obj)[0] & 0xff);
181             break;
182         case DataBuffer.TYPE_USHORT:
183             data.setElem(y * scanlineStride + x, ((short[]) obj)[0] & 0xffff);
184             break;
185         case DataBuffer.TYPE_INT:
186             data.setElem(y * scanlineStride + x, ((int[]) obj)[0]);
187             break;
188         }
189     }
190
191     /**
192      * Compares this SinglePixelPackedSampleModel object with 
193      * the specified object.
194      * 
195      * @param o the Object to be compared.
196      * 
197      * @return true, if this SinglePixelPackedSampleModel object is 
198      * equal to the specified object, false otherwise.
199      */
200     @Override
201     public boolean equals(Object o) {
202         if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
203             return false;
204         }
205
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;
215     }
216
217     @Override
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$
222         }
223
224         int masks[] = new int[bands.length];
225         for (int i = 0; i < bands.length; i++) {
226             masks[i] = this.bitMasks[bands[i]];
227         }
228         return new SinglePixelPackedSampleModel(this.dataType, this.width,
229                 this.height, this.scanlineStride, masks);
230     }
231
232     @Override
233     public SampleModel createCompatibleSampleModel(int w, int h) {
234         return new SinglePixelPackedSampleModel(this.dataType, w, h,
235                 this.bitMasks);
236     }
237
238     @Override
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$
243         }
244         int pixel[];
245         if (iArray == null) {
246             pixel = new int[this.numBands];
247         } else {
248             pixel = iArray;
249         }
250
251         for (int i = 0; i < this.numBands; i++) {
252             pixel[i] = getSample(x, y, i, data);
253         }
254
255         return pixel;
256     }
257
258     @Override
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$
263         }
264         for (int i = 0; i < this.numBands; i++) {
265             setSample(x, y, i, iArray[i], data);
266         }
267     }
268
269     @Override
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$
274         }
275         int sample = data.getElem(y * scanlineStride + x);
276         return ((sample & this.bitMasks[b]) >>> this.bitOffsets[b]);
277     }
278
279     @Override
280     public int[] getPixels(int x, int y, int w, int h, int iArray[],
281             DataBuffer data) {
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$
286         }
287
288         int pixels[];
289
290         if (iArray == null) {
291             pixels = new int[w * h * this.numBands];
292         } else {
293             pixels = iArray;
294         }
295
296         int idx = 0;
297
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);
302                 }
303             }
304         }
305         return pixels;
306     }
307
308     @Override
309     public void setPixels(int x, int y, int w, int h, int iArray[],
310             DataBuffer data) {
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$
316         }
317
318         int idx = 0;
319
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);
324                 }
325             }
326         }
327     }
328
329     @Override
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$
334         }
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);
339     }
340
341     @Override
342     public int[] getSamples(int x, int y, int w, int h, int b, int iArray[],
343             DataBuffer data) {
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$
349         }
350
351         int samples[];
352         int idx = 0;
353
354         if (iArray == null) {
355             samples = new int[w * h];
356         } else {
357             samples = iArray;
358         }
359
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);
363             }
364         }
365
366         return samples;
367     }
368
369     @Override
370     public void setSamples(int x, int y, int w, int h, int b, int iArray[],
371             DataBuffer data) {
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$
376         }
377
378         int idx = 0;
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);
382             }
383         }
384     }
385
386     @Override
387     public DataBuffer createDataBuffer() {
388         DataBuffer data = null;
389         int size = (this.height - 1) * scanlineStride + width;
390
391         switch (this.dataType) {
392         case DataBuffer.TYPE_BYTE:
393             data = new DataBufferByte(size);
394             break;
395         case DataBuffer.TYPE_USHORT:
396             data = new DataBufferUShort(size);
397             break;
398         case DataBuffer.TYPE_INT:
399             data = new DataBufferInt(size);
400             break;
401         }
402         return data;
403     }
404
405     /**
406      * Gets the offset of the specified pixel in the data array.
407      * 
408      * @param x the X coordinate of the specified pixel.
409      * @param y the Y coordinate of the specified pixel.
410      * 
411      * @return the offset of the specified pixel.
412      */
413     public int getOffset(int x, int y) {
414         return (y * scanlineStride + x);
415     }
416
417     @Override
418     public int getSampleSize(int band) {
419         return bitSizes[band];
420     }
421
422     @Override
423     public int[] getSampleSize() {
424         return bitSizes.clone();
425     }
426
427     /**
428      * Gets an array of the bit offsets of the data array elements. 
429      * 
430      * @return an array of the bit offsets.
431      */
432     public int[] getBitOffsets() {
433         return bitOffsets.clone();
434     }
435
436     /**
437      * Gets an array of the bit masks for all bands.
438      * 
439      * @return an array of the bit masks for all bands.
440      */
441     public int[] getBitMasks() {
442         return bitMasks.clone();
443     }
444
445     /**
446      * Returns a hash code of this MultiPixelPackedSampleModel class.
447      * 
448      * @return the hash code of this MultiPixelPackedSampleModel class.
449      */
450     @Override
451     public int hashCode() {
452         int hash = 0;
453         int tmp = 0;
454
455         hash = width;
456         tmp = hash >>> 24;
457         hash <<= 8;
458         hash |= tmp;
459         hash ^= height;
460         tmp = hash >>> 24;
461         hash <<= 8;
462         hash |= tmp;
463         hash ^= numBands;
464         tmp = hash >>> 24;
465         hash <<= 8;
466         hash |= tmp;
467         hash ^= dataType;
468         tmp = hash >>> 24;
469         hash <<= 8;
470         hash |= tmp;
471         for (int element : bitMasks) {
472             hash ^= element;
473             tmp = hash >>> 24;
474             hash <<= 8;
475             hash |= tmp;
476         }
477         for (int element : bitOffsets) {
478             hash ^= element;
479             tmp = hash >>> 24;
480             hash <<= 8;
481             hash |= tmp;
482         }
483         for (int element : bitSizes) {
484             hash ^= element;
485             tmp = hash >>> 24;
486             hash <<= 8;
487             hash |= tmp;
488         }
489         hash ^= scanlineStride;
490         return hash;
491     }
492
493     /**
494      * Gets the scanline stride.
495      * 
496      * @return the scanline stride
497      */
498     public int getScanlineStride() {
499         return this.scanlineStride;
500     }
501
502     @Override
503     public int getNumDataElements() {
504         return 1;
505     }
506
507 }
508