This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new bc36b68 Add Lanczos interpolation (experimental). bc36b68 is described below commit bc36b680ccf811df33986a1b0c4ce5db79cf975a Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Mar 26 01:15:04 2020 +0100 Add Lanczos interpolation (experimental). --- .../java/org/apache/sis/image/Interpolation.java | 13 +++ .../org/apache/sis/image/LanczosInterpolation.java | 114 +++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java b/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java index f5d8bd3..cdb0498 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java +++ b/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java @@ -27,6 +27,7 @@ import java.nio.DoubleBuffer; * * <p>This interface is designed for interpolations in a two-dimensional space only.</p> * + * @author Rémi Marechal (Geomatys) * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) * @version 1.1 @@ -131,4 +132,16 @@ public interface Interpolation { return true; } }; + + /** + * Lanczos interpolation. The kernel is: + * + * <blockquote> + * <var>L</var>(<var>x</var>) = <var>a</var>⋅sin(π⋅<var>x</var>)⋅sin(π⋅<var>x</var>/<var>a</var>)/(π⋅<var>x</var>)² + * for |<var>x</var>| ≤ lanczos window size + * </blockquote> + * + * @see <a href="https://en.wikipedia.org/wiki/Lanczos_resampling">Lanczos resampling on Wikipedia</a> + */ + Interpolation LANCZOS = new LanczosInterpolation(2); } diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java b/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java new file mode 100644 index 0000000..138df5f --- /dev/null +++ b/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.sis.image; + +import java.util.Arrays; +import java.awt.Dimension; +import java.nio.DoubleBuffer; + + +/** + * Lanczos interpolation of arbitrary size. + * The kernel is: + * + * <blockquote> + * <var>L</var>(<var>x</var>) = <var>a</var>⋅sin(π⋅<var>x</var>)⋅sin(π⋅<var>x</var>/<var>a</var>)/(π⋅<var>x</var>)² + * for |<var>x</var>| ≤ lanczos window size + * </blockquote> + * + * @author Rémi Marechal (Geomatys) + * @author Martin Desruisseaux (Geomatys) + * @version 1.1 + * + * @see <a href="https://en.wikipedia.org/wiki/Lanczos_resampling">Lanczos resampling on Wikipedia</a> + * + * @since 1.1 + * @module + */ +final class LanczosInterpolation implements Interpolation { + /** + * The Lanczos window size. This is denoted <var>a</var> in this class javadoc. + */ + private final double a; + + /** + * Width of the interpolation support region. + */ + private final int span; + + /** + * Creates a new interpolation. + * + * @param a the Lanczos window size. + */ + LanczosInterpolation(final int a) { + this.a = a; + span = 2*a; + } + + /** + * Interpolation name for debugging purpose. + */ + @Override + public String toString() { + return "LANCZOS"; + } + + /** + * Size of the area over which to provide values. + */ + @Override + public Dimension getSupportSize() { + return new Dimension(span, span); + } + + /** + * Applies Lanczos interpolation. + */ + @Override + public boolean interpolate(final DoubleBuffer source, final int numBands, + final double xfrac, final double yfrac, final double[] writeTo, final int writeToOffset) + { + Arrays.fill(writeTo, writeToOffset, writeToOffset + numBands, 0); + final double[] kx = new double[span]; + final double[] ky = new double[span]; + for (int i=0; i<span; i++) { + final double offset = i - a; + kx[i] = kernel(offset + xfrac); + ky[i] = kernel(offset + yfrac); + } + source.mark(); + for (int y=0; y<span; y++) { + for (int x=0; x<span; x++) { + final double k = kx[x] * ky[y]; + for (int b=0; b<numBands; b++) { + writeTo[writeToOffset + b] += k * source.get(); + } + } + } + source.reset(); + return true; + } + + /** + * Computes a value of the Lanczos reconstruction kernel L(x). + */ + private double kernel(double x) { + x *= Math.PI; + return (x != 0) ? Math.sin(x) * Math.sin(x/a)*a / (x*x) : 1; + } +}