/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
package org.geotools.arcsde.raster.info;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_16BIT_S;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_16BIT_U;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_1BIT;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_REAL;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_S;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_32BIT_U;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_4BIT;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_64BIT_REAL;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_8BIT_S;
import static org.geotools.arcsde.raster.info.RasterCellType.TYPE_8BIT_U;
import static org.geotools.arcsde.raster.info.RasterUtils.determineNoDataValue;
import static org.geotools.arcsde.raster.info.RasterUtils.determineTargetCellType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.awt.Transparency;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferUShort;
import java.awt.image.IndexColorModel;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class RasterUtilsTest {
@Test
public void testSdeColormapToJavaColorModel() {
testSdeColormapToJavaColorModel(8, 256, 3, DataBuffer.TYPE_BYTE);
testSdeColormapToJavaColorModel(8, 10, 3, DataBuffer.TYPE_BYTE);
testSdeColormapToJavaColorModel(8, 256, 4, DataBuffer.TYPE_BYTE);
testSdeColormapToJavaColorModel(8, 10, 4, DataBuffer.TYPE_BYTE);
testSdeColormapToJavaColorModel(16, 65536, 3, DataBuffer.TYPE_USHORT);
testSdeColormapToJavaColorModel(16, 10, 3, DataBuffer.TYPE_USHORT);
testSdeColormapToJavaColorModel(16, 65536, 4, DataBuffer.TYPE_USHORT);
testSdeColormapToJavaColorModel(16, 10, 4, DataBuffer.TYPE_USHORT);
// what about a 16bit sample model with a data buffer byte with more than 256 entries?
testSdeColormapToJavaColorModel(16, 530, 3, DataBuffer.TYPE_BYTE);
}
private void testSdeColormapToJavaColorModel(final int bitsPerSample, final int size,
final int numBanks, final int transferType) {
DataBuffer colorMapData;
IndexColorModel colorModel;
colorMapData = newColorMap(size, numBanks, transferType);
colorModel = RasterUtils.sdeColorMapToJavaColorModel(colorMapData, bitsPerSample);
assertColorModel(colorMapData, colorModel, bitsPerSample);
}
private void assertColorModel(DataBuffer expected, IndexColorModel actual, int bitsPerSample) {
final int size = expected.getSize();
final int numBanks = expected.getNumBanks();
// final int dataType = expected.getDataType();
assertEquals(bitsPerSample, actual.getPixelSize());
assertEquals(bitsPerSample == 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT, actual
.getTransferType());
assertEquals(numBanks, actual.getNumComponents());
if (numBanks == 3) {
assertEquals(-1, actual.getTransparentPixel());
assertFalse(actual.hasAlpha());
assertEquals(Transparency.OPAQUE, actual.getTransparency());
} else if (numBanks == 4) {
// transparent pixel is looked up by IndexColorModel
assertTrue(actual.getTransparentPixel() > -1);
assertTrue(actual.hasAlpha());
assertEquals(Transparency.TRANSLUCENT, actual.getTransparency());
}
assertEquals(size, actual.getMapSize());
for (int elem = 0; elem < size; elem++) {
for (int bank = 0; bank < numBanks; bank++) {
int actualValue = 0;
switch (bank) {
case 0:
actualValue = actual.getRed(elem);
break;
case 1:
actualValue = actual.getGreen(elem);
break;
case 2:
actualValue = actual.getBlue(elem);
break;
case 3:
actualValue = actual.getAlpha(elem);
break;
}
assertEquals("at index " + elem + ", bank " + bank, expected.getElem(bank, elem),
actualValue);
}
}
}
private DataBuffer newColorMap(int size, int numBanks, int transferType) {
DataBuffer colorMapData;
switch (transferType) {
case DataBuffer.TYPE_BYTE:
colorMapData = new DataBufferByte(size, numBanks);
break;
case DataBuffer.TYPE_USHORT:
colorMapData = new DataBufferUShort(size, numBanks);
break;
default:
throw new IllegalArgumentException();
}
for (int elem = 0; elem < size; elem++) {
for (int bank = 0; bank < numBanks; bank++) {
// cast to byte
int value = elem & 0xFF;
colorMapData.setElem(bank, elem, value);
}
}
return colorMapData;
}
@Test
public void testDetermineTargetCellType() {
assertDetermineTargetCellType(TYPE_1BIT, TYPE_1BIT, 0);
assertDetermineTargetCellType(TYPE_1BIT, TYPE_8BIT_U, 2);
assertDetermineTargetCellType(TYPE_1BIT, TYPE_8BIT_U, 0, 1, 2);
assertDetermineTargetCellType(TYPE_4BIT, TYPE_4BIT, 0);
assertDetermineTargetCellType(TYPE_4BIT, TYPE_4BIT, 15);
assertDetermineTargetCellType(TYPE_4BIT, TYPE_8BIT_U, 16);
assertDetermineTargetCellType(TYPE_8BIT_U, TYPE_8BIT_U, 0);
assertDetermineTargetCellType(TYPE_8BIT_U, TYPE_8BIT_U, 255);
assertDetermineTargetCellType(TYPE_8BIT_U, TYPE_16BIT_U, 256);
assertDetermineTargetCellType(TYPE_8BIT_U, TYPE_16BIT_U, 0, 255, 256);
assertDetermineTargetCellType(TYPE_8BIT_S, TYPE_8BIT_S, Byte.MIN_VALUE);
assertDetermineTargetCellType(TYPE_8BIT_S, TYPE_8BIT_S, Byte.MAX_VALUE);
assertDetermineTargetCellType(TYPE_8BIT_S, TYPE_16BIT_S, Byte.MAX_VALUE + 1);
assertDetermineTargetCellType(TYPE_8BIT_S, TYPE_16BIT_S, 0, Byte.MIN_VALUE - 1,
Byte.MAX_VALUE);
assertDetermineTargetCellType(TYPE_16BIT_S, TYPE_16BIT_S, Short.MIN_VALUE);
assertDetermineTargetCellType(TYPE_16BIT_S, TYPE_16BIT_S, Short.MAX_VALUE);
assertDetermineTargetCellType(TYPE_16BIT_S, TYPE_32BIT_S, Short.MAX_VALUE + 1);
assertDetermineTargetCellType(TYPE_16BIT_S, TYPE_32BIT_S, 0, Short.MIN_VALUE - 1,
Short.MAX_VALUE);
assertDetermineTargetCellType(TYPE_16BIT_U, TYPE_16BIT_U, 0);
assertDetermineTargetCellType(TYPE_16BIT_U, TYPE_16BIT_U, 65535);
assertDetermineTargetCellType(TYPE_16BIT_U, TYPE_32BIT_U, 65536);
assertDetermineTargetCellType(TYPE_16BIT_U, TYPE_32BIT_U, 0, 65535, 65536);
assertDetermineTargetCellType(TYPE_32BIT_U, TYPE_32BIT_U, 0);
long max32bitU = TYPE_32BIT_U.getSampleValueRange().castTo(Long.class).getMaxValue();
assertDetermineTargetCellType(TYPE_32BIT_U, TYPE_32BIT_U, max32bitU);
assertDetermineTargetCellType(TYPE_32BIT_U, TYPE_64BIT_REAL, max32bitU + 1);
assertDetermineTargetCellType(TYPE_32BIT_U, TYPE_64BIT_REAL, 0, max32bitU, max32bitU + 1);
assertDetermineTargetCellType(TYPE_32BIT_S, TYPE_32BIT_S, Integer.MIN_VALUE);
assertDetermineTargetCellType(TYPE_32BIT_S, TYPE_32BIT_S, Integer.MAX_VALUE);
assertDetermineTargetCellType(TYPE_32BIT_S, TYPE_64BIT_REAL, (long) Integer.MIN_VALUE - 1L);
assertDetermineTargetCellType(TYPE_32BIT_S, TYPE_64BIT_REAL, Integer.MIN_VALUE,
(long) Integer.MAX_VALUE + 1L, (long) Integer.MIN_VALUE - 1L);
{
try {
assertDetermineTargetCellType(TYPE_32BIT_REAL, TYPE_32BIT_REAL, Float.MIN_VALUE);
fail("Expected IAE for 332BIT_REAL with no-data other than Float.NaN");
} catch (IllegalArgumentException e) {
assertTrue(true);
}
try {
assertDetermineTargetCellType(TYPE_32BIT_REAL, TYPE_32BIT_REAL, Float.MAX_VALUE);
fail("Expected IAE for 332BIT_REAL with no-data other than Float.NaN");
} catch (IllegalArgumentException e) {
assertTrue(true);
}
assertDetermineTargetCellType(TYPE_32BIT_REAL, TYPE_32BIT_REAL, Float.NaN);
}
{
try {
assertDetermineTargetCellType(TYPE_64BIT_REAL, TYPE_64BIT_REAL, Double.MIN_VALUE);
fail("Expected IAE for TYPE_64BIT_REAL with no-data other than Float.NaN");
} catch (IllegalArgumentException e) {
assertTrue(true);
}
try {
assertDetermineTargetCellType(TYPE_64BIT_REAL, TYPE_64BIT_REAL, Double.MAX_VALUE);
fail("Expected IAE for TYPE_64BIT_REAL with no-data other than Float.NaN");
} catch (IllegalArgumentException e) {
assertTrue(true);
}
assertDetermineTargetCellType(TYPE_64BIT_REAL, TYPE_64BIT_REAL, Double.NaN);
}
}
/**
*
* @param nativeCellType
* the native cell type
* @param expectedTargetCellType
* the expected cell type
* @param noData
* list of no-data values, one per band in the raster
*/
private void assertDetermineTargetCellType(RasterCellType nativeCellType,
RasterCellType expectedTargetCellType, Number... noData) {
List<Number> noDataValues = new ArrayList<Number>();
for (Number bandNNoData : noData) {
noDataValues.add(bandNNoData);
}
RasterCellType targetCellType = determineTargetCellType(nativeCellType, noDataValues);
assertEquals(expectedTargetCellType, targetCellType);
}
@Test
public void testDeterminaNoDataValueNonColorMapped() {
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_1BIT, 2, null);
assertDetermineNoDataValue(1, 0, 1, TYPE_1BIT, 2, null);
assertDetermineNoDataValue(1, 0, 0, TYPE_1BIT, 2,
"1BIT no-data should have been set to 2, "
+ "regardless of the dataset not containing set pixels");
assertDetermineNoDataValue(1, 0, 15, TYPE_4BIT, 16, null);
assertDetermineNoDataValue(1, 0, 3, TYPE_4BIT, 16,
"4BIT no-data should have been set to 16, "
+ "regardless of the dataset used values");
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_4BIT, 16, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_8BIT_U, 256, null);
assertDetermineNoDataValue(1, 0, 255, TYPE_8BIT_U, 256, null);
assertDetermineNoDataValue(1, 0, 254, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(1, 1, 254, TYPE_8BIT_U, 0, null);
// 8bit unsigned rasters with 3 or 4 bands have a hardcoded nodata value of 255 so they
// account for white/transparent
assertDetermineNoDataValue(3, Double.NaN, Double.NaN, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(3, 0, 255, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(3, 0, 254, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(3, 1, 254, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(4, Double.NaN, Double.NaN, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(4, 0, 255, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(4, 0, 254, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(4, 1, 254, TYPE_8BIT_U, 255, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_8BIT_S, -129, null);
assertDetermineNoDataValue(1, -128, 127, TYPE_8BIT_S, Byte.MIN_VALUE - 1, null);
assertDetermineNoDataValue(1, -128, 126, TYPE_8BIT_S, 127, null);
assertDetermineNoDataValue(1, -127, 127, TYPE_8BIT_S, -128, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_16BIT_U, 65536, null);
assertDetermineNoDataValue(1, 0, 65535, TYPE_16BIT_U, 65536, null);
assertDetermineNoDataValue(1, 1, 65535, TYPE_16BIT_U, 0, null);
assertDetermineNoDataValue(1, 0, 65534, TYPE_16BIT_U, 65535, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_16BIT_S, Short.MIN_VALUE - 1,
null);
assertDetermineNoDataValue(1, Short.MIN_VALUE, Short.MAX_VALUE, TYPE_16BIT_S,
Short.MIN_VALUE - 1, null);
assertDetermineNoDataValue(1, Short.MIN_VALUE, Short.MAX_VALUE - 1, TYPE_16BIT_S,
Short.MAX_VALUE, null);
assertDetermineNoDataValue(1, Short.MIN_VALUE + 1, Short.MAX_VALUE, TYPE_16BIT_S,
Short.MIN_VALUE, null);
double max32bitU = TYPE_32BIT_U.getSampleValueRange().getMaximum();
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_32BIT_U, max32bitU + 1, null);
assertDetermineNoDataValue(1, 0, max32bitU, TYPE_32BIT_U, max32bitU + 1, null);
assertDetermineNoDataValue(1, 1, max32bitU, TYPE_32BIT_U, 0, null);
assertDetermineNoDataValue(1, 0, max32bitU - 1, TYPE_32BIT_U, max32bitU, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_32BIT_S, Integer.MIN_VALUE - 1L,
null);
assertDetermineNoDataValue(1, Integer.MIN_VALUE, Integer.MAX_VALUE, TYPE_32BIT_S,
(long) Integer.MIN_VALUE - 1, null);
assertDetermineNoDataValue(1, 1, Integer.MAX_VALUE, TYPE_32BIT_S, 0, null);
assertDetermineNoDataValue(1, Integer.MIN_VALUE, Integer.MAX_VALUE - 1L, TYPE_32BIT_S,
Integer.MAX_VALUE, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_32BIT_REAL, Float.NaN, null);
assertDetermineNoDataValue(1, Float.MIN_VALUE, Float.MAX_VALUE, TYPE_32BIT_REAL, Float.NaN,
null);
assertDetermineNoDataValue(1, Float.MIN_VALUE + 1, Float.MAX_VALUE, TYPE_32BIT_REAL,
Float.NaN, null);
assertDetermineNoDataValue(1, Float.MIN_VALUE, Float.MAX_VALUE - 1L, TYPE_32BIT_REAL,
Float.NaN, null);
assertDetermineNoDataValue(1, Double.NaN, Double.NaN, TYPE_64BIT_REAL, Double.NaN, null);
assertDetermineNoDataValue(1, Double.MIN_VALUE, Double.MAX_VALUE, TYPE_64BIT_REAL,
Double.NaN, null);
assertDetermineNoDataValue(1, Double.MIN_VALUE + 1, Double.MAX_VALUE, TYPE_64BIT_REAL,
Double.NaN, null);
assertDetermineNoDataValue(1, Double.MIN_VALUE, Double.MAX_VALUE - 1L, TYPE_64BIT_REAL,
Double.NaN, null);
}
private void assertDetermineNoDataValue(final int numBands, final double statsMin,
final double statsMax, final RasterCellType nativeCellType,
final Number expectedNoDataValue, final String failureMsg) {
Number noDataValue = determineNoDataValue(numBands, statsMin, statsMax, nativeCellType);
if (failureMsg == null) {
assertEquals(expectedNoDataValue.doubleValue(), noDataValue.doubleValue(), 0);
} else {
assertEquals(failureMsg, expectedNoDataValue.doubleValue(), noDataValue.doubleValue(),
0);
}
}
}