@Test
public void extractPolygonsFromViewshedRaster() throws Exception {

    final double ROUND_OFF_TOLERANCE = 1.0e-4D;
    URL url = getClass().getResource("viewshed.tif");
    BufferedImage img = ImageIO.read(url);
    Rectangle bounds = new Rectangle(img.getMinX(), img.getMinY(), img.getWidth(), img.getHeight());
    ReferencedEnvelope env = new ReferencedEnvelope(bounds, null);
    GridCoverage2D cov = covFactory.create("coverage", img, env);
    final int OUTSIDE = -1;
    List<Number> noDataValues = new ArrayList<Number>();
    noDataValues.add(OUTSIDE);
    SimpleFeatureCollection fc = process.execute(
            cov, 0, Boolean.TRUE, null, noDataValues, null, null);
    // validate geometries and sum areas
    SimpleFeatureIterator iter = fc.features();
    Map<Integer, Double> areas = new HashMap<Integer, Double>();
    try {
        while (iter.hasNext()) {
            SimpleFeature feature = iter.next();
            Geometry geom = (Geometry) feature.getDefaultGeometry();
            assertTrue(geom.isValid());
            int value = ((Number) feature.getAttribute("value")).intValue();
            if (value != OUTSIDE) {
                Double sum = areas.get(value);
                if (sum == null) {
                    sum = 0.0d;
                }
                sum += geom.getArea();
                areas.put(value, sum);
            }
        }
    } finally {
        iter.close();
    }
    
    // compare summed areas to image data
    Map<Integer, Double> imgAreas = new HashMap<Integer, Double>();
    Raster tile = img.getTile(0, 0);
    for (int y = img.getMinY(), ny = 0; ny < img.getHeight(); y++, ny++) {
        for (int x = img.getMinX(), nx = 0; nx < img.getWidth(); x++, nx++) {
            double gridvalue = tile.getSampleDouble(x, y, 0);
            if (Math.abs(gridvalue - OUTSIDE) < TOL) {
                Double sum = areas.get((int)gridvalue);
                if (sum == null) {
                    sum = 1.0D;
                } else {
                    sum += 1.0D;
                }
                areas.put((int)gridvalue, sum);
            }
        }
    }
    for (Integer i : imgAreas.keySet()) {
        double ratio = areas.get(i) / imgAreas.get(i);
        assertTrue(Math.abs(1.0D - ratio) < ROUND_OFF_TOLERANCE);
    }
}