diff options
Diffstat (limited to 'awt/java/awt/image/MultiPixelPackedSampleModel.java')
-rw-r--r-- | awt/java/awt/image/MultiPixelPackedSampleModel.java | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/awt/java/awt/image/MultiPixelPackedSampleModel.java b/awt/java/awt/image/MultiPixelPackedSampleModel.java new file mode 100644 index 0000000..dd44b49 --- /dev/null +++ b/awt/java/awt/image/MultiPixelPackedSampleModel.java @@ -0,0 +1,454 @@ +/* + * 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 org.apache.harmony.awt.internal.nls.Messages; + +/** + * The MultiPixelPackedSampleModel class represents image data with one + * band. This class packs multiple pixels with one sample in one data + * element and supports the following data types: DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT. + */ +public class MultiPixelPackedSampleModel extends SampleModel { + + /** The pixel bit stride. */ + private int pixelBitStride; + + /** The scanline stride. */ + private int scanlineStride; + + /** The data bit offset. */ + private int dataBitOffset; + + /** The bit mask. */ + private int bitMask; + + /** The data element size. */ + private int dataElementSize; + + /** The pixels per data element. */ + private int pixelsPerDataElement; + + /** + * Instantiates a new MultiPixelPackedSampleModel 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 numberOfBits the number of bits per pixel. + * @param scanlineStride the scanline stride of the of the image data. + * @param dataBitOffset the array of the band offsets. + */ + public MultiPixelPackedSampleModel(int dataType, int w, int h, + int numberOfBits, int scanlineStride, int dataBitOffset) { + + super(dataType, w, h, 1); + 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; + if(numberOfBits == 0) { + // awt.20C=Number of Bits equals to zero + throw new RasterFormatException(Messages.getString("awt.20C")); //$NON-NLS-1$ + } + this.pixelBitStride = numberOfBits; + this.dataElementSize = DataBuffer.getDataTypeSize(dataType); + if(dataElementSize % pixelBitStride != 0) { + // awt.20D=The number of bits per pixel is not a power of 2 or pixels span data element boundaries + throw new RasterFormatException(Messages.getString("awt.20D")); //$NON-NLS-1$ + } + + if(dataBitOffset % numberOfBits != 0) { + // awt.20E=Data Bit offset is not a multiple of pixel bit stride + throw new RasterFormatException(Messages.getString("awt.20E")); //$NON-NLS-1$ + } + this.dataBitOffset = dataBitOffset; + + this.pixelsPerDataElement = dataElementSize / pixelBitStride; + this.bitMask = (1 << numberOfBits) - 1; + } + + /** + * Instantiates a new MultiPixelPackedSampleModel 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 numberOfBits the number of bits per pixel. + */ + public MultiPixelPackedSampleModel(int dataType, int w, int h, + int numberOfBits) { + + this(dataType, w, h, numberOfBits, (numberOfBits * w + + DataBuffer.getDataTypeSize(dataType) - 1) / + DataBuffer.getDataTypeSize(dataType), 0); + } + + @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) getSample(x, y, 0, data); + obj = bdata; + break; + case DataBuffer.TYPE_USHORT: + short sdata[]; + if (obj == null) { + sdata = new short[1]; + } else { + sdata = (short[]) obj; + } + sdata[0] = (short) getSample(x, y, 0, data); + obj = sdata; + break; + case DataBuffer.TYPE_INT: + int idata[]; + if (obj == null) { + idata = new int[1]; + } else { + idata = (int[]) obj; + } + idata[0] = getSample(x, y, 0, data); + obj = idata; + break; + } + + return obj; + } + + @Override + public void setDataElements(int x, int y, Object obj, DataBuffer data) { + setSample(x, y, obj, data, 1, 0); + } + + /** + * Compares this MultiPixelPackedSampleModel object with + * the specified object. + * + * @param o the Object to be compared. + * + * @return true, if the object is a MultiPixelPackedSampleModel + * with the same data parameter values as this MultiPixelPackedSampleModel, + * false otherwise. + */ + @Override + public boolean equals(Object o) { + if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) { + return false; + } + + MultiPixelPackedSampleModel model = (MultiPixelPackedSampleModel) o; + return this.width == model.width && + this.height == model.height && + this.numBands == model.numBands && + this.dataType == model.dataType && + this.pixelBitStride == model.pixelBitStride && + this.bitMask == model.bitMask && + this.pixelsPerDataElement == model.pixelsPerDataElement && + this.dataElementSize == model.dataElementSize && + this.dataBitOffset == model.dataBitOffset && + this.scanlineStride == model.scanlineStride; + } + + @Override + public SampleModel createSubsetSampleModel(int bands[]) { + if (bands != null && bands.length != 1) { + // awt.20F=Number of bands must be only 1 + throw new RasterFormatException(Messages.getString("awt.20F")); //$NON-NLS-1$ + } + return createCompatibleSampleModel(width, height); + } + + @Override + public SampleModel createCompatibleSampleModel(int w, int h) { + return new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride); + } + + @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[numBands]; + } else { + pixel = iArray; + } + + pixel[0] = getSample(x, y, 0, data); + return pixel; + } + + @Override + public void setPixel(int x, int y, int iArray[], DataBuffer data) { + setSample(x, y, iArray, data, 2, 0); + } + + @Override + public int getSample(int x, int y, int b, DataBuffer data) { + if (x < 0 || y < 0 || x >= this.width || y >= this.height || b != 0) { + // awt.63=Coordinates are not in bounds + throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$ + } + + int bitnum = dataBitOffset + x * pixelBitStride; + int elem = data.getElem(y * scanlineStride + bitnum / dataElementSize); + int shift = dataElementSize - (bitnum & (dataElementSize - 1)) - + pixelBitStride; + + return (elem >> shift) & bitMask; + } + + @Override + public void setSample(int x, int y, int b, int s, DataBuffer data) { + if (b != 0) { + // awt.63=Coordinates are not in bounds + throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$ + } + + setSample(x, y, null, data, 3, s); + } + + @Override + public DataBuffer createDataBuffer() { + DataBuffer dataBuffer = null; + int size = scanlineStride * height; + + switch (dataType) { + case DataBuffer.TYPE_BYTE: + dataBuffer = new DataBufferByte(size + (dataBitOffset + 7) / 8); + break; + case DataBuffer.TYPE_USHORT: + dataBuffer = new DataBufferUShort(size + (dataBitOffset + 15) / 16); + break; + case DataBuffer.TYPE_INT: + dataBuffer = new DataBufferInt(size + (dataBitOffset + 31) / 32); + break; + } + return dataBuffer; + } + + /** + * 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 * pixelBitStride + dataBitOffset) / + dataElementSize; + } + + @Override + public int getSampleSize(int band) { + return pixelBitStride; + } + + /** + * Gets the bit offset in the data element which + * is stored for the specified pixel of a scanline. + * + * @param x the pixel. + * + * @return the bit offset of the pixel in the data element. + */ + public int getBitOffset(int x) { + return (x * pixelBitStride + dataBitOffset) % dataElementSize; + } + + @Override + public int[] getSampleSize() { + int sampleSizes[] = { pixelBitStride }; + return sampleSizes; + } + + /** + * 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; + hash ^= scanlineStride; + tmp = hash >>> 24; + hash <<= 8; + hash |= tmp; + hash ^= pixelBitStride; + tmp = hash >>> 24; + hash <<= 8; + hash |= tmp; + hash ^= dataBitOffset; + tmp = hash >>> 24; + hash <<= 8; + hash |= tmp; + hash ^= bitMask; + tmp = hash >>> 24; + hash <<= 8; + hash |= tmp; + hash ^= dataElementSize; + tmp = hash >>> 24; + hash <<= 8; + hash |= tmp; + hash ^= pixelsPerDataElement; + return hash; + } + + @Override + public int getTransferType() { + if (pixelBitStride > 16) { + return DataBuffer.TYPE_INT; + } else if (pixelBitStride > 8) { + return DataBuffer.TYPE_USHORT; + } else { + return DataBuffer.TYPE_BYTE; + } + } + + /** + * Gets the scanline stride of this MultiPixelPackedSampleModel. + * + * @return the scanline stride of this MultiPixelPackedSampleModel. + */ + public int getScanlineStride() { + return scanlineStride; + } + + /** + * Gets the pixel bit stride of this MultiPixelPackedSampleModel. + * + * @return the pixel bit stride of this MultiPixelPackedSampleModel. + */ + public int getPixelBitStride() { + return pixelBitStride; + } + + @Override + public int getNumDataElements() { + return 1; + } + + /** + * Gets the data bit offset. + * + * @return the data bit offset. + */ + public int getDataBitOffset() { + return dataBitOffset; + } + + /** + * This method is used by other methods of this class. The behaviour of + * this method depends on the method which has been invoke this one. The + * argument methodId is used to choose valid behaviour in a particular case. + * If methodId is equal to 1 it means that this method has been invoked by + * the setDataElements() method, 2 - means setPixel(), and setSample() in + * any other cases. + * + * @param x the x + * @param y the y + * @param obj the obj + * @param data the data + * @param methodId the method id + * @param s the s + */ + private void setSample(final int x, final int y, final Object obj, + final DataBuffer data, final int methodId, int s) { + 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$ + } + + final int bitnum = dataBitOffset + x * pixelBitStride; + final int idx = y * scanlineStride + bitnum / dataElementSize; + final int shift = dataElementSize - (bitnum & (dataElementSize - 1)) + - pixelBitStride; + final int mask = ~(bitMask << shift); + int elem = data.getElem(idx); + + switch (methodId) { + case 1: { // Invoked from setDataElements() + switch (getTransferType()) { + case DataBuffer.TYPE_BYTE: + s = ((byte[]) obj)[0] & 0xff; + break; + case DataBuffer.TYPE_USHORT: + s = ((short[]) obj)[0] & 0xffff; + break; + case DataBuffer.TYPE_INT: + s = ((int[]) obj)[0]; + break; + } + break; + } + case 2: { // Invoked from setPixel() + s = ((int[]) obj)[0]; + break; + } + } + + elem &= mask; + elem |= (s & bitMask) << shift; + data.setElem(idx, elem); + } +} + |