/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2014, Geomatys * * 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.geotoolkit.metadata; import org.geotoolkit.image.internal.SampleType; import java.io.Serializable; import java.util.*; import org.apache.sis.util.ArgumentChecks; import org.opengis.coverage.Coverage; import org.opengis.metadata.content.AttributeGroup; import org.opengis.metadata.content.CoverageDescription; import org.opengis.metadata.content.RangeDimension; import org.opengis.metadata.content.SampleDimension; /** * Image statistic from an image : * Get min, max, datatype and histogram array by bands * * @author bgarcia * @author Quentin Boileau (Geomatys) */ public class ImageStatistics implements Serializable{ /** * Image bands */ private Band[] bands; public ImageStatistics(int nbBands) { this(nbBands, null); } /** * constructor with a band numbers to create bands * @param nbBands image band numbers */ public ImageStatistics(int nbBands, SampleType dataType) { bands = new Band[nbBands]; for (int i = 0; i < bands.length; i++) { bands[i] = new Band(i, dataType); } } public Band[] getBands() { return bands; } public void setBands(final Band[] bands) { this.bands = bands; } public Band getBand(int bandNumber) { return bands[bandNumber]; } @Override public String toString() { return "StatisticContainer{\n" + "bands=" + Arrays.toString(bands) + "}"; } /** * Band Inner class */ public static class Band implements Serializable { private final int bandIndex; private String name = null; private SampleType dataType = null; private Double min = null; private Double max = null; private Double mean = null; private Double std = null; /** * no data values */ private double[] noData = null; private long[] histogram = null; public Band(int bandIndex) { this(bandIndex, null); } public Band(int bandIndex, SampleType dataType) { this.bandIndex = bandIndex; this.dataType = dataType; } public int getBandIndex() { return bandIndex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public SampleType getDataType() { return dataType; } public void setDataType(SampleType dataType) { this.dataType = dataType; } public void setHistogram(long[] histogram) { this.histogram = histogram; } public long[] getHistogram() { return histogram; } public Map<Double, Long> getDistribution() { int nbBins = histogram.length; final Map<Double, Long> map = new HashMap(nbBins); double binSize = (max - min) / ((double)nbBins-1.0); for (int j = 0; j <nbBins; j++) { double value = min+binSize*j; long occurs = histogram[j]; map.put(value, occurs); } return new TreeMap<>(map); } public long[] tightenHistogram(int distributionSize) { int fullSize = histogram.length; if (fullSize <= distributionSize) { return histogram; } final long[] distArr = new long[distributionSize]; double steps = (double)fullSize / (double)distributionSize; //int middleStep = (int) Math.ceil(steps / 2f); double pos = 0.0; for (int i = 0; i < distributionSize; i++) { long distSum = 0; double endStep = pos + steps; int start = (int) pos; int end = (int) endStep; for (int j = start; j < end; j++) { distSum += histogram[j]; } pos = endStep; distArr[i] = distSum; } return distArr; } public double[] getNoData() { return noData; } public void setNoData(final double[] noData) { this.noData = noData; } /** * Get image min value * @return data which have min elements on image */ public Double getMin() { return min; } public void setMin(Double min) { this.min = min; } /** * Get image max value * @return data which have max elements on image */ public Double getMax() { return max; } public void setMax(Double max) { this.max = max; } public Double getMean() { return mean; } public void setMean(Double mean) { this.mean = mean; } public Double getStd() { return std; } public void setStd(Double std) { this.std = std; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Band ").append(bandIndex).append(" {") .append(" min=").append(min) .append(", max=").append(max) .append(", mean=").append(mean) .append(", std=").append(std) .append(", dataType=").append(dataType.name()) .append(", histogram=") .append(Arrays.toString(histogram)) .append(", noData=").append(Arrays.toString(noData)) .append("}\n"); return sb.toString(); } } /** * Create {@link ImageStatistics} from {@link CoverageDescription}.<br/> * Moreover travel all existing {@link SampleDimension} from {@link CoverageDescription} * to define appropriate statistics. * * @param covdesc Description of the studied {@link Coverage}. * @return {@link ImageStatistics} or {@code null} if it is impossible to define * statistic for each bands, or {@link CoverageDescription#getAttributeGroups() } is {@code null} or empty, * or also if internaly {@link AttributeGroup#getAttributes()} is {@code null} or empty. */ public static ImageStatistics transform(final CoverageDescription covdesc) { ArgumentChecks.ensureNonNull("CoverageDescription", covdesc); final Collection<? extends AttributeGroup> attributeGroups = covdesc.getAttributeGroups(); if (attributeGroups == null || attributeGroups.isEmpty()) return null; final List<Band> bands = new ArrayList<>(); //search for band statistics for (AttributeGroup attg : attributeGroups) { final Collection<? extends RangeDimension> attributes = attg.getAttributes(); if (attributes == null || attributes.isEmpty()) return null; for (RangeDimension rd : attributes) { if (!(rd instanceof SampleDimension)) continue; final int i = Integer.parseInt(rd.getSequenceIdentifier().tip().toString()); final SampleDimension sd = (SampleDimension) rd; final Band band = new Band(i); band.setMin(sd.getMinValue()); band.setMax(sd.getMaxValue()); band.setStd(sd.getStandardDeviation()); band.setMean(sd.getMeanValue()); if (sd instanceof DefaultSampleDimensionExt) { final DefaultSampleDimensionExt ext = (DefaultSampleDimensionExt) sd; band.setHistogram(ext.getHistogram()); } bands.add(band); } } if (bands.isEmpty()) return null; final ImageStatistics stats = new ImageStatistics(bands.size()); stats.setBands(bands.toArray(new Band[0])); return stats; } }