/* * $RCSfile: LookupTableJAI.java,v $ * * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.1 $ * $Date: 2005/02/11 04:57:12 $ * $State: Exp $ */ package com.lightcrafts.mediax.jai; import java.awt.Rectangle; import java.awt.Point; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.DataBufferShort; import java.awt.image.DataBufferUShort; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import com.lightcrafts.mediax.jai.remote.SerializableState; import com.lightcrafts.mediax.jai.remote.SerializerFactory; import com.lightcrafts.media.jai.util.DataBufferUtils; /** * A lookup table object associated with the "Lookup" operation. The * "Lookup" operation is described in * com.lightcrafts.mediax.jai.operator.LookupDescriptor. * *

This object represents a single- or multi-banded table of any * JAI supported data type. A single- or multi-banded source image * of integral data types is passed through the table and transformed * into a single- or multi-banded destination image of either integral * and floating point data types. * *

The table data may cover only a subrange of the legal range of the * input data type. The subrange is selected by means of an offset parameter * which is to be subtracted from the input value before indexing into the * table array. When only a subranged table is used with a source image, it * is up to the user to make certain that the source image does not have * pixel values outside of the table range. Otherwise, * an ArrayIndexOutOfBoundsException can occur. * *

The table data is saved by reference only. * * @see com.lightcrafts.mediax.jai.operator.LookupDescriptor * */ public class LookupTableJAI extends Object implements Serializable { /** The table data. */ transient DataBuffer data; /** The band offset values */ private int[] tableOffsets; /** * Constructs a single-banded byte lookup table. The index offset is 0. * * @param data The single-banded byte data. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(byte[] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.data = new DataBufferByte(data, data.length); this.initOffsets(1, 0); } /** * Constructs a single-banded byte lookup table with an index offset. * * @param data The single-banded byte data. * @param offset The offset. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(byte[] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, offset); this.data = new DataBufferByte(data, data.length); } /** * Constructs a multi-banded byte lookup table. The index offset for * each band is 0. * * @param data The multi-banded byte data in [band][index] format. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(byte[][] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, 0); this.data = new DataBufferByte(data, data[0].length); } /** * Constructs a multi-banded byte lookup table where all bands have * the same index offset. * * @param data The multi-banded byte data in [band][index] format. * @param offset The common offset for all bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(byte[][] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offset); this.data = new DataBufferByte(data, data[0].length); } /** * Constructs a multi-banded byte lookup table where each band has * a different index offset. * * @param data The multi-banded byte data in [band][index] format. * @param offsets The offsets for the bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(byte[][] data, int[] offsets) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offsets); this.data = new DataBufferByte(data, data[0].length); } /** * Constructs a single-banded short or unsigned short lookup table. * The index offset is 0. * * @param data The single-banded short data. * @param isUShort True if data type is DataBuffer.TYPE_USHORT; * false if data type is DataBuffer.TYPE_SHORT. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(short[] data, boolean isUShort) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, 0); if (isUShort) { this.data = new DataBufferUShort(data, data.length); } else { this.data = new DataBufferShort(data, data.length); } } /** * Constructs a single-banded short or unsigned short lookup table with * an index offset. * * @param data The single-banded short data. * @param offset The offset. * @param isUShort True if data type is DataBuffer.TYPE_USHORT; * false if data type is DataBuffer.TYPE_SHORT. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(short[] data, int offset, boolean isUShort) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, offset); if (isUShort) { this.data = new DataBufferUShort(data, data.length); } else { this.data = new DataBufferShort(data, data.length); } } /** * Constructs a multi-banded short or unsigned short lookup table. * The index offset for each band is 0. * * @param data The multi-banded short data in [band][index] format. * @param isUShort True if data type is DataBuffer.TYPE_USHORT; * false if data type is DataBuffer.TYPE_SHORT. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(short[][] data, boolean isUShort) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, 0); if (isUShort) { this.data = new DataBufferUShort(data, data[0].length); } else { this.data = new DataBufferShort(data, data[0].length); } } /** * Constructs a multi-banded short or unsigned short lookup table where all * bands have the same index offset. * * @param data The multi-banded short data in [band][index] format. * @param offset The common offset for all bands. * @param isUShort True if data type is DataBuffer.TYPE_USHORT; * false if data type is DataBuffer.TYPE_SHORT. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(short[][] data, int offset, boolean isUShort) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offset); if (isUShort) { this.data = new DataBufferUShort(data, data[0].length); } else { this.data = new DataBufferShort(data, data[0].length); } } /** * Constructs a multi-banded short or unsigned short lookup table where * each band has a different index offset. * * @param data The multi-banded short data in [band][index] format. * @param offsets The offsets for the bands. * @param isUShort True if data type is DataBuffer.TYPE_USHORT; * false if data type is DataBuffer.TYPE_SHORT. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(short[][] data, int[] offsets, boolean isUShort) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offsets); if (isUShort) { this.data = new DataBufferUShort(data, data[0].length); } else { this.data = new DataBufferShort(data, data[0].length); } } /** * Constructs a single-banded int lookup table. The index offset is 0. * * @param data The single-banded int data. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(int[] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, 0); this.data = new DataBufferInt(data, data.length); } /** * Constructs a single-banded int lookup table with an index offset. * * @param data The single-banded int data. * @param offset The offset. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(int[] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, offset); this.data = new DataBufferInt(data, data.length); } /** * Constructs a multi-banded int lookup table. The index offset for * each band is 0. * * @param data The multi-banded int data in [band][index] format. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(int[][] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, 0); this.data = new DataBufferInt(data, data[0].length); } /** * Constructs a multi-banded int lookup table where all bands have * the same index offset. * * @param data The multi-banded int data in [band][index] format. * @param offset The common offset for all bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(int[][] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offset); this.data = new DataBufferInt(data, data[0].length); } /** * Constructs a multi-banded int lookup table where each band has * a different index offset. * * @param data The multi-banded int data in [band][index] format. * @param offsets The offsets for the bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(int[][] data, int[] offsets) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offsets); this.data = new DataBufferInt(data, data[0].length); } /** * Constructs a single-banded float lookup table. The index offset is 0. * * @param data The single-banded float data. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(float[] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, 0); this.data = DataBufferUtils.createDataBufferFloat(data, data.length); } /** * Constructs a single-banded float lookup table with an index offset. * * @param data The single-banded float data. * @param offset The offset. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(float[] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, offset); this.data = DataBufferUtils.createDataBufferFloat(data, data.length); } /** * Constructs a multi-banded float lookup table. The index offset for * each band is 0. * * @param data The multi-banded float data in [band][index] format. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(float[][] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, 0); this.data = DataBufferUtils.createDataBufferFloat(data, data[0].length); } /** * Constructs a multi-banded float lookup table where all bands have * the same index offset. * * @param data The multi-banded float data in [band][index] format. * @param offset The common offset for all bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(float[][] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offset); this.data = DataBufferUtils.createDataBufferFloat(data, data[0].length); } /** * Constructs a multi-banded float lookup table where each band has * a different index offset. * * @param data The multi-banded float data in [band][index] format. * @param offsets The offsets for the bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(float[][] data, int[] offsets) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offsets); this.data = DataBufferUtils.createDataBufferFloat(data, data[0].length); } /** * Constructs a single-banded double lookup table. The index offset is 0. * * @param data The single-banded double data. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(double[] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, 0); this.data = DataBufferUtils.createDataBufferDouble(data, data.length); } /** * Constructs a single-banded double lookup table with an index offset. * * @param data The single-banded double data. * @param offset The offset. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(double[] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(1, offset); this.data = DataBufferUtils.createDataBufferDouble(data, data.length); } /** * Constructs a multi-banded double lookup table. The index offset for * each band is 0. * * @param data The multi-banded double data in [band][index] format. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(double[][] data) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, 0); this.data = DataBufferUtils.createDataBufferDouble(data, data[0].length); } /** * Constructs a multi-banded double lookup table where all bands have * the same index offset. * * @param data The multi-banded double data in [band][index] format. * @param offset The common offset for all bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(double[][] data, int offset) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offset); this.data = DataBufferUtils.createDataBufferDouble(data, data[0].length); } /** * Constructs a multi-banded double lookup table where each band has * a different index offset. * * @param data The multi-banded double data in [band][index] format. * @param offsets The offsets for the bands. * @throws IllegalArgumentException if data is null. */ public LookupTableJAI(double[][] data, int[] offsets) { if ( data == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } this.initOffsets(data.length, offsets); this.data = DataBufferUtils.createDataBufferDouble(data, data[0].length); } /** * Returns the table data as a DataBuffer. */ public DataBuffer getData() { return data; } /** * Returns the byte table data in array format, or null if the * table's data type is not byte. */ public byte[][] getByteData() { return data instanceof DataBufferByte ? ((DataBufferByte)data).getBankData() : null; } /** * Returns the byte table data of a specific band in array format, * or null if the table's data type is not byte. */ public byte[] getByteData(int band) { return data instanceof DataBufferByte ? ((DataBufferByte)data).getData(band) : null; } /** * Returns the short table data in array format, or null if the * table's data type is not short. This includes both signed and * unsigned short table data. * */ public short[][] getShortData() { if (data instanceof DataBufferUShort) { return ((DataBufferUShort)data).getBankData(); } else if (data instanceof DataBufferShort) { return ((DataBufferShort)data).getBankData(); } else { return null; } } /** * Returns the short table data of a specific band in array format, * or null if the table's data type is not short. * */ public short[] getShortData(int band) { if (data instanceof DataBufferUShort) { return ((DataBufferUShort)data).getData(band); } else if (data instanceof DataBufferShort) { return ((DataBufferShort)data).getData(band); } else { return null; } } /** * Returns the integer table data in array format, or null if the * table's data type is not int. * */ public int[][] getIntData() { return data instanceof DataBufferInt ? ((DataBufferInt)data).getBankData() : null; } /** * Returns the integer table data of a specific band in array format, * or null if table's data type is not int. * */ public int[] getIntData(int band) { return data instanceof DataBufferInt ? ((DataBufferInt)data).getData(band) : null; } /** * Returns the float table data in array format, or null if the * table's data type is not float. * */ public float[][] getFloatData() { return data.getDataType() == DataBuffer.TYPE_FLOAT ? DataBufferUtils.getBankDataFloat(data) : null; } /** * Returns the float table data of a specific band in array format, * or null if table's data type is not float. * */ public float[] getFloatData(int band) { return data.getDataType() == DataBuffer.TYPE_FLOAT ? DataBufferUtils.getDataFloat(data, band) : null; } /** * Returns the double table data in array format, or null if the * table's data type is not double. * */ public double[][] getDoubleData() { return data.getDataType() == DataBuffer.TYPE_DOUBLE ? DataBufferUtils.getBankDataDouble(data) : null; } /** * Returns the double table data of a specific band in array format, * or null if table's data type is not double. * */ public double[] getDoubleData(int band) { return data.getDataType() == DataBuffer.TYPE_DOUBLE ? DataBufferUtils.getDataDouble(data, band) : null; } /** Returns the index offsets of entry 0 for all bands. */ public int[] getOffsets() { return tableOffsets; } /** * Returns the index offset of entry 0 for the default band. * */ public int getOffset() { return tableOffsets[0]; } /** * Returns the index offset of entry 0 for a specific band. * */ public int getOffset(int band) { return tableOffsets[band]; } /** Returns the number of bands of the table. */ public int getNumBands() { return data.getNumBanks(); } /** * Returns the number of entries per band of the table. * */ public int getNumEntries() { return data.getSize(); } /** Returns the data type of the table data. * */ public int getDataType() { return data.getDataType(); } /** * Returns the number of bands of the destination image, based on * the number of bands of the source image and lookup table. * * @param srcNumBands The number of bands of the source image. * @return the number of bands in destination image. */ public int getDestNumBands(int srcNumBands) { int tblNumBands = getNumBands(); return srcNumBands == 1 ? tblNumBands : srcNumBands; } /** * Returns a SampleModel suitable for holding the output * of a lookup operation on the source data described by a given * SampleModel with this table. The width and height of the destination * SampleModel are the same as that of the source. This method will * return null if the source SampleModel has a non-integral data type. * * @param srcSampleModel The SampleModel of the source image. * * @throws IllegalArgumentException if srcSampleModel is null. * @return sampleModel suitable for the destination image. */ public SampleModel getDestSampleModel(SampleModel srcSampleModel) { if ( srcSampleModel == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } return getDestSampleModel(srcSampleModel, srcSampleModel.getWidth(), srcSampleModel.getHeight()); } /** * Returns a SampleModel suitable for holding the output * of a lookup operation on the source data described by a given * SampleModel with this table. This method will return null if the * source SampleModel has a non-integral data type. * * @param srcSampleModel The SampleModel of the source image. * @param width The width of the destination SampleModel. * @param height The height of the destination SampleModel. * * @throws IllegalArgumentException if srcSampleModel is null. * @return sampleModel suitable for the destination image. */ public SampleModel getDestSampleModel(SampleModel srcSampleModel, int width, int height) { if ( srcSampleModel == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } if (!isIntegralDataType(srcSampleModel)) { return null; // source has non-integral data type } return RasterFactory.createComponentSampleModel(srcSampleModel, getDataType(), width, height, getDestNumBands(srcSampleModel.getNumBands())); } /** * Validates data type. Returns true if it's one of the integral * data types; false otherwise. * * @throws IllegalArgumentException if sampleModel is null. */ public boolean isIntegralDataType(SampleModel sampleModel) { if ( sampleModel == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } return isIntegralDataType(sampleModel.getTransferType()); } /** * Returns true if the specified data type is * an integral data type, such as byte, ushort, short, or int. */ public boolean isIntegralDataType(int dataType) { if ((dataType == DataBuffer.TYPE_BYTE) || (dataType == DataBuffer.TYPE_USHORT) || (dataType == DataBuffer.TYPE_SHORT) || (dataType == DataBuffer.TYPE_INT)){ return true; } else { return false; } } /** * Performs lookup on a given value belonging to a given source * band, and returns the result as an int. * * @param band The source band the value is from. * @param value The source value to be placed through the lookup table. */ public int lookup(int band, int value) { return data.getElem(band, value-tableOffsets[band]); } /** * Performs lookup on a given value belonging to a given source * band, and returns the result as a float. * * @param band The source band the value is from. * @param value The source value to be placed through the lookup table. */ public float lookupFloat(int band, int value) { return data.getElemFloat(band, value-tableOffsets[band]); } /** * Performs lookup on a given value belonging to a given source * band, and returns the result as a double. * * @param band The source band the value is from. * @param value The source value to be placed through the lookup table. */ public double lookupDouble(int band, int value) { return data.getElemDouble(band, value-tableOffsets[band]); } /** * Performs table lookup in place on a given WritableRaster. The * The lookup operation must preserve the data type and * SampleModel of the source. A reference to the supplied * WritableRaster will be returned. * * @throws IllegalArgumentException if the src is null. * @throws IllegalArgumentException if the source's SampleModel * is not of integral type. * @throws IllegalArgumentException if the lookup operation would * result in a change in the data type or number of bands * of the Raster. */ public WritableRaster lookup(WritableRaster src) { if ( src == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } return lookup(src, src, src.getBounds()); } /** * Performs table lookup on a source Raster, writing the result * into a supplied WritableRaster. The destination must have a * data type and SampleModel appropriate to the results of the * lookup operation. The table lookup operation is performed * within a specified rectangle. * *

The dst argument may be null, in which case a new * WritableRaster is created using the appropriate SampleModel. * *

The rectangle of interest may be null, in which case the * operation will be performed on the intersection of the source * and destination bounding rectangles. * * @param src A Raster containing the source pixel data. * @param dst The WritableRaster to be computed, or null. * If supplied, its data type and number of bands must * be suitable for the source and lookup table. * @param rect The rectangle within the tile to be computed. * If rect is null, the intersection of the source and * destination bounds will be used. Otherwise, it * will be clipped to the intersection of the source * and destination bounds. * @return A reference to the supplied WritableRaster, or to a * new WritableRaster if the supplied one was null. * * @throws IllegalArgumentException if the source is null. * @throws IllegalArgumentException if the source's SampleModel * is not of integral type. * @throws IllegalArgumentException if the destination's data type * or number of bands differ from those returned by * getDataType() and getDestNumBands(). */ public WritableRaster lookup(Raster src, WritableRaster dst, Rectangle rect) { // Validate source. if (src == null) { throw new IllegalArgumentException(JaiI18N.getString("LookupTableJAI1")); } SampleModel srcSampleModel = src.getSampleModel(); if (!isIntegralDataType(srcSampleModel)) { throw new IllegalArgumentException(JaiI18N.getString("LookupTableJAI2")); } // Validate rectangle. if (rect == null) { rect = src.getBounds(); } else { rect = rect.intersection(src.getBounds()); } if (dst != null) { rect = rect.intersection(dst.getBounds()); } // Validate destination. SampleModel dstSampleModel; if (dst == null) { // create dst according to table dstSampleModel = getDestSampleModel(srcSampleModel, rect.width, rect.height); dst = RasterFactory.createWritableRaster(dstSampleModel, new Point(rect.x, rect.y)); } else { dstSampleModel = dst.getSampleModel(); if (dstSampleModel.getTransferType() != getDataType() || dstSampleModel.getNumBands() != getDestNumBands(srcSampleModel.getNumBands())) { throw new IllegalArgumentException(JaiI18N.getString("LookupTableJAI3")); } } // Add bit support? int sTagID = RasterAccessor.findCompatibleTag(null, srcSampleModel); int dTagID = RasterAccessor.findCompatibleTag(null, dstSampleModel); RasterFormatTag sTag = new RasterFormatTag(srcSampleModel,sTagID); RasterFormatTag dTag = new RasterFormatTag(dstSampleModel,dTagID); RasterAccessor s = new RasterAccessor(src, rect, sTag, null); RasterAccessor d = new RasterAccessor(dst, rect, dTag, null); int srcNumBands = s.getNumBands(); int srcDataType = s.getDataType(); int tblNumBands = getNumBands(); int tblDataType = getDataType(); int dstWidth = d.getWidth(); int dstHeight = d.getHeight(); int dstNumBands = d.getNumBands(); int dstDataType = d.getDataType(); // Source information. int srcLineStride = s.getScanlineStride(); int srcPixelStride = s.getPixelStride(); int[] srcBandOffsets = s.getBandOffsets(); byte[][] bSrcData = s.getByteDataArrays(); short[][] sSrcData = s.getShortDataArrays(); int[][] iSrcData = s.getIntDataArrays(); if (srcNumBands < dstNumBands) { int offset0 = srcBandOffsets[0]; srcBandOffsets = new int[dstNumBands]; for (int i = 0; i < dstNumBands; i++) { srcBandOffsets[i] = offset0; } switch (srcDataType) { case DataBuffer.TYPE_BYTE: byte[] bData0 = bSrcData[0]; bSrcData = new byte[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { bSrcData[i] = bData0; } break; case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: short[] sData0 = sSrcData[0]; sSrcData = new short[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { sSrcData[i] = sData0; } break; case DataBuffer.TYPE_INT: int[] iData0 = iSrcData[0]; iSrcData = new int[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { iSrcData[i] = iData0; } break; } } // Table information. int[] tblOffsets = getOffsets(); byte[][] bTblData = getByteData(); short[][] sTblData = getShortData(); int[][] iTblData = getIntData(); float[][] fTblData = getFloatData(); double[][] dTblData = getDoubleData(); if (tblNumBands < dstNumBands) { int offset0 = tblOffsets[0]; tblOffsets = new int[dstNumBands]; for (int i = 0; i < dstNumBands; i++) { tblOffsets[i] = offset0; } switch (tblDataType) { case DataBuffer.TYPE_BYTE: byte[] bData0 = bTblData[0]; bTblData = new byte[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { bTblData[i] = bData0; } break; case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: short[] sData0 = sTblData[0]; sTblData = new short[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { sTblData[i] = sData0; } break; case DataBuffer.TYPE_INT: int[] iData0 = iTblData[0]; iTblData = new int[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { iTblData[i] = iData0; } break; case DataBuffer.TYPE_FLOAT: float[] fData0 = fTblData[0]; fTblData = new float[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { fTblData[i] = fData0; } break; case DataBuffer.TYPE_DOUBLE: double[] dData0 = dTblData[0]; dTblData = new double[dstNumBands][]; for (int i = 0; i < dstNumBands; i++) { dTblData[i] = dData0; } } } // Destination information. int dstLineStride = d.getScanlineStride(); int dstPixelStride = d.getPixelStride(); int[] dstBandOffsets = d.getBandOffsets(); byte[][] bDstData = d.getByteDataArrays(); short[][] sDstData = d.getShortDataArrays(); int[][] iDstData = d.getIntDataArrays(); float[][] fDstData = d.getFloatDataArrays(); double[][] dDstData = d.getDoubleDataArrays(); switch (dstDataType) { case DataBuffer.TYPE_BYTE: switch (srcDataType) { case DataBuffer.TYPE_BYTE: lookup(srcLineStride, srcPixelStride, srcBandOffsets, bSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, bDstData, tblOffsets, bTblData); break; case DataBuffer.TYPE_USHORT: lookupU(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, bDstData, tblOffsets, bTblData); break; case DataBuffer.TYPE_SHORT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, bDstData, tblOffsets, bTblData); break; case DataBuffer.TYPE_INT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, iSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, bDstData, tblOffsets, bTblData); break; } break; case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: switch (srcDataType) { case DataBuffer.TYPE_BYTE: lookup(srcLineStride, srcPixelStride, srcBandOffsets, bSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, sDstData, tblOffsets, sTblData); break; case DataBuffer.TYPE_USHORT: lookupU(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, sDstData, tblOffsets, sTblData); break; case DataBuffer.TYPE_SHORT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, sDstData, tblOffsets, sTblData); break; case DataBuffer.TYPE_INT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, iSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, sDstData, tblOffsets, sTblData); break; } break; case DataBuffer.TYPE_INT: switch (srcDataType) { case DataBuffer.TYPE_BYTE: lookup(srcLineStride, srcPixelStride, srcBandOffsets, bSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, iDstData, tblOffsets, iTblData); break; case DataBuffer.TYPE_USHORT: lookupU(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, iDstData, tblOffsets, iTblData); break; case DataBuffer.TYPE_SHORT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, iDstData, tblOffsets, iTblData); break; case DataBuffer.TYPE_INT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, iSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, iDstData, tblOffsets, iTblData); break; } break; case DataBuffer.TYPE_FLOAT: switch (srcDataType) { case DataBuffer.TYPE_BYTE: lookup(srcLineStride, srcPixelStride, srcBandOffsets, bSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, fDstData, tblOffsets, fTblData); break; case DataBuffer.TYPE_USHORT: lookupU(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, fDstData, tblOffsets, fTblData); break; case DataBuffer.TYPE_SHORT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, fDstData, tblOffsets, fTblData); break; case DataBuffer.TYPE_INT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, iSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, fDstData, tblOffsets, fTblData); break; } break; case DataBuffer.TYPE_DOUBLE: switch (srcDataType) { case DataBuffer.TYPE_BYTE: lookup(srcLineStride, srcPixelStride, srcBandOffsets, bSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, dDstData, tblOffsets, dTblData); break; case DataBuffer.TYPE_USHORT: lookupU(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, dDstData, tblOffsets, dTblData); break; case DataBuffer.TYPE_SHORT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, sSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, dDstData, tblOffsets, dTblData); break; case DataBuffer.TYPE_INT: lookup(srcLineStride, srcPixelStride, srcBandOffsets, iSrcData, dstWidth, dstHeight, dstNumBands, dstLineStride, dstPixelStride, dstBandOffsets, dDstData, tblOffsets, dTblData); break; } break; } d.copyDataToRaster(); return dst; } // byte to byte private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData) { for (int b = 0; b < bands; b++) { byte[] s = srcData[b]; byte[] d = dstData[b]; byte[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // ushort to byte private void lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; byte[] d = dstData[b]; byte[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFFFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // short to byte private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; byte[] d = dstData[b]; byte[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // int to byte private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData) { for (int b = 0; b < bands; b++) { int[] s = srcData[b]; byte[] d = dstData[b]; byte[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // byte to short or ushort private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData) { for (int b = 0; b < bands; b++) { byte[] s = srcData[b]; short[] d = dstData[b]; short[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // ushort to short or ushort private void lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; short[] d = dstData[b]; short[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFFFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // short to short or ushort private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; short[] d = dstData[b]; short[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // int to short or ushort private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData) { for (int b = 0; b < bands; b++) { int[] s = srcData[b]; short[] d = dstData[b]; short[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // byte to int private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData) { if (tblData == null) { for (int b = 0; b < bands; b++) { byte[] s = srcData[b]; int[] d = dstData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = data.getElem(b, s[srcPixelOffset]&0xFF); srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } else { for (int b = 0; b < bands; b++) { byte[] s = srcData[b]; int[] d = dstData[b]; int[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } } // ushort to int private void lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData) { if (tblData == null) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; int[] d = dstData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = data.getElem(b, s[srcPixelOffset]&0xFFFF); srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } else { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; int[] d = dstData[b]; int[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFFFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } } // short to int private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData) { if (tblData == null) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; int[] d = dstData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = data.getElem(b, s[srcPixelOffset]); srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } else { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; int[] d = dstData[b]; int[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } } // int to int private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData) { if (tblData == null) { for (int b = 0; b < bands; b++) { int[] s = srcData[b]; int[] d = dstData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = data.getElem(b, s[srcPixelOffset]); srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } else { for (int b = 0; b < bands; b++) { int[] s = srcData[b]; int[] d = dstData[b]; int[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } } // byte to float private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData) { for (int b = 0; b < bands; b++) { byte[] s = srcData[b]; float[] d = dstData[b]; float[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // ushort to float private void lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; float[] d = dstData[b]; float[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFFFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // short to float private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; float[] d = dstData[b]; float[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // int to float private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData) { for (int b = 0; b < bands; b++) { int[] s = srcData[b]; float[] d = dstData[b]; float[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // byte to double private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData) { for (int b = 0; b < bands; b++) { byte[] s = srcData[b]; double[] d = dstData[b]; double[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // ushort to double private void lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; double[] d = dstData[b]; double[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFFFF) - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // short to double private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData) { for (int b = 0; b < bands; b++) { short[] s = srcData[b]; double[] d = dstData[b]; double[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } // int to double private void lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData) { for (int b = 0; b < bands; b++) { int[] s = srcData[b]; double[] d = dstData[b]; double[] t = tblData[b]; int srcLineOffset = srcBandOffsets[b]; int dstLineOffset = dstBandOffsets[b]; int tblOffset = tblOffsets[b]; for (int h = 0; h < height; h++) { int srcPixelOffset = srcLineOffset; int dstPixelOffset = dstLineOffset; srcLineOffset += srcLineStride; dstLineOffset += dstLineStride; for (int w = 0; w < width; w++) { d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset]; srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } } } } /** * Determine which entry in the LookupTableJAI is closest * in Euclidean distance to the argument pixel. * * @param pixel The pixel the closest entry to which is to be found. * * @return the index of the closest entry. If the data array of the * lookup table is in the format data[numBands][numEntries], then the * value v for band b of the closest entry is *

     *     v = data[b][index - lookup.getOffset()]
     * 
* where index is the returned value of this method. * * @throws IllegalArgumentException if pixel is null. */ public int findNearestEntry(float[] pixel) { if ( pixel == null ) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } int dataType = data.getDataType(); int numBands = getNumBands(); int numEntries = getNumEntries(); int index = -1; if(dataType == DataBuffer.TYPE_BYTE) { byte buffer[][] = getByteData(); // Find the distance to the first entry and set result to 0. float minDistance = 0.0F; index = 0; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - (float)(buffer[b][0] & 0xff); minDistance += delta*delta; } // Find the distance to each entry and set the result to // the index which is closest to the argument. for(int i = 1; i < numEntries; i++) { float distance = 0.0F; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - (float)(buffer[b][i] & 0xff); distance += delta*delta; } if(distance < minDistance) { minDistance = distance; index = i; } } } else if(dataType == DataBuffer.TYPE_SHORT) { short buffer[][] = getShortData(); // Find the distance to the first entry and set result to 0. float minDistance = 0.0F; index = 0; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - buffer[b][0]; minDistance += delta*delta; } // Find the distance to each entry and set the result to // the index which is closest to the argument. for(int i = 1; i < numEntries; i++) { float distance = 0.0F; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - buffer[b][i]; distance += delta*delta; } if(distance < minDistance) { minDistance = distance; index = i; } } } else if(dataType == DataBuffer.TYPE_USHORT) { short buffer[][] = getShortData(); // Find the distance to the first entry and set result to 0. float minDistance = 0.0F; index = 0; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - (float)(buffer[b][0] & 0xffff); minDistance += delta*delta; } // Find the distance to each entry and set the result to // the index which is closest to the argument. for(int i = 1; i < numEntries; i++) { float distance = 0.0F; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - (float)(buffer[b][i] & 0xffff); distance += delta*delta; } if(distance < minDistance) { minDistance = distance; index = i; } } } else if(dataType == DataBuffer.TYPE_INT) { int buffer[][] = getIntData(); // Find the distance to the first entry and set result to 0. float minDistance = 0.0F; index = 0; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - buffer[b][0]; minDistance += delta*delta; } // Find the distance to each entry and set the result to // the index which is closest to the argument. for(int i = 1; i < numEntries; i++) { float distance = 0.0F; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - buffer[b][i]; distance += delta*delta; } if(distance < minDistance) { minDistance = distance; index = i; } } } else if(dataType == DataBuffer.TYPE_FLOAT) { float buffer[][] = getFloatData(); // Find the distance to the first entry and set result to 0. float minDistance = 0.0F; index = 0; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - buffer[b][0]; minDistance += delta*delta; } // Find the distance to each entry and set the result to // the index which is closest to the argument. for(int i = 1; i < numEntries; i++) { float distance = 0.0F; for(int b = 0; b < numBands; b++) { float delta = pixel[b] - buffer[b][i]; distance += delta*delta; } if(distance < minDistance) { minDistance = distance; index = i; } } } else if(dataType == DataBuffer.TYPE_DOUBLE) { double buffer[][] = getDoubleData(); // Find the distance to the first entry and set result to 0. double minDistance = 0.0F; index = 0; for(int b = 0; b < numBands; b++) { double delta = pixel[b] - buffer[b][0]; minDistance += delta*delta; } // Find the distance to each entry and set the result to // the index which is closest to the argument. for(int i = 1; i < numEntries; i++) { double distance = 0.0F; for(int b = 0; b < numBands; b++) { double delta = pixel[b] - buffer[b][i]; distance += delta*delta; } if(distance < minDistance) { minDistance = distance; index = i; } } } else { // This can't happen since we control the type of data throw new RuntimeException(JaiI18N.getString("LookupTableJAI0")); } // Return the index of the closest color plus the offset of the // default band or -1 on error. return index == -1 ? index : index + getOffset(); } /** * Serialize the LookupTableJAI. * * @param out The ObjectOutputStream. */ private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject(SerializerFactory.getState(data)); } /** * Deserialize the LookupTableJAI. * * @param in The ObjectInputStream. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); Object object = in.readObject(); SerializableState ss = (SerializableState)object; data = (DataBuffer)ss.getObject(); } private void initOffsets(int nbands, int offset) { tableOffsets = new int[nbands]; for (int i=0; i