/* * 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 ComponentSampleModel class represents a set of image data whose each * element - the sample of a pixel - takes one data element of the DataBuffer. * <p> * The Bank indices denote the correspondence between the bank of data buffers * and a band of image data. The Pixel stride is the number of data array * elements between two samples for the same band on the same scanline. The * pixel stride for a BandedSampleModel is one. The scanline stride represents * the number of data array elements between a specified sample and the * corresponding sample in the same column in the next scanline. The array of * band offsets gives the starting offsets within each data banks of the in the * DataBuffer. The bank indices represents the indices within each bank of the * DataBuffer corresponding to a band of image data. * * @since Android 1.0 */ public class ComponentSampleModel extends SampleModel { /** * The band offsets array of this ComponentSampleModel. */ protected int bandOffsets[]; /** * The bank indices array of this ComponentSampleModel. */ protected int bankIndices[]; /** * The number of bands in this ComponentSampleModel. */ protected int numBands; /** * The number banks of this ComponentSampleModel. */ protected int numBanks; /** * The scanline stride of this ComponentSampleModel. */ protected int scanlineStride; /** * The pixel stride of this ComponentSampleModel. */ protected int pixelStride; /** * Instantiates a new ComponentSampleModel with the specified properties. * * @param dataType * the data type of samples. * @param w * the width of the image data. * @param h * the height of the image data. * @param pixelStride * the pixel stride of the image data. * @param scanlineStride * the scanline stride of the image data. * @param bankIndices * the array of the bank indices. * @param bandOffsets * the array of the band offsets. */ public ComponentSampleModel(int dataType, int w, int h, int pixelStride, int scanlineStride, int bankIndices[], int bandOffsets[]) { super(dataType, w, h, bandOffsets.length); if (pixelStride < 0) { // awt.24B=Pixel stride must be >= 0 throw new IllegalArgumentException(Messages.getString("awt.24B")); //$NON-NLS-1$ } if (scanlineStride < 0) { // awt.24C=Scanline stride must be >= 0 throw new IllegalArgumentException(Messages.getString("awt.24C")); //$NON-NLS-1$ } if (bankIndices.length != bandOffsets.length) { // awt.24D=Bank Indices length must be equal Bank Offsets length throw new IllegalArgumentException(Messages.getString("awt.24D")); //$NON-NLS-1$ } this.pixelStride = pixelStride; this.scanlineStride = scanlineStride; this.bandOffsets = bandOffsets.clone(); this.bankIndices = bankIndices.clone(); this.numBands = bandOffsets.length; int maxBank = 0; for (int i = 0; i < bankIndices.length; i++) { if (bankIndices[i] < 0) { // awt.24E=Index of {0} bank must be >= 0 throw new IllegalArgumentException(Messages.getString("awt.24E", i)); //$NON-NLS-1$ } if (bankIndices[i] > maxBank) { maxBank = bankIndices[i]; } } this.numBanks = maxBank + 1; } /** * Instantiates a new ComponentSampleModel with the specified properties. * * @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 pixelStride * the pixel stride of the image data. * @param scanlineStride * the scanline stride of the image data. * @param bandOffsets * the band offsets. */ public ComponentSampleModel(int dataType, int w, int h, int pixelStride, int scanlineStride, int bandOffsets[]) { super(dataType, w, h, bandOffsets.length); if (pixelStride < 0) { // awt.24B=Pixel stride must be >= 0 throw new IllegalArgumentException(Messages.getString("awt.24B")); //$NON-NLS-1$ } if (scanlineStride < 0) { // awt.24C=Scanline stride must be >= 0 throw new IllegalArgumentException(Messages.getString("awt.24C")); //$NON-NLS-1$ } this.pixelStride = pixelStride; this.scanlineStride = scanlineStride; this.bandOffsets = bandOffsets.clone(); this.numBands = bandOffsets.length; this.numBanks = 1; this.bankIndices = new int[numBands]; for (int i = 0; i < numBands; i++) { bankIndices[i] = 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 (dataType) { case DataBuffer.TYPE_BYTE: byte bdata[]; if (obj == null) { bdata = new byte[numBands]; } else { bdata = (byte[])obj; } for (int i = 0; i < numBands; i++) { bdata[i] = (byte)getSample(x, y, i, data); } obj = bdata; break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: short sdata[]; if (obj == null) { sdata = new short[numBands]; } else { sdata = (short[])obj; } for (int i = 0; i < numBands; i++) { sdata[i] = (short)getSample(x, y, i, data); } obj = sdata; break; case DataBuffer.TYPE_INT: int idata[]; if (obj == null) { idata = new int[numBands]; } else { idata = (int[])obj; } for (int i = 0; i < numBands; i++) { idata[i] = getSample(x, y, i, data); } obj = idata; break; case DataBuffer.TYPE_FLOAT: float fdata[]; if (obj == null) { fdata = new float[numBands]; } else { fdata = (float[])obj; } for (int i = 0; i < numBands; i++) { fdata[i] = getSampleFloat(x, y, i, data); } obj = fdata; break; case DataBuffer.TYPE_DOUBLE: double ddata[]; if (obj == null) { ddata = new double[numBands]; } else { ddata = (double[])obj; } for (int i = 0; i < numBands; i++) { ddata[i] = getSampleDouble(x, y, i, data); } obj = ddata; 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 (dataType) { case DataBuffer.TYPE_BYTE: byte barr[] = (byte[])obj; for (int i = 0; i < numBands; i++) { setSample(x, y, i, barr[i] & 0xff, data); } break; case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_USHORT: short sarr[] = (short[])obj; for (int i = 0; i < numBands; i++) { setSample(x, y, i, sarr[i] & 0xffff, data); } break; case DataBuffer.TYPE_INT: int iarr[] = (int[])obj; for (int i = 0; i < numBands; i++) { setSample(x, y, i, iarr[i], data); } break; case DataBuffer.TYPE_FLOAT: float farr[] = (float[])obj; for (int i = 0; i < numBands; i++) { setSample(x, y, i, farr[i], data); } break; case DataBuffer.TYPE_DOUBLE: double darr[] = (double[])obj; for (int i = 0; i < numBands; i++) { setSample(x, y, i, darr[i], data); } break; } } /** * Compares this ComponentSampleModel with the specified Object. * * @param o * the Object. * @return true, if the object is a ComponentSampleModel with identical data * values to this ComponentSampleModel, false otherwise. */ @Override public boolean equals(Object o) { if ((o == null) || !(o instanceof ComponentSampleModel)) { return false; } ComponentSampleModel model = (ComponentSampleModel)o; return this.width == model.width && this.height == model.height && this.numBands == model.numBands && this.dataType == model.dataType && Arrays.equals(this.bandOffsets, model.bandOffsets) && Arrays.equals(this.bankIndices, model.bankIndices) && this.numBands == model.numBands && this.numBanks == model.numBanks && this.scanlineStride == model.scanlineStride && this.pixelStride == model.pixelStride; } /** * @see java.awt.image.SampleModel#createSubsetSampleModel(int[]) */ @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 indices[] = new int[bands.length]; int offsets[] = new int[bands.length]; for (int i = 0; i < bands.length; i++) { indices[i] = bankIndices[bands[i]]; offsets[i] = bandOffsets[bands[i]]; } return new ComponentSampleModel(dataType, width, height, pixelStride, scanlineStride, indices, offsets); } @Override public SampleModel createCompatibleSampleModel(int w, int h) { return new ComponentSampleModel(dataType, w, h, pixelStride, pixelStride * w, bankIndices, bandOffsets); } @Override public int[] getPixel(int x, int y, int iArray[], DataBuffer data) { int pixel[]; if (iArray == null) { pixel = new int[numBands]; } else { pixel = iArray; } for (int i = 0; i < numBands; i++) { pixel[i] = getSample(x, y, i, data); } return pixel; } @Override public void setPixel(int x, int y, int iArray[], DataBuffer data) { for (int i = 0; i < 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$ } return data.getElem(bankIndices[b], y * scanlineStride + x * pixelStride + bandOffsets[b]); } @Override public float getSampleFloat(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$ } return data.getElemFloat(bankIndices[b], y * scanlineStride + x * pixelStride + bandOffsets[b]); } @Override public double getSampleDouble(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$ } return data.getElemDouble(bankIndices[b], y * scanlineStride + x * pixelStride + bandOffsets[b]); } @Override public int[] getPixels(int x, int y, int w, int h, int iArray[], DataBuffer data) { if (x < 0 || y < 0 || x > this.width || x + w > this.width || y > this.height || y + h > this.height) { // awt.63=Coordinates are not in bounds throw new ArrayIndexOutOfBoundsException(Messages.getString("awt.63")); //$NON-NLS-1$ } int pixels[] = null; int idx = 0; if (iArray == null) { pixels = new int[w * h * numBands]; } else { pixels = iArray; } for (int i = y; i < y + h; i++) { for (int j = x; j < x + w; j++) { for (int n = 0; n < 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 || x + w > this.width || y + 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 < 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$ } data.setElem(bankIndices[b], y * scanlineStride + x * pixelStride + bandOffsets[b], s); } @Override public int[] getSamples(int x, int y, int w, int h, int b, int iArray[], DataBuffer data) { if (x < 0 || y < 0 || x + w > this.width || y + 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; } if (data == null) { // awt.295=data is null throw new NullPointerException(Messages.getString("awt.295")); //$NON-NLS-1$ } 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 || x + w > this.width || y + 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(j, i, b, iArray[idx++], data); } } } @Override public void setSample(int x, int y, int b, float 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$ } data.setElemFloat(bankIndices[b], y * scanlineStride + x * pixelStride + bandOffsets[b], s); } @Override public void setSample(int x, int y, int b, double 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$ } data .setElemDouble(bankIndices[b], y * scanlineStride + x * pixelStride + bandOffsets[b], s); } @Override public DataBuffer createDataBuffer() { DataBuffer data = null; int maxOffset = bandOffsets[0]; for (int i = 1; i < bandOffsets.length; i++) { if (bandOffsets[i] > maxOffset) { maxOffset = bandOffsets[i]; } } int size = (height - 1) * scanlineStride + (width - 1) * pixelStride + maxOffset + 1; switch (dataType) { case DataBuffer.TYPE_BYTE: data = new DataBufferByte(size, numBanks); break; case DataBuffer.TYPE_SHORT: data = new DataBufferShort(size, numBanks); break; case DataBuffer.TYPE_USHORT: data = new DataBufferUShort(size, numBanks); break; case DataBuffer.TYPE_INT: data = new DataBufferInt(size, numBanks); break; case DataBuffer.TYPE_FLOAT: data = new DataBufferFloat(size, numBanks); break; case DataBuffer.TYPE_DOUBLE: data = new DataBufferDouble(size, numBanks); break; } return data; } /** * Gets the offset of the specified band of the specified pixel. * * @param x * the X coordinate of the pixel. * @param y * the Y coordinate of the pixel. * @param b * the band. * @return the offset of the specified band of the specified pixel. */ public int getOffset(int x, int y, int b) { return y * scanlineStride + x * pixelStride + bandOffsets[b]; } /** * Gets the offset of the first band of the specified pixel. * * @param x * the X coordinate of pixel. * @param y * the Y coordinate of pixel. * @return the offset of the first band of the specified pixel. */ public int getOffset(int x, int y) { return y * scanlineStride + x * pixelStride + bandOffsets[0]; } @Override public final int getSampleSize(int band) { return DataBuffer.getDataTypeSize(dataType); } @Override public final int[] getSampleSize() { int sampleSizes[] = new int[numBands]; int size = DataBuffer.getDataTypeSize(dataType); for (int i = 0; i < numBands; i++) { sampleSizes[i] = size; } return sampleSizes; } /** * Gets an array of bank indices corresponding to this ComponentSampleModel. * * @return the array of bank indices. */ public final int[] getBankIndices() { return bankIndices.clone(); } /** * Gets an array of the band offsets corresponding to this * ComponentSampleModel. * * @return the array of band offsets. */ public final int[] getBandOffsets() { return bandOffsets.clone(); } /** * Gets a hash code of this ComponentSampleModel object. * * @return a hash code of this ComponentSampleModel object. */ @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 : bandOffsets) { hash ^= element; tmp = hash >>> 24; hash <<= 8; hash |= tmp; } for (int element : bankIndices) { hash ^= element; tmp = hash >>> 24; hash <<= 8; hash |= tmp; } hash ^= pixelStride; tmp = hash >>> 24; hash <<= 8; hash |= tmp; hash ^= scanlineStride; return hash; } /** * Gets the scanline stride of this ComponentSampleModel. * * @return the scanline stride of this ComponentSampleModel. */ public final int getScanlineStride() { return scanlineStride; } /** * Gets the pixel stride. * * @return the pixel stride. */ public final int getPixelStride() { return pixelStride; } @Override public final int getNumDataElements() { return numBands; } }