001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Igor V. Stolyarov
019: * @version $Revision$
020: */package java.awt.image;
021:
022: import org.apache.harmony.awt.internal.nls.Messages;
023:
024: public class MultiPixelPackedSampleModel extends SampleModel {
025:
026: private int pixelBitStride;
027:
028: private int scanlineStride;
029:
030: private int dataBitOffset;
031:
032: private int bitMask;
033:
034: private int dataElementSize;
035:
036: private int pixelsPerDataElement;
037:
038: public MultiPixelPackedSampleModel(int dataType, int w, int h,
039: int numberOfBits, int scanlineStride, int dataBitOffset) {
040:
041: super (dataType, w, h, 1);
042: if (dataType != DataBuffer.TYPE_BYTE
043: && dataType != DataBuffer.TYPE_USHORT
044: && dataType != DataBuffer.TYPE_INT) {
045: // awt.61=Unsupported data type: {0}
046: throw new IllegalArgumentException(Messages.getString(
047: "awt.61", //$NON-NLS-1$
048: dataType));
049: }
050:
051: this .scanlineStride = scanlineStride;
052: if (numberOfBits == 0) {
053: // awt.20C=Number of Bits equals to zero
054: throw new RasterFormatException(Messages
055: .getString("awt.20C")); //$NON-NLS-1$
056: }
057: this .pixelBitStride = numberOfBits;
058: this .dataElementSize = DataBuffer.getDataTypeSize(dataType);
059: if (dataElementSize % pixelBitStride != 0) {
060: // awt.20D=The number of bits per pixel is not a power of 2 or pixels span data element boundaries
061: throw new RasterFormatException(Messages
062: .getString("awt.20D")); //$NON-NLS-1$
063: }
064:
065: if (dataBitOffset % numberOfBits != 0) {
066: // awt.20E=Data Bit offset is not a multiple of pixel bit stride
067: throw new RasterFormatException(Messages
068: .getString("awt.20E")); //$NON-NLS-1$
069: }
070: this .dataBitOffset = dataBitOffset;
071:
072: this .pixelsPerDataElement = dataElementSize / pixelBitStride;
073: this .bitMask = (1 << numberOfBits) - 1;
074: }
075:
076: public MultiPixelPackedSampleModel(int dataType, int w, int h,
077: int numberOfBits) {
078:
079: this (dataType, w, h, numberOfBits, (numberOfBits * w
080: + DataBuffer.getDataTypeSize(dataType) - 1)
081: / DataBuffer.getDataTypeSize(dataType), 0);
082: }
083:
084: @Override
085: public Object getDataElements(int x, int y, Object obj,
086: DataBuffer data) {
087: if (x < 0 || y < 0 || x >= this .width || y >= this .height) {
088: // awt.63=Coordinates are not in bounds
089: throw new ArrayIndexOutOfBoundsException(Messages
090: .getString("awt.63")); //$NON-NLS-1$
091: }
092: switch (getTransferType()) {
093: case DataBuffer.TYPE_BYTE:
094: byte bdata[];
095: if (obj == null) {
096: bdata = new byte[1];
097: } else {
098: bdata = (byte[]) obj;
099: }
100: bdata[0] = (byte) getSample(x, y, 0, data);
101: obj = bdata;
102: break;
103: case DataBuffer.TYPE_USHORT:
104: short sdata[];
105: if (obj == null) {
106: sdata = new short[1];
107: } else {
108: sdata = (short[]) obj;
109: }
110: sdata[0] = (short) getSample(x, y, 0, data);
111: obj = sdata;
112: break;
113: case DataBuffer.TYPE_INT:
114: int idata[];
115: if (obj == null) {
116: idata = new int[1];
117: } else {
118: idata = (int[]) obj;
119: }
120: idata[0] = getSample(x, y, 0, data);
121: obj = idata;
122: break;
123: }
124:
125: return obj;
126: }
127:
128: @Override
129: public void setDataElements(int x, int y, Object obj,
130: DataBuffer data) {
131: setSample(x, y, obj, data, 1, 0);
132: }
133:
134: @Override
135: public boolean equals(Object o) {
136: if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
137: return false;
138: }
139:
140: MultiPixelPackedSampleModel model = (MultiPixelPackedSampleModel) o;
141: return this .width == model.width
142: && this .height == model.height
143: && this .numBands == model.numBands
144: && this .dataType == model.dataType
145: && this .pixelBitStride == model.pixelBitStride
146: && this .bitMask == model.bitMask
147: && this .pixelsPerDataElement == model.pixelsPerDataElement
148: && this .dataElementSize == model.dataElementSize
149: && this .dataBitOffset == model.dataBitOffset
150: && this .scanlineStride == model.scanlineStride;
151: }
152:
153: @Override
154: public SampleModel createSubsetSampleModel(int bands[]) {
155: if (bands != null && bands.length != 1) {
156: // awt.20F=Number of bands must be only 1
157: throw new RasterFormatException(Messages
158: .getString("awt.20F")); //$NON-NLS-1$
159: }
160: return createCompatibleSampleModel(width, height);
161: }
162:
163: @Override
164: public SampleModel createCompatibleSampleModel(int w, int h) {
165: return new MultiPixelPackedSampleModel(dataType, w, h,
166: pixelBitStride);
167: }
168:
169: @Override
170: public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
171: if (x < 0 || y < 0 || x >= this .width || y >= this .height) {
172: // awt.63=Coordinates are not in bounds
173: throw new ArrayIndexOutOfBoundsException(Messages
174: .getString("awt.63")); //$NON-NLS-1$
175: }
176: int pixel[];
177: if (iArray == null) {
178: pixel = new int[numBands];
179: } else {
180: pixel = iArray;
181: }
182:
183: pixel[0] = getSample(x, y, 0, data);
184: return pixel;
185: }
186:
187: @Override
188: public void setPixel(int x, int y, int iArray[], DataBuffer data) {
189: setSample(x, y, iArray, data, 2, 0);
190: }
191:
192: @Override
193: public int getSample(int x, int y, int b, DataBuffer data) {
194: if (x < 0 || y < 0 || x >= this .width || y >= this .height
195: || b != 0) {
196: // awt.63=Coordinates are not in bounds
197: throw new ArrayIndexOutOfBoundsException(Messages
198: .getString("awt.63")); //$NON-NLS-1$
199: }
200:
201: int bitnum = dataBitOffset + x * pixelBitStride;
202: int elem = data.getElem(y * scanlineStride + bitnum
203: / dataElementSize);
204: int shift = dataElementSize - (bitnum & (dataElementSize - 1))
205: - pixelBitStride;
206:
207: return (elem >> shift) & bitMask;
208: }
209:
210: @Override
211: public void setSample(int x, int y, int b, int s, DataBuffer data) {
212: if (b != 0) {
213: // awt.63=Coordinates are not in bounds
214: throw new ArrayIndexOutOfBoundsException(Messages
215: .getString("awt.63")); //$NON-NLS-1$
216: }
217:
218: setSample(x, y, null, data, 3, s);
219: }
220:
221: @Override
222: public DataBuffer createDataBuffer() {
223: DataBuffer dataBuffer = null;
224: int size = scanlineStride * height;
225:
226: switch (dataType) {
227: case DataBuffer.TYPE_BYTE:
228: dataBuffer = new DataBufferByte(size + (dataBitOffset + 7)
229: / 8);
230: break;
231: case DataBuffer.TYPE_USHORT:
232: dataBuffer = new DataBufferUShort(size
233: + (dataBitOffset + 15) / 16);
234: break;
235: case DataBuffer.TYPE_INT:
236: dataBuffer = new DataBufferInt(size + (dataBitOffset + 31)
237: / 32);
238: break;
239: }
240: return dataBuffer;
241: }
242:
243: public int getOffset(int x, int y) {
244: return y * scanlineStride
245: + (x * pixelBitStride + dataBitOffset)
246: / dataElementSize;
247: }
248:
249: @Override
250: public int getSampleSize(int band) {
251: return pixelBitStride;
252: }
253:
254: public int getBitOffset(int x) {
255: return (x * pixelBitStride + dataBitOffset) % dataElementSize;
256: }
257:
258: @Override
259: public int[] getSampleSize() {
260: int sampleSizes[] = { pixelBitStride };
261: return sampleSizes;
262: }
263:
264: @Override
265: public int hashCode() {
266: int hash = 0;
267: int tmp = 0;
268:
269: hash = width;
270: tmp = hash >>> 24;
271: hash <<= 8;
272: hash |= tmp;
273: hash ^= height;
274: tmp = hash >>> 24;
275: hash <<= 8;
276: hash |= tmp;
277: hash ^= numBands;
278: tmp = hash >>> 24;
279: hash <<= 8;
280: hash |= tmp;
281: hash ^= dataType;
282: tmp = hash >>> 24;
283: hash <<= 8;
284: hash |= tmp;
285: hash ^= scanlineStride;
286: tmp = hash >>> 24;
287: hash <<= 8;
288: hash |= tmp;
289: hash ^= pixelBitStride;
290: tmp = hash >>> 24;
291: hash <<= 8;
292: hash |= tmp;
293: hash ^= dataBitOffset;
294: tmp = hash >>> 24;
295: hash <<= 8;
296: hash |= tmp;
297: hash ^= bitMask;
298: tmp = hash >>> 24;
299: hash <<= 8;
300: hash |= tmp;
301: hash ^= dataElementSize;
302: tmp = hash >>> 24;
303: hash <<= 8;
304: hash |= tmp;
305: hash ^= pixelsPerDataElement;
306: return hash;
307: }
308:
309: @Override
310: public int getTransferType() {
311: if (pixelBitStride > 16) {
312: return DataBuffer.TYPE_INT;
313: } else if (pixelBitStride > 8) {
314: return DataBuffer.TYPE_USHORT;
315: } else {
316: return DataBuffer.TYPE_BYTE;
317: }
318: }
319:
320: public int getScanlineStride() {
321: return scanlineStride;
322: }
323:
324: public int getPixelBitStride() {
325: return pixelBitStride;
326: }
327:
328: @Override
329: public int getNumDataElements() {
330: return 1;
331: }
332:
333: public int getDataBitOffset() {
334: return dataBitOffset;
335: }
336:
337: /**
338: * This method is used by other methods of this class. The behaviour of
339: * this method depends on the method which has been invoke this one. The
340: * argument methodId is used to choose valid behaviour in a particular case.
341: * If methodId is equal to 1 it means that this method has been invoked by
342: * the setDataElements() method, 2 - means setPixel(), and setSample() in
343: * any other cases.
344: */
345: private void setSample(final int x, final int y, final Object obj,
346: final DataBuffer data, final int methodId, int s) {
347: if ((x < 0) || (y < 0) || (x >= this .width)
348: || (y >= this .height)) {
349: // awt.63=Coordinates are not in bounds
350: throw new ArrayIndexOutOfBoundsException(Messages
351: .getString("awt.63")); //$NON-NLS-1$
352: }
353:
354: final int bitnum = dataBitOffset + x * pixelBitStride;
355: final int idx = y * scanlineStride + bitnum / dataElementSize;
356: final int shift = dataElementSize
357: - (bitnum & (dataElementSize - 1)) - pixelBitStride;
358: final int mask = ~(bitMask << shift);
359: int elem = data.getElem(idx);
360:
361: switch (methodId) {
362: case 1: { // Invoked from setDataElements()
363: switch (getTransferType()) {
364: case DataBuffer.TYPE_BYTE:
365: s = ((byte[]) obj)[0] & 0xff;
366: break;
367: case DataBuffer.TYPE_USHORT:
368: s = ((short[]) obj)[0] & 0xffff;
369: break;
370: case DataBuffer.TYPE_INT:
371: s = ((int[]) obj)[0];
372: break;
373: }
374: break;
375: }
376: case 2: { // Invoked from setPixel()
377: s = ((int[]) obj)[0];
378: break;
379: }
380: }
381:
382: elem &= mask;
383: elem |= (s & bitMask) << shift;
384: data.setElem(idx, elem);
385: }
386: }
|