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
22package java.awt.image;
23
24import org.apache.harmony.awt.internal.nls.Messages;
25
26/**
27 * The BandedSampleModel class provides samples of pixels in an image which is
28 * stored in a band interleaved method. Each pixel's sample takes one data
29 * element of the DataBuffer. The pixel stride for a BandedSampleModel is one.
30 *
31 * @since Android 1.0
32 */
33public final class BandedSampleModel extends ComponentSampleModel {
34
35    /**
36     * Creates the indices.
37     *
38     * @param numBands
39     *            the num bands.
40     * @return the int[].
41     */
42    private static int[] createIndices(int numBands) {
43        int indices[] = new int[numBands];
44        for (int i = 0; i < numBands; i++) {
45            indices[i] = i;
46        }
47        return indices;
48    }
49
50    /**
51     * Creates the offsets.
52     *
53     * @param numBands
54     *            the num bands.
55     * @return the int[].
56     */
57    private static int[] createOffsets(int numBands) {
58        int offsets[] = new int[numBands];
59        for (int i = 0; i < numBands; i++) {
60            offsets[i] = 0;
61        }
62        return offsets;
63    }
64
65    /**
66     * Instantiates a new BandedSampleModel object with the specified data type
67     * of samples, the width, height and bands number of image data.
68     *
69     * @param dataType
70     *            the data type of samples.
71     * @param w
72     *            the width of image data.
73     * @param h
74     *            the height of image data.
75     * @param numBands
76     *            the number of bands.
77     */
78    public BandedSampleModel(int dataType, int w, int h, int numBands) {
79        this(dataType, w, h, w, BandedSampleModel.createIndices(numBands), BandedSampleModel
80                .createOffsets(numBands));
81    }
82
83    /**
84     * Instantiates a new BandedSampleModel object with the specified data type
85     * of samples, the width, height and bands number of image data.
86     *
87     * @param dataType
88     *            the data type of samples.
89     * @param w
90     *            the width of image data.
91     * @param h
92     *            the height of image data.
93     * @param scanlineStride
94     *            the scanline stride of the of the image data.
95     * @param bankIndices
96     *            the array of the bank indices.
97     * @param bandOffsets
98     *            the array of the band offsets.
99     */
100    public BandedSampleModel(int dataType, int w, int h, int scanlineStride, int bankIndices[],
101            int bandOffsets[]) {
102        super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
103    }
104
105    @Override
106    public SampleModel createCompatibleSampleModel(int w, int h) {
107        return new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffsets);
108    }
109
110    @Override
111    public DataBuffer createDataBuffer() {
112        DataBuffer data = null;
113        int size = scanlineStride * height;
114
115        switch (dataType) {
116            case DataBuffer.TYPE_BYTE:
117                data = new DataBufferByte(size, numBanks);
118                break;
119            case DataBuffer.TYPE_SHORT:
120            case DataBuffer.TYPE_USHORT:
121                data = new DataBufferShort(size, numBanks);
122                break;
123            case DataBuffer.TYPE_INT:
124                data = new DataBufferInt(size, numBanks);
125                break;
126            case DataBuffer.TYPE_FLOAT:
127                data = new DataBufferFloat(size, numBanks);
128                break;
129            case DataBuffer.TYPE_DOUBLE:
130                data = new DataBufferDouble(size, numBanks);
131                break;
132        }
133
134        return data;
135
136    }
137
138    @Override
139    public SampleModel createSubsetSampleModel(int[] bands) {
140        if (bands.length > numBands) {
141            // awt.64=The number of the bands in the subset is greater than the
142            // number of bands in the sample model
143            throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
144        }
145
146        int indices[] = new int[bands.length];
147        int offsets[] = new int[bands.length];
148
149        for (int i = 0; i < bands.length; i++) {
150            indices[i] = bankIndices[bands[i]];
151            offsets[i] = bandOffsets[bands[i]];
152        }
153
154        return new BandedSampleModel(dataType, width, height, scanlineStride, indices, offsets);
155    }
156
157    @Override
158    public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
159        switch (dataType) {
160            case DataBuffer.TYPE_BYTE: {
161                byte bdata[];
162
163                if (obj == null) {
164                    bdata = new byte[numBands];
165                } else {
166                    bdata = (byte[])obj;
167                }
168
169                for (int i = 0; i < numBands; i++) {
170                    bdata[i] = (byte)getSample(x, y, i, data);
171                }
172
173                obj = bdata;
174                break;
175            }
176            case DataBuffer.TYPE_SHORT:
177            case DataBuffer.TYPE_USHORT: {
178                short sdata[];
179
180                if (obj == null) {
181                    sdata = new short[numBands];
182                } else {
183                    sdata = (short[])obj;
184                }
185
186                for (int i = 0; i < numBands; i++) {
187                    sdata[i] = (short)getSample(x, y, i, data);
188                }
189
190                obj = sdata;
191                break;
192            }
193            case DataBuffer.TYPE_INT: {
194                int idata[];
195
196                if (obj == null) {
197                    idata = new int[numBands];
198                } else {
199                    idata = (int[])obj;
200                }
201
202                for (int i = 0; i < numBands; i++) {
203                    idata[i] = getSample(x, y, i, data);
204                }
205
206                obj = idata;
207                break;
208            }
209            case DataBuffer.TYPE_FLOAT: {
210                float fdata[];
211
212                if (obj == null) {
213                    fdata = new float[numBands];
214                } else {
215                    fdata = (float[])obj;
216                }
217
218                for (int i = 0; i < numBands; i++) {
219                    fdata[i] = getSampleFloat(x, y, i, data);
220                }
221
222                obj = fdata;
223                break;
224            }
225            case DataBuffer.TYPE_DOUBLE: {
226                double ddata[];
227
228                if (obj == null) {
229                    ddata = new double[numBands];
230                } else {
231                    ddata = (double[])obj;
232                }
233
234                for (int i = 0; i < numBands; i++) {
235                    ddata[i] = getSampleDouble(x, y, i, data);
236                }
237
238                obj = ddata;
239                break;
240            }
241        }
242
243        return obj;
244    }
245
246    @Override
247    public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
248        int pixel[];
249        if (iArray == null) {
250            pixel = new int[numBands];
251        } else {
252            pixel = iArray;
253        }
254
255        for (int i = 0; i < numBands; i++) {
256            pixel[i] = getSample(x, y, i, data);
257        }
258
259        return pixel;
260    }
261
262    @Override
263    public int getSample(int x, int y, int b, DataBuffer data) {
264        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
265            // awt.63=Coordinates are not in bounds
266            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
267        }
268
269        return data.getElem(bankIndices[b], y * scanlineStride + x + bandOffsets[b]);
270    }
271
272    @Override
273    public double getSampleDouble(int x, int y, int b, DataBuffer data) {
274        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
275            // awt.63=Coordinates are not in bounds
276            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
277        }
278
279        return data.getElemDouble(bankIndices[b], y * scanlineStride + x + bandOffsets[b]);
280    }
281
282    @Override
283    public float getSampleFloat(int x, int y, int b, DataBuffer data) {
284        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
285            // awt.63=Coordinates are not in bounds
286            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
287        }
288
289        return data.getElemFloat(bankIndices[b], y * scanlineStride + x + bandOffsets[b]);
290    }
291
292    @Override
293    public int[] getSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) {
294        int samples[];
295        int idx = 0;
296
297        if (iArray == null) {
298            samples = new int[w * h];
299        } else {
300            samples = iArray;
301        }
302
303        for (int i = y; i < y + h; i++) {
304            for (int j = x; j < x + w; j++) {
305                samples[idx++] = getSample(j, i, b, data);
306            }
307        }
308
309        return samples;
310    }
311
312    @Override
313    public int hashCode() {
314        int hash = super.hashCode();
315        int tmp = hash >>> 8;
316        hash <<= 8;
317        hash |= tmp;
318
319        return hash ^ 0x55;
320    }
321
322    @Override
323    public void setDataElements(int x, int y, Object obj, DataBuffer data) {
324        switch (dataType) {
325            case DataBuffer.TYPE_BYTE:
326                byte bdata[] = (byte[])obj;
327                for (int i = 0; i < numBands; i++) {
328                    setSample(x, y, i, bdata[i] & 0xff, data);
329                }
330                break;
331
332            case DataBuffer.TYPE_SHORT:
333            case DataBuffer.TYPE_USHORT:
334                short sdata[] = (short[])obj;
335                for (int i = 0; i < numBands; i++) {
336                    setSample(x, y, i, sdata[i] & 0xffff, data);
337                }
338                break;
339
340            case DataBuffer.TYPE_INT:
341                int idata[] = (int[])obj;
342                for (int i = 0; i < numBands; i++) {
343                    setSample(x, y, i, idata[i], data);
344                }
345                break;
346
347            case DataBuffer.TYPE_FLOAT:
348                float fdata[] = (float[])obj;
349                for (int i = 0; i < numBands; i++) {
350                    setSample(x, y, i, fdata[i], data);
351                }
352                break;
353
354            case DataBuffer.TYPE_DOUBLE:
355                double ddata[] = (double[])obj;
356                for (int i = 0; i < numBands; i++) {
357                    setSample(x, y, i, ddata[i], data);
358                }
359                break;
360        }
361    }
362
363    @Override
364    public void setPixel(int x, int y, int iArray[], DataBuffer data) {
365        for (int i = 0; i < numBands; i++) {
366            setSample(x, y, i, iArray[i], data);
367        }
368    }
369
370    @Override
371    public void setPixels(int x, int y, int w, int h, int iArray[], DataBuffer data) {
372        int idx = 0;
373
374        for (int i = y; i < y + h; i++) {
375            for (int j = x; j < x + w; j++) {
376                for (int n = 0; n < numBands; n++) {
377                    setSample(j, i, n, iArray[idx++], data);
378                }
379            }
380        }
381    }
382
383    @Override
384    public void setSample(int x, int y, int b, double s, DataBuffer data) {
385        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
386            // awt.63=Coordinates are not in bounds
387            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
388        }
389
390        data.setElemDouble(bankIndices[b], y * scanlineStride + x + bandOffsets[b], s);
391    }
392
393    @Override
394    public void setSample(int x, int y, int b, float s, DataBuffer data) {
395        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
396            // awt.63=Coordinates are not in bounds
397            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
398        }
399
400        data.setElemFloat(bankIndices[b], y * scanlineStride + x + bandOffsets[b], s);
401    }
402
403    @Override
404    public void setSample(int x, int y, int b, int s, DataBuffer data) {
405        if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
406            // awt.63=Coordinates are not in bounds
407            throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
408        }
409
410        data.setElem(bankIndices[b], y * scanlineStride + x + bandOffsets[b], s);
411    }
412
413    @Override
414    public void setSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) {
415        int idx = 0;
416
417        for (int i = y; i < y + h; i++) {
418            for (int j = x; j < x + w; j++) {
419                setSample(j, i, b, iArray[idx++], data);
420            }
421        }
422
423    }
424
425}
426