• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 package java.awt.image;
23 
24 import java.util.Arrays;
25 
26 import org.apache.harmony.awt.internal.nls.Messages;
27 
28 /**
29  * The SinglePixelPackedSampleModel class represents pixel data where several
30  * samples combine to create a single pixel and are stored in a single data
31  * array element. This class supports TYPE_BYTE, TYPE_USHORT, TYPE_INT data
32  * types.
33  *
34  * @since Android 1.0
35  */
36 public class SinglePixelPackedSampleModel extends SampleModel {
37 
38     /**
39      * The bit masks.
40      */
41     private int bitMasks[];
42 
43     /**
44      * The bit offsets.
45      */
46     private int bitOffsets[];
47 
48     /**
49      * The bit sizes.
50      */
51     private int bitSizes[];
52 
53     /**
54      * The scanline stride.
55      */
56     private int scanlineStride;
57 
58     /**
59      * The max bit size.
60      */
61     private int maxBitSize;
62 
63     /**
64      * Instantiates a new SinglePixelPackedSampleModel with the specified
65      * parameters.
66      *
67      * @param dataType
68      *            the data type of samples.
69      * @param w
70      *            the width of the image data.
71      * @param h
72      *            the height of the image data.
73      * @param bitMasks
74      *            the bit masks for all the bands.
75      */
SinglePixelPackedSampleModel(int dataType, int w, int h, int bitMasks[])76     public SinglePixelPackedSampleModel(int dataType, int w, int h, int bitMasks[]) {
77         this(dataType, w, h, w, bitMasks);
78     }
79 
80     /**
81      * Instantiates a new SinglePixelPackedSampleModel with the specified
82      * parameters.
83      *
84      * @param dataType
85      *            the data type of the samples.
86      * @param w
87      *            the width of the image data.
88      * @param h
89      *            the height of the image data.
90      * @param scanlineStride
91      *            the scanline stride of the image data.
92      * @param bitMasks
93      *            the bit masks for all the bands.
94      */
SinglePixelPackedSampleModel(int dataType, int w, int h, int scanlineStride, int bitMasks[])95     public SinglePixelPackedSampleModel(int dataType, int w, int h, int scanlineStride,
96             int bitMasks[]) {
97 
98         super(dataType, w, h, bitMasks.length);
99 
100         if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_USHORT
101                 && dataType != DataBuffer.TYPE_INT) {
102             // awt.61=Unsupported data type: {0}
103             throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
104                     dataType));
105         }
106 
107         this.scanlineStride = scanlineStride;
108         this.bitMasks = bitMasks.clone();
109         this.bitOffsets = new int[this.numBands];
110         this.bitSizes = new int[this.numBands];
111 
112         this.maxBitSize = 0;
113 
114         for (int i = 0; i < this.numBands; i++) {
115             int offset = 0;
116             int size = 0;
117             int mask = bitMasks[i];
118 
119             if (mask != 0) {
120                 while ((mask & 1) == 0) {
121                     mask >>>= 1;
122                     offset++;
123                 }
124 
125                 while ((mask & 1) == 1) {
126                     mask >>>= 1;
127                     size++;
128                 }
129 
130                 if (mask != 0) {
131                     // awt.62=Wrong mask : {0}
132                     throw new IllegalArgumentException(Messages.getString("awt.62", bitMasks[i])); //$NON-NLS-1$
133                 }
134             }
135 
136             this.bitOffsets[i] = offset;
137             this.bitSizes[i] = size;
138 
139             if (this.maxBitSize < size) {
140                 this.maxBitSize = size;
141             }
142 
143         }
144 
145     }
146 
147     @Override
getDataElements(int x, int y, Object obj, DataBuffer data)148     public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
149         if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
150             // awt.63=Coordinates are not in bounds
151             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
152         }
153         switch (getTransferType()) {
154             case DataBuffer.TYPE_BYTE:
155                 byte bdata[];
156                 if (obj == null) {
157                     bdata = new byte[1];
158                 } else {
159                     bdata = (byte[])obj;
160                 }
161 
162                 bdata[0] = (byte)data.getElem(y * scanlineStride + x);
163                 obj = bdata;
164                 break;
165             case DataBuffer.TYPE_USHORT:
166                 short sdata[];
167                 if (obj == null) {
168                     sdata = new short[1];
169                 } else {
170                     sdata = (short[])obj;
171                 }
172 
173                 sdata[0] = (short)data.getElem(y * scanlineStride + x);
174                 obj = sdata;
175                 break;
176             case DataBuffer.TYPE_INT:
177                 int idata[];
178                 if (obj == null) {
179                     idata = new int[1];
180                 } else {
181                     idata = (int[])obj;
182                 }
183 
184                 idata[0] = data.getElem(y * scanlineStride + x);
185                 obj = idata;
186                 break;
187         }
188         return obj;
189     }
190 
191     @Override
setDataElements(int x, int y, Object obj, DataBuffer data)192     public void setDataElements(int x, int y, Object obj, DataBuffer data) {
193         if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
194             // awt.63=Coordinates are not in bounds
195             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
196         }
197         switch (getTransferType()) {
198             case DataBuffer.TYPE_BYTE:
199                 data.setElem(y * scanlineStride + x, ((byte[])obj)[0] & 0xff);
200                 break;
201             case DataBuffer.TYPE_USHORT:
202                 data.setElem(y * scanlineStride + x, ((short[])obj)[0] & 0xffff);
203                 break;
204             case DataBuffer.TYPE_INT:
205                 data.setElem(y * scanlineStride + x, ((int[])obj)[0]);
206                 break;
207         }
208     }
209 
210     /**
211      * Compares this SinglePixelPackedSampleModel object with the specified
212      * object.
213      *
214      * @param o
215      *            the Object to be compared.
216      * @return true, if this SinglePixelPackedSampleModel object is equal to the
217      *         specified object, false otherwise.
218      */
219     @Override
equals(Object o)220     public boolean equals(Object o) {
221         if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
222             return false;
223         }
224 
225         SinglePixelPackedSampleModel model = (SinglePixelPackedSampleModel)o;
226         return this.width == model.width && this.height == model.height
227                 && this.numBands == model.numBands && this.dataType == model.dataType
228                 && Arrays.equals(this.bitMasks, model.bitMasks)
229                 && Arrays.equals(this.bitOffsets, model.bitOffsets)
230                 && Arrays.equals(this.bitSizes, model.bitSizes)
231                 && this.scanlineStride == model.scanlineStride;
232     }
233 
234     @Override
createSubsetSampleModel(int bands[])235     public SampleModel createSubsetSampleModel(int bands[]) {
236         if (bands.length > this.numBands) {
237             // awt.64=The number of the bands in the subset is greater than the
238             // number of bands in the sample model
239             throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
240         }
241 
242         int masks[] = new int[bands.length];
243         for (int i = 0; i < bands.length; i++) {
244             masks[i] = this.bitMasks[bands[i]];
245         }
246         return new SinglePixelPackedSampleModel(this.dataType, this.width, this.height,
247                 this.scanlineStride, masks);
248     }
249 
250     @Override
createCompatibleSampleModel(int w, int h)251     public SampleModel createCompatibleSampleModel(int w, int h) {
252         return new SinglePixelPackedSampleModel(this.dataType, w, h, this.bitMasks);
253     }
254 
255     @Override
getPixel(int x, int y, int iArray[], DataBuffer data)256     public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
257         if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
258             // awt.63=Coordinates are not in bounds
259             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
260         }
261         int pixel[];
262         if (iArray == null) {
263             pixel = new int[this.numBands];
264         } else {
265             pixel = iArray;
266         }
267 
268         for (int i = 0; i < this.numBands; i++) {
269             pixel[i] = getSample(x, y, i, data);
270         }
271 
272         return pixel;
273     }
274 
275     @Override
setPixel(int x, int y, int iArray[], DataBuffer data)276     public void setPixel(int x, int y, int iArray[], DataBuffer data) {
277         if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
278             // awt.63=Coordinates are not in bounds
279             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
280         }
281         for (int i = 0; i < this.numBands; i++) {
282             setSample(x, y, i, iArray[i], data);
283         }
284     }
285 
286     @Override
getSample(int x, int y, int b, DataBuffer data)287     public int getSample(int x, int y, int b, DataBuffer data) {
288         if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
289             // awt.63=Coordinates are not in bounds
290             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
291         }
292         int sample = data.getElem(y * scanlineStride + x);
293         return ((sample & this.bitMasks[b]) >>> this.bitOffsets[b]);
294     }
295 
296     @Override
getPixels(int x, int y, int w, int h, int iArray[], DataBuffer data)297     public int[] getPixels(int x, int y, int w, int h, int iArray[], DataBuffer data) {
298         if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
299                 || ((long)y + (long)h > this.height)) {
300             // awt.63=Coordinates are not in bounds
301             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
302         }
303 
304         int pixels[];
305 
306         if (iArray == null) {
307             pixels = new int[w * h * this.numBands];
308         } else {
309             pixels = iArray;
310         }
311 
312         int idx = 0;
313 
314         for (int i = y; i < y + h; i++) {
315             for (int j = x; j < x + w; j++) {
316                 for (int n = 0; n < this.numBands; n++) {
317                     pixels[idx++] = getSample(j, i, n, data);
318                 }
319             }
320         }
321         return pixels;
322     }
323 
324     @Override
setPixels(int x, int y, int w, int h, int iArray[], DataBuffer data)325     public void setPixels(int x, int y, int w, int h, int iArray[], DataBuffer data) {
326         if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
327                 || ((long)y + (long)h > this.height)) {
328             // awt.63=Coordinates are not in bounds
329             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
330         }
331 
332         int idx = 0;
333 
334         for (int i = y; i < y + h; i++) {
335             for (int j = x; j < x + w; j++) {
336                 for (int n = 0; n < this.numBands; n++) {
337                     setSample(j, i, n, iArray[idx++], data);
338                 }
339             }
340         }
341     }
342 
343     @Override
setSample(int x, int y, int b, int s, DataBuffer data)344     public void setSample(int x, int y, int b, int s, DataBuffer data) {
345         if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
346             // awt.63=Coordinates are not in bounds
347             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
348         }
349         int tmp = data.getElem(y * scanlineStride + x);
350         tmp &= ~this.bitMasks[b];
351         tmp |= (s << this.bitOffsets[b]) & this.bitMasks[b];
352         data.setElem(y * scanlineStride + x, tmp);
353     }
354 
355     @Override
getSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data)356     public int[] getSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) {
357         if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
358                 || ((long)y + (long)h > this.height)) {
359             // awt.63=Coordinates are not in bounds
360             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
361         }
362 
363         int samples[];
364         int idx = 0;
365 
366         if (iArray == null) {
367             samples = new int[w * h];
368         } else {
369             samples = iArray;
370         }
371 
372         for (int i = y; i < y + h; i++) {
373             for (int j = x; j < x + w; j++) {
374                 samples[idx++] = getSample(j, i, b, data);
375             }
376         }
377 
378         return samples;
379     }
380 
381     @Override
setSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data)382     public void setSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) {
383         if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
384                 || ((long)y + (long)h > this.height)) {
385             // awt.63=Coordinates are not in bounds
386             throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
387         }
388 
389         int idx = 0;
390         for (int i = y; i < y + h; i++) {
391             for (int j = x; j < x + w; j++) {
392                 setSample(x + j, y + i, b, iArray[idx++], data);
393             }
394         }
395     }
396 
397     @Override
createDataBuffer()398     public DataBuffer createDataBuffer() {
399         DataBuffer data = null;
400         int size = (this.height - 1) * scanlineStride + width;
401 
402         switch (this.dataType) {
403             case DataBuffer.TYPE_BYTE:
404                 data = new DataBufferByte(size);
405                 break;
406             case DataBuffer.TYPE_USHORT:
407                 data = new DataBufferUShort(size);
408                 break;
409             case DataBuffer.TYPE_INT:
410                 data = new DataBufferInt(size);
411                 break;
412         }
413         return data;
414     }
415 
416     /**
417      * Gets the offset of the specified pixel in the data array.
418      *
419      * @param x
420      *            the X coordinate of the specified pixel.
421      * @param y
422      *            the Y coordinate of the specified pixel.
423      * @return the offset of the specified pixel.
424      */
getOffset(int x, int y)425     public int getOffset(int x, int y) {
426         return (y * scanlineStride + x);
427     }
428 
429     @Override
getSampleSize(int band)430     public int getSampleSize(int band) {
431         return bitSizes[band];
432     }
433 
434     @Override
getSampleSize()435     public int[] getSampleSize() {
436         return bitSizes.clone();
437     }
438 
439     /**
440      * Gets an array of the bit offsets of the data array elements.
441      *
442      * @return an array of the bit offsets.
443      */
getBitOffsets()444     public int[] getBitOffsets() {
445         return bitOffsets.clone();
446     }
447 
448     /**
449      * Gets an array of the bit masks for all bands.
450      *
451      * @return an array of the bit masks for all bands.
452      */
getBitMasks()453     public int[] getBitMasks() {
454         return bitMasks.clone();
455     }
456 
457     /**
458      * Returns a hash code of this MultiPixelPackedSampleModel class.
459      *
460      * @return the hash code of this MultiPixelPackedSampleModel class.
461      */
462     @Override
hashCode()463     public int hashCode() {
464         int hash = 0;
465         int tmp = 0;
466 
467         hash = width;
468         tmp = hash >>> 24;
469         hash <<= 8;
470         hash |= tmp;
471         hash ^= height;
472         tmp = hash >>> 24;
473         hash <<= 8;
474         hash |= tmp;
475         hash ^= numBands;
476         tmp = hash >>> 24;
477         hash <<= 8;
478         hash |= tmp;
479         hash ^= dataType;
480         tmp = hash >>> 24;
481         hash <<= 8;
482         hash |= tmp;
483         for (int element : bitMasks) {
484             hash ^= element;
485             tmp = hash >>> 24;
486             hash <<= 8;
487             hash |= tmp;
488         }
489         for (int element : bitOffsets) {
490             hash ^= element;
491             tmp = hash >>> 24;
492             hash <<= 8;
493             hash |= tmp;
494         }
495         for (int element : bitSizes) {
496             hash ^= element;
497             tmp = hash >>> 24;
498             hash <<= 8;
499             hash |= tmp;
500         }
501         hash ^= scanlineStride;
502         return hash;
503     }
504 
505     /**
506      * Gets the scanline stride.
507      *
508      * @return the scanline stride
509      */
getScanlineStride()510     public int getScanlineStride() {
511         return this.scanlineStride;
512     }
513 
514     @Override
getNumDataElements()515     public int getNumDataElements() {
516         return 1;
517     }
518 
519 }
520