520 lines
16 KiB
Java
520 lines
16 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/**
|
|
* @author Igor V. Stolyarov
|
|
* @version $Revision$
|
|
*/
|
|
|
|
package java.awt.image;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import org.apache.harmony.awt.internal.nls.Messages;
|
|
|
|
/**
|
|
* The SinglePixelPackedSampleModel class represents pixel data where several
|
|
* samples combine to create a single pixel and are stored in a single data
|
|
* array element. This class supports TYPE_BYTE, TYPE_USHORT, TYPE_INT data
|
|
* types.
|
|
*
|
|
* @since Android 1.0
|
|
*/
|
|
public class SinglePixelPackedSampleModel extends SampleModel {
|
|
|
|
/**
|
|
* The bit masks.
|
|
*/
|
|
private int bitMasks[];
|
|
|
|
/**
|
|
* The bit offsets.
|
|
*/
|
|
private int bitOffsets[];
|
|
|
|
/**
|
|
* The bit sizes.
|
|
*/
|
|
private int bitSizes[];
|
|
|
|
/**
|
|
* The scanline stride.
|
|
*/
|
|
private int scanlineStride;
|
|
|
|
/**
|
|
* The max bit size.
|
|
*/
|
|
private int maxBitSize;
|
|
|
|
/**
|
|
* Instantiates a new SinglePixelPackedSampleModel with the specified
|
|
* parameters.
|
|
*
|
|
* @param dataType
|
|
* the data type of samples.
|
|
* @param w
|
|
* the width of the image data.
|
|
* @param h
|
|
* the height of the image data.
|
|
* @param bitMasks
|
|
* the bit masks for all the bands.
|
|
*/
|
|
public SinglePixelPackedSampleModel(int dataType, int w, int h, int bitMasks[]) {
|
|
this(dataType, w, h, w, bitMasks);
|
|
}
|
|
|
|
/**
|
|
* Instantiates a new SinglePixelPackedSampleModel with the specified
|
|
* parameters.
|
|
*
|
|
* @param dataType
|
|
* the data type of the samples.
|
|
* @param w
|
|
* the width of the image data.
|
|
* @param h
|
|
* the height of the image data.
|
|
* @param scanlineStride
|
|
* the scanline stride of the image data.
|
|
* @param bitMasks
|
|
* the bit masks for all the bands.
|
|
*/
|
|
public SinglePixelPackedSampleModel(int dataType, int w, int h, int scanlineStride,
|
|
int bitMasks[]) {
|
|
|
|
super(dataType, w, h, bitMasks.length);
|
|
|
|
if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_USHORT
|
|
&& dataType != DataBuffer.TYPE_INT) {
|
|
// awt.61=Unsupported data type: {0}
|
|
throw new IllegalArgumentException(Messages.getString("awt.61", //$NON-NLS-1$
|
|
dataType));
|
|
}
|
|
|
|
this.scanlineStride = scanlineStride;
|
|
this.bitMasks = bitMasks.clone();
|
|
this.bitOffsets = new int[this.numBands];
|
|
this.bitSizes = new int[this.numBands];
|
|
|
|
this.maxBitSize = 0;
|
|
|
|
for (int i = 0; i < this.numBands; i++) {
|
|
int offset = 0;
|
|
int size = 0;
|
|
int mask = bitMasks[i];
|
|
|
|
if (mask != 0) {
|
|
while ((mask & 1) == 0) {
|
|
mask >>>= 1;
|
|
offset++;
|
|
}
|
|
|
|
while ((mask & 1) == 1) {
|
|
mask >>>= 1;
|
|
size++;
|
|
}
|
|
|
|
if (mask != 0) {
|
|
// awt.62=Wrong mask : {0}
|
|
throw new IllegalArgumentException(Messages.getString("awt.62", bitMasks[i])); //$NON-NLS-1$
|
|
}
|
|
}
|
|
|
|
this.bitOffsets[i] = offset;
|
|
this.bitSizes[i] = size;
|
|
|
|
if (this.maxBitSize < size) {
|
|
this.maxBitSize = size;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
|
|
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
switch (getTransferType()) {
|
|
case DataBuffer.TYPE_BYTE:
|
|
byte bdata[];
|
|
if (obj == null) {
|
|
bdata = new byte[1];
|
|
} else {
|
|
bdata = (byte[])obj;
|
|
}
|
|
|
|
bdata[0] = (byte)data.getElem(y * scanlineStride + x);
|
|
obj = bdata;
|
|
break;
|
|
case DataBuffer.TYPE_USHORT:
|
|
short sdata[];
|
|
if (obj == null) {
|
|
sdata = new short[1];
|
|
} else {
|
|
sdata = (short[])obj;
|
|
}
|
|
|
|
sdata[0] = (short)data.getElem(y * scanlineStride + x);
|
|
obj = sdata;
|
|
break;
|
|
case DataBuffer.TYPE_INT:
|
|
int idata[];
|
|
if (obj == null) {
|
|
idata = new int[1];
|
|
} else {
|
|
idata = (int[])obj;
|
|
}
|
|
|
|
idata[0] = data.getElem(y * scanlineStride + x);
|
|
obj = idata;
|
|
break;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
@Override
|
|
public void setDataElements(int x, int y, Object obj, DataBuffer data) {
|
|
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
switch (getTransferType()) {
|
|
case DataBuffer.TYPE_BYTE:
|
|
data.setElem(y * scanlineStride + x, ((byte[])obj)[0] & 0xff);
|
|
break;
|
|
case DataBuffer.TYPE_USHORT:
|
|
data.setElem(y * scanlineStride + x, ((short[])obj)[0] & 0xffff);
|
|
break;
|
|
case DataBuffer.TYPE_INT:
|
|
data.setElem(y * scanlineStride + x, ((int[])obj)[0]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compares this SinglePixelPackedSampleModel object with the specified
|
|
* object.
|
|
*
|
|
* @param o
|
|
* the Object to be compared.
|
|
* @return true, if this SinglePixelPackedSampleModel object is equal to the
|
|
* specified object, false otherwise.
|
|
*/
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
|
|
return false;
|
|
}
|
|
|
|
SinglePixelPackedSampleModel model = (SinglePixelPackedSampleModel)o;
|
|
return this.width == model.width && this.height == model.height
|
|
&& this.numBands == model.numBands && this.dataType == model.dataType
|
|
&& Arrays.equals(this.bitMasks, model.bitMasks)
|
|
&& Arrays.equals(this.bitOffsets, model.bitOffsets)
|
|
&& Arrays.equals(this.bitSizes, model.bitSizes)
|
|
&& this.scanlineStride == model.scanlineStride;
|
|
}
|
|
|
|
@Override
|
|
public SampleModel createSubsetSampleModel(int bands[]) {
|
|
if (bands.length > this.numBands) {
|
|
// awt.64=The number of the bands in the subset is greater than the
|
|
// number of bands in the sample model
|
|
throw new RasterFormatException(Messages.getString("awt.64")); //$NON-NLS-1$
|
|
}
|
|
|
|
int masks[] = new int[bands.length];
|
|
for (int i = 0; i < bands.length; i++) {
|
|
masks[i] = this.bitMasks[bands[i]];
|
|
}
|
|
return new SinglePixelPackedSampleModel(this.dataType, this.width, this.height,
|
|
this.scanlineStride, masks);
|
|
}
|
|
|
|
@Override
|
|
public SampleModel createCompatibleSampleModel(int w, int h) {
|
|
return new SinglePixelPackedSampleModel(this.dataType, w, h, this.bitMasks);
|
|
}
|
|
|
|
@Override
|
|
public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
|
|
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
int pixel[];
|
|
if (iArray == null) {
|
|
pixel = new int[this.numBands];
|
|
} else {
|
|
pixel = iArray;
|
|
}
|
|
|
|
for (int i = 0; i < this.numBands; i++) {
|
|
pixel[i] = getSample(x, y, i, data);
|
|
}
|
|
|
|
return pixel;
|
|
}
|
|
|
|
@Override
|
|
public void setPixel(int x, int y, int iArray[], DataBuffer data) {
|
|
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
for (int i = 0; i < this.numBands; i++) {
|
|
setSample(x, y, i, iArray[i], data);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getSample(int x, int y, int b, DataBuffer data) {
|
|
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
int sample = data.getElem(y * scanlineStride + x);
|
|
return ((sample & this.bitMasks[b]) >>> this.bitOffsets[b]);
|
|
}
|
|
|
|
@Override
|
|
public int[] getPixels(int x, int y, int w, int h, int iArray[], DataBuffer data) {
|
|
if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
|
|
|| ((long)y + (long)h > this.height)) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
|
|
int pixels[];
|
|
|
|
if (iArray == null) {
|
|
pixels = new int[w * h * this.numBands];
|
|
} else {
|
|
pixels = iArray;
|
|
}
|
|
|
|
int idx = 0;
|
|
|
|
for (int i = y; i < y + h; i++) {
|
|
for (int j = x; j < x + w; j++) {
|
|
for (int n = 0; n < this.numBands; n++) {
|
|
pixels[idx++] = getSample(j, i, n, data);
|
|
}
|
|
}
|
|
}
|
|
return pixels;
|
|
}
|
|
|
|
@Override
|
|
public void setPixels(int x, int y, int w, int h, int iArray[], DataBuffer data) {
|
|
if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
|
|
|| ((long)y + (long)h > this.height)) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
|
|
int idx = 0;
|
|
|
|
for (int i = y; i < y + h; i++) {
|
|
for (int j = x; j < x + w; j++) {
|
|
for (int n = 0; n < this.numBands; n++) {
|
|
setSample(j, i, n, iArray[idx++], data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setSample(int x, int y, int b, int s, DataBuffer data) {
|
|
if (x < 0 || y < 0 || x >= this.width || y >= this.height) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
int tmp = data.getElem(y * scanlineStride + x);
|
|
tmp &= ~this.bitMasks[b];
|
|
tmp |= (s << this.bitOffsets[b]) & this.bitMasks[b];
|
|
data.setElem(y * scanlineStride + x, tmp);
|
|
}
|
|
|
|
@Override
|
|
public int[] getSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) {
|
|
if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
|
|
|| ((long)y + (long)h > this.height)) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
|
|
int samples[];
|
|
int idx = 0;
|
|
|
|
if (iArray == null) {
|
|
samples = new int[w * h];
|
|
} else {
|
|
samples = iArray;
|
|
}
|
|
|
|
for (int i = y; i < y + h; i++) {
|
|
for (int j = x; j < x + w; j++) {
|
|
samples[idx++] = getSample(j, i, b, data);
|
|
}
|
|
}
|
|
|
|
return samples;
|
|
}
|
|
|
|
@Override
|
|
public void setSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) {
|
|
if ((x < 0) || (y < 0) || ((long)x + (long)w > this.width)
|
|
|| ((long)y + (long)h > this.height)) {
|
|
// awt.63=Coordinates are not in bounds
|
|
throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$
|
|
}
|
|
|
|
int idx = 0;
|
|
for (int i = y; i < y + h; i++) {
|
|
for (int j = x; j < x + w; j++) {
|
|
setSample(x + j, y + i, b, iArray[idx++], data);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public DataBuffer createDataBuffer() {
|
|
DataBuffer data = null;
|
|
int size = (this.height - 1) * scanlineStride + width;
|
|
|
|
switch (this.dataType) {
|
|
case DataBuffer.TYPE_BYTE:
|
|
data = new DataBufferByte(size);
|
|
break;
|
|
case DataBuffer.TYPE_USHORT:
|
|
data = new DataBufferUShort(size);
|
|
break;
|
|
case DataBuffer.TYPE_INT:
|
|
data = new DataBufferInt(size);
|
|
break;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Gets the offset of the specified pixel in the data array.
|
|
*
|
|
* @param x
|
|
* the X coordinate of the specified pixel.
|
|
* @param y
|
|
* the Y coordinate of the specified pixel.
|
|
* @return the offset of the specified pixel.
|
|
*/
|
|
public int getOffset(int x, int y) {
|
|
return (y * scanlineStride + x);
|
|
}
|
|
|
|
@Override
|
|
public int getSampleSize(int band) {
|
|
return bitSizes[band];
|
|
}
|
|
|
|
@Override
|
|
public int[] getSampleSize() {
|
|
return bitSizes.clone();
|
|
}
|
|
|
|
/**
|
|
* Gets an array of the bit offsets of the data array elements.
|
|
*
|
|
* @return an array of the bit offsets.
|
|
*/
|
|
public int[] getBitOffsets() {
|
|
return bitOffsets.clone();
|
|
}
|
|
|
|
/**
|
|
* Gets an array of the bit masks for all bands.
|
|
*
|
|
* @return an array of the bit masks for all bands.
|
|
*/
|
|
public int[] getBitMasks() {
|
|
return bitMasks.clone();
|
|
}
|
|
|
|
/**
|
|
* Returns a hash code of this MultiPixelPackedSampleModel class.
|
|
*
|
|
* @return the hash code of this MultiPixelPackedSampleModel class.
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
int hash = 0;
|
|
int tmp = 0;
|
|
|
|
hash = width;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
hash ^= height;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
hash ^= numBands;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
hash ^= dataType;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
for (int element : bitMasks) {
|
|
hash ^= element;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
}
|
|
for (int element : bitOffsets) {
|
|
hash ^= element;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
}
|
|
for (int element : bitSizes) {
|
|
hash ^= element;
|
|
tmp = hash >>> 24;
|
|
hash <<= 8;
|
|
hash |= tmp;
|
|
}
|
|
hash ^= scanlineStride;
|
|
return hash;
|
|
}
|
|
|
|
/**
|
|
* Gets the scanline stride.
|
|
*
|
|
* @return the scanline stride
|
|
*/
|
|
public int getScanlineStride() {
|
|
return this.scanlineStride;
|
|
}
|
|
|
|
@Override
|
|
public int getNumDataElements() {
|
|
return 1;
|
|
}
|
|
|
|
}
|