/* JAI-Ext - OpenSource Java Advanced Image Extensions Library * http://www.geo-solutions.it/ * Copyright 2014 GeoSolutions * Licensed 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. */ package it.geosolutions.jaiext.binarize; import static org.junit.Assert.assertEquals; import it.geosolutions.jaiext.range.Range; import it.geosolutions.jaiext.range.RangeFactory; import it.geosolutions.jaiext.testclasses.TestBase; import java.awt.Rectangle; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.RenderedImage; import javax.media.jai.ROI; import javax.media.jai.ROIShape; import javax.media.jai.RenderedOp; import org.junit.BeforeClass; import org.junit.Test; /** * Unit test for testing Binarize operation with ROI and No Data. */ public class BinarizeTest extends TestBase { /** Array of inut test data */ private static RenderedImage[] testImages; /** NoData Range for Byte */ private static Range noDataByte; /** NoData Range for Ushort */ private static Range noDataUShort; /** NoData Range for Short */ private static Range noDataShort; /** NoData Range for Int */ private static Range noDataInt; /** NoData Range for Float */ private static Range noDataFloat; /** NoData Range for Double */ private static Range noDataDouble; /** ROI object used for tests */ private static ROI roiObject; /** Threshold used for binarization */ private static double[] thresholds; @BeforeClass public static void initialSetup() { byte noDataB = 50; short noDataS = 50; int noDataI = 50; float noDataF = 50; double noDataD = 50; // thresholds thresholds = new double[6]; thresholds[0] = 63; thresholds[1] = Short.MAX_VALUE / 4; thresholds[2] = -49; thresholds[3] = 105; thresholds[4] = (255 / 2) * 5; thresholds[5] = (255 / 7) * 13; // Image creation testImages = new RenderedImage[6]; IMAGE_FILLER = true; testImages[DataBuffer.TYPE_BYTE] = createTestImage(DataBuffer.TYPE_BYTE, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataB, false, 1, (byte) (thresholds[DataBuffer.TYPE_BYTE] + 1)); testImages[DataBuffer.TYPE_USHORT] = createTestImage(DataBuffer.TYPE_USHORT, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataS, false, 1, (short) (thresholds[DataBuffer.TYPE_USHORT] + 1)); testImages[DataBuffer.TYPE_SHORT] = createTestImage(DataBuffer.TYPE_SHORT, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataS, false, 1, (short) (thresholds[DataBuffer.TYPE_SHORT] + 1)); testImages[DataBuffer.TYPE_INT] = createTestImage(DataBuffer.TYPE_INT, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataI, false, 1, (int) (thresholds[DataBuffer.TYPE_INT] + 1)); testImages[DataBuffer.TYPE_FLOAT] = createTestImage(DataBuffer.TYPE_FLOAT, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataF, false, 1, (float) (thresholds[DataBuffer.TYPE_FLOAT] + 1)); testImages[DataBuffer.TYPE_DOUBLE] = createTestImage(DataBuffer.TYPE_DOUBLE, DEFAULT_WIDTH, DEFAULT_HEIGHT, noDataD, false, 1, thresholds[DataBuffer.TYPE_DOUBLE] + 1); IMAGE_FILLER = false; // No Data Ranges boolean minIncluded = true; boolean maxIncluded = true; noDataByte = RangeFactory.create(noDataB, minIncluded, noDataB, maxIncluded); noDataUShort = RangeFactory.createU(noDataS, minIncluded, noDataS, maxIncluded); noDataShort = RangeFactory.create(noDataS, minIncluded, noDataS, maxIncluded); noDataInt = RangeFactory.create(noDataI, minIncluded, noDataI, maxIncluded); noDataFloat = RangeFactory.create(noDataF, minIncluded, noDataF, maxIncluded, true); noDataDouble = RangeFactory.create(noDataD, minIncluded, noDataD, maxIncluded, true); // ROI creation Rectangle roiBounds = new Rectangle(5, 5, DEFAULT_WIDTH / 4, DEFAULT_HEIGHT / 4); roiObject = new ROIShape(roiBounds); } @Test public void testValidData() { boolean roiUsed = false; boolean noDataUsed = false; for (int i = 0; i < 6; i++) { testType(testImages[i], noDataUsed, roiUsed); } } @Test public void testRoi() { boolean roiUsed = true; boolean noDataUsed = false; for (int i = 0; i < 6; i++) { testType(testImages[i], noDataUsed, roiUsed); } } @Test public void testNoData() { boolean roiUsed = false; boolean noDataUsed = true; for (int i = 0; i < 6; i++) { testType(testImages[i], noDataUsed, roiUsed); } } @Test public void testRoiNoData() { boolean roiUsed = true; boolean noDataUsed = true; for (int i = 0; i < 6; i++) { testType(testImages[i], noDataUsed, roiUsed); } } private void testType(RenderedImage src, boolean nodataUsed, boolean roiUsed) { // Optional No Data Range used Range noData; // Source image data type int dataType = src.getSampleModel().getDataType(); // If no Data are present, the No Data Range associated is used if (nodataUsed) { switch (dataType) { case DataBuffer.TYPE_BYTE: noData = noDataByte; break; case DataBuffer.TYPE_USHORT: noData = noDataUShort; break; case DataBuffer.TYPE_SHORT: noData = noDataShort; break; case DataBuffer.TYPE_INT: noData = noDataInt; break; case DataBuffer.TYPE_FLOAT: noData = noDataFloat; break; case DataBuffer.TYPE_DOUBLE: noData = noDataDouble; break; default: throw new IllegalArgumentException("Wrong data type"); } } else { noData = null; } // Setting threshold double threshold = thresholds[dataType]; ROI roi; if (roiUsed) { roi = roiObject; } else { roi = null; } // binarized RenderedOp binarized = BinarizeDescriptor.create(src, threshold, roi, noData, null); int tileWidth = binarized.getTileWidth(); int tileHeight = binarized.getTileHeight(); int minTileX = binarized.getMinTileX(); int minTileY = binarized.getMinTileY(); int numXTiles = binarized.getNumXTiles(); int numYTiles = binarized.getNumYTiles(); int maxTileX = minTileX + numXTiles; int maxTileY = minTileY + numYTiles; // Ensure same size assertEquals(binarized.getWidth(), src.getWidth()); assertEquals(binarized.getHeight(), src.getHeight()); assertEquals(binarized.getMinX(), src.getMinX()); assertEquals(binarized.getMinY(), src.getMinY()); assertEquals(minTileX, src.getMinTileX()); assertEquals(minTileY, src.getMinTileY()); assertEquals(numXTiles, src.getNumXTiles()); assertEquals(numYTiles, src.getNumYTiles()); assertEquals(tileWidth, src.getTileWidth()); assertEquals(tileHeight, src.getTileHeight()); // Check if the binarization is correct for (int tileX = minTileX; tileX < maxTileX; tileX++) { for (int tileY = minTileY; tileY < maxTileY; tileY++) { Raster tile = binarized.getTile(tileX, tileY); Raster srcTile = src.getTile(tileX, tileY); int minX = tile.getMinX(); int minY = tile.getMinY(); int maxX = minX + tileWidth - 1; int maxY = minY + tileHeight - 1; for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { double sample = srcTile.getSampleDouble(x, y, 0); int result = tile.getSample(x, y, 0); boolean over = result > 0; // Check if the data can be accepted boolean isValidData = (!roiUsed || (roiUsed && roiObject.contains(x, y))) && (!nodataUsed || (nodataUsed && !noDataDouble.contains(sample))); if (isValidData) { assertEquals(over, sample >= threshold); } else { assertEquals(over, false); } } } } } // Disposal of the output image binarized.dispose(); } }