Search in sources :

Example 1 with ImageProcessor

use of org.apache.sis.image.ImageProcessor in project sis by apache.

the class ImageConverter method call.

/**
 * Prepares the ARGB values to be written in the JavaFX image.
 * The task opportunistically returns statistics on all bands of the source image.
 * They are the statistics used for stretching the color ramp before to paint the JavaFX image.
 *
 * @return statistics on sample value, or {@code null} if not computed.
 */
@Override
protected Statistics[] call() {
    if (sourceAOI == null) {
        sourceAOI = ImageUtilities.getBounds(source);
    }
    /*
         * Use a uniform scale. At least one of `width` or `height` will be unchanged.
         * We favor showing fully the image instead of filling all the canvas space.
         */
    final double scale = Math.min(width / (double) sourceAOI.width, height / (double) sourceAOI.height);
    xpos = (width - (width = Numerics.clamp(Math.round(scale * sourceAOI.width)))) / 2;
    ypos = (height - (height = Numerics.clamp(Math.round(scale * sourceAOI.height)))) / 2;
    if (width <= 0 || height <= 0) {
        return null;
    }
    final AffineTransform toCanvas = AffineTransform.getScaleInstance(scale, scale);
    toCanvas.translate(-sourceAOI.x, -sourceAOI.y);
    /*
         * Stretch color ramp using statistics about source image before to paint on JavaFX image.
         */
    final ImageProcessor processor = new ImageProcessor();
    final Statistics[] statistics = processor.valueOfStatistics(source, sourceAOI, (DoubleUnaryOperator[]) null);
    final RenderedImage image = processor.stretchColorRamp(source, JDK9.mapOf("multStdDev", 3, "statistics", statistics));
    final RenderedImage mask = getMask(processor);
    final BufferedImage buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
    final Graphics2D graphics = buffer.createGraphics();
    try {
        graphics.drawRenderedImage(RenderingWorkaround.wrap(image), toCanvas);
        if (mask != null) {
            graphics.drawRenderedImage(RenderingWorkaround.wrap(mask), toCanvas);
        }
    } finally {
        graphics.dispose();
    }
    data = ((DataBufferInt) buffer.getRaster().getDataBuffer()).getData();
    return statistics;
}
Also used : ImageProcessor(org.apache.sis.image.ImageProcessor) AffineTransform(java.awt.geom.AffineTransform) RenderedImage(java.awt.image.RenderedImage) Statistics(org.apache.sis.math.Statistics) BufferedImage(java.awt.image.BufferedImage) DoubleUnaryOperator(java.util.function.DoubleUnaryOperator) Graphics2D(java.awt.Graphics2D)

Example 2 with ImageProcessor

use of org.apache.sis.image.ImageProcessor in project sis by apache.

the class MemoryGridResource method read.

/**
 * Returns a subset of the wrapped grid coverage. If a non-null grid geometry is specified, then
 * this method tries to return a grid coverage matching the given grid geometry on a best-effort basis.
 * In current implementation this is either a {@link org.apache.sis.coverage.grid.GridCoverage2D} or
 * the original grid coverage.
 *
 * @param  domain  desired grid extent and resolution, or {@code null} for the whole domain.
 * @param  range   0-based indices of sample dimensions to read, or {@code null} or an empty sequence for reading them all.
 * @return the grid coverage for the specified domain and range.
 */
@Override
public GridCoverage read(GridGeometry domain, final int... range) {
    List<SampleDimension> bands = coverage.getSampleDimensions();
    final RangeArgument rangeIndices = validateRangeArgument(bands.size(), range);
    /*
         * The given `domain` may use arbitrary `gridToCRS` and `CRS` properties.
         * For this simple implementation we need the same `gridToCRS` and `CRS`
         * than the wrapped coverage; only domain `extent` is allowed to differ.
         * Subsampling is ignored for now because it is an expensive operation.
         * Clipping and range selection are light and do not copy any data.
         *
         * TODO: a future implementation may apply subsampling efficiently,
         *       by adjusting the pixel stride in SampleModel.
         */
    GridExtent intersection = null;
    final GridGeometry source = coverage.getGridGeometry();
    if (domain == null) {
        domain = source;
    } else {
        intersection = source.derive().rounding(GridRoundingMode.ENCLOSING).subgrid(domain).getIntersection();
        if (intersection.equals(source.getExtent())) {
            // Will request the whole image.
            intersection = null;
            domain = source;
        }
    }
    /*
         * Quick check before to invoke the potentially costly `coverage.render(…)` method.
         */
    final boolean sameBands = rangeIndices.isIdentity();
    if (sameBands && intersection == null) {
        return coverage;
    }
    /*
         * After `render(…)` execution, the (minX, minY) image coordinates are the differences between
         * the extent that we requested and the one that we got. If that differences is not zero, then
         * we need to translate the `GridExtent` in order to make it matches what we got. But before to
         * apply that translation, we adjust the grid size (because it may add another translation).
         */
    RenderedImage data = coverage.render(intersection);
    if (intersection != null) {
        final int[] sd = intersection.getSubspaceDimensions(2);
        final int dimX = sd[0];
        final int dimY = sd[1];
        final long ox = intersection.getLow(dimX);
        final long oy = intersection.getLow(dimY);
        final long[] changes = new long[Math.max(dimX, dimY) + 1];
        for (int i = changes.length; --i >= 0; ) {
            // We need only the dimensions that may change.
            changes[i] = intersection.getSize(i);
        }
        changes[dimX] = data.getWidth();
        changes[dimY] = data.getHeight();
        intersection = intersection.resize(changes);
        /*
             * Apply the translation after we resized the grid extent, because the resize operation
             * may have caused an additional translation. We cancel that translation with terms that
             * restore the (ox,oy) lower coordinates before to add the data minimum X,Y.
             */
        Arrays.fill(changes, 0);
        changes[dimX] = Math.addExact(ox - intersection.getLow(dimX), data.getMinX());
        changes[dimY] = Math.addExact(oy - intersection.getLow(dimY), data.getMinX());
        intersection = intersection.translate(changes);
        /*
             * If the result is the same intersection than the source coverage,
             * we may be able to return that coverage directly.
             */
        if (intersection.equals(source.getExtent())) {
            if (sameBands) {
                return coverage;
            }
            domain = source;
        } else {
            domain = new GridGeometry(intersection, PixelInCell.CELL_CORNER, source.getGridToCRS(PixelInCell.CELL_CORNER), source.getCoordinateReferenceSystem());
        }
    }
    if (!sameBands) {
        data = new ImageProcessor().selectBands(data, range);
        bands = UnmodifiableArrayList.wrap(rangeIndices.select(bands));
    }
    return new GridCoverageBuilder().setValues(data).setRanges(bands).setDomain(domain).build();
}
Also used : GridGeometry(org.apache.sis.coverage.grid.GridGeometry) GridExtent(org.apache.sis.coverage.grid.GridExtent) SampleDimension(org.apache.sis.coverage.SampleDimension) ImageProcessor(org.apache.sis.image.ImageProcessor) GridCoverageBuilder(org.apache.sis.coverage.grid.GridCoverageBuilder) RenderedImage(java.awt.image.RenderedImage)

Aggregations

RenderedImage (java.awt.image.RenderedImage)2 ImageProcessor (org.apache.sis.image.ImageProcessor)2 Graphics2D (java.awt.Graphics2D)1 AffineTransform (java.awt.geom.AffineTransform)1 BufferedImage (java.awt.image.BufferedImage)1 DoubleUnaryOperator (java.util.function.DoubleUnaryOperator)1 SampleDimension (org.apache.sis.coverage.SampleDimension)1 GridCoverageBuilder (org.apache.sis.coverage.grid.GridCoverageBuilder)1 GridExtent (org.apache.sis.coverage.grid.GridExtent)1 GridGeometry (org.apache.sis.coverage.grid.GridGeometry)1 Statistics (org.apache.sis.math.Statistics)1