// Catalano Imaging Library
// The Catalano Framework
//
// Copyright 2015 Diego Catalano
// diego.catalano at live.com
//
// Copyright 2015 Jerry Huxtable
// jerry at jhlabs.com
//
// Based on JH Labs
//
// 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 Catalano.Imaging.Tools;

import Catalano.Core.FloatPoint;
import java.io.Serializable;
import java.util.List;

/**
 * Curve representation.
 * @author Diego Catalano
 */
public class Curve implements Serializable{
    
    public float[] x;
    public float[] y;

    /**
     * Get value of the x axis coordinates.
     * @return X axis coordinates.
     */
    public float[] getX() {
        return x;
    }
    
    /**
     * Set values of the x axis coordinates.
     * @param x X axis coordinates.
     */
    public void setX(float[] x) {
        this.x = x;
    }

    /**
     * Get value of the y axis coordinates.
     * @return Y axis coordinates.
     */
    public float[] getY() {
        return y;
    }

    /**
     * Set value of the y axis coordinates.
     * @param y Y axis coordinates.
     */
    public void setY(float[] y) {
        this.y = y;
    }
    
    /**
     * Set the values.
     * @param x X axis coordinates.
     * @param y Y axis coordinates.
     */
    public void setXY(float[] x, float[] y){
        this.x = x;
        this.y = y;
    }
    
    /**
     * Initialize a new instance of the Curve class.
     */
    public Curve() {
        x = new float[0];
        y = new float[0];
    }
    
    /**
     * Initialize a new instance of the Curve class.
     * @param curve Curve.
     */
    public Curve( Curve curve ) {
        x = (float[])curve.x.clone();
        y = (float[])curve.y.clone();
    }
    
    /**
     *  Initialize a new instance of the Curve class.
     * @param x X points.
     * @param y Y points.
     */
    public Curve(float[] x, float[] y){
        this.x = x;
        this.y = y;
    }
    
    /**
     * Add collection of points.
     * @param points Points.
     */
    public void addPoint(List points){
        for (FloatPoint p : points) {
            addPoint(p);
        }
    }
    
    /**
     * Add point in the curve.
     * @param point Point.
     */
    public void addPoint(FloatPoint point){
        addPoint(point.x, point.y);
    }
    
    /**
     * Add point in the curve.
     * @param kx X axis coordinate.
     * @param ky Y axis coordinate.
     */
    public void addPoint( float kx, float ky ) {
        int pos = -1;
        int numKnots = x.length;
        float[] nx = new float[numKnots+1];
        float[] ny = new float[numKnots+1];
        int j = 0;
        for ( int i = 0; i < numKnots; i++ ) {
                if ( pos == -1 && x[i] > kx ) {
                        pos = j;
                        nx[j] = kx;
                        ny[j] = ky;
                        j++;
                }
                nx[j] = x[i];
                ny[j] = y[i];
                j++;
        }
        if ( pos == -1 ) {
                //pos = j;
                nx[j] = kx;
                ny[j] = ky;
        }
        x = nx;
        y = ny;
        //return pos;
    }
    
    /**
     * Remove point
     * @param index Index.
     */
    public void removePoint(int index) {
        int numKnots = x.length;
        if ( numKnots <= 2 )
                return;
        float[] nx = new float[numKnots-1];
        float[] ny = new float[numKnots-1];
        int j = 0;
        for ( int i = 0; i < numKnots-1; i++ ) {
                if ( i == index )
                        j++;
                nx[i] = x[j];
                ny[i] = y[j];
                j++;
        }
        x = nx;
        y = ny;
    }
    
    /**
     * Clear all the points.
     */
    public void clear(){
        x = y = null;
    }
    
    /**
     * Create LUT.
     * @return LUT.
     */
    public int[] makeLut() {
        int numKnots = x.length;
        float[] nx = new float[numKnots+2];
        float[] ny = new float[numKnots+2];
        System.arraycopy(x, 0, nx, 1, numKnots);
        System.arraycopy(y, 0, ny, 1, numKnots);
        nx[0] = nx[1];
        ny[0] = ny[1];
        nx[numKnots+1] = nx[numKnots];
        ny[numKnots+1] = ny[numKnots];

        int[] table = new int[256];
        for (int i = 0; i < 1024; i++) {
                float f = i/1024.0f;
                int x = (int)(255 * Curve.Spline( f, nx.length, nx ) + 0.5f);
                int y = (int)(255 * Curve.Spline( f, nx.length, ny ) + 0.5f);
                x = x > 255 ? 255 : x;
                x = x < 0 ? 0 : x;
                y = y > 255 ? 255 : y;
                y = y < 0 ? 0 : y;
                table[x] = y;
        }
        return table;
    }
    
    /**
     * Compute a Catmull-Rom spline.
     * @param x the input parameter
     * @param numKnots the number of knots in the spline
     * @param knots the array of knots
     * @return the spline value
     */
    public static float Spline(float x, int numKnots, float[] knots) {
        int span;
        int numSpans = numKnots - 3;
        float k0, k1, k2, k3;
        float c0, c1, c2, c3;

        if (numSpans < 1)
                throw new IllegalArgumentException("Too few knots in spline");

        x = x > 1 ? 1 : x;
        x = x < 0 ? 0 : x;
        x *= numSpans;
        span = (int)x;
        if (span > numKnots-4)
                span = numKnots-4;
        x -= span;

        k0 = knots[span];
        k1 = knots[span+1];
        k2 = knots[span+2];
        k3 = knots[span+3];

        c3 = -0.5f*k0 + 1.5f*k1 + -1.5f*k2 + 0.5f*k3;
        c2 = 1f*k0 + -2.5f*k1 + 2f*k2 + -0.5f*k3;
        c1 = -0.5f*k0 + 0f*k1 + 0.5f*k2 + 0f*k3;
        c0 = 0f*k0 + 1f*k1 + 0f*k2 + 0f*k3;

        return ((c3*x + c2)*x + c1)*x + c0;
    }
    
    /**
     * Compute a Catmull-Rom spline, but with variable knot spacing.
     * @param x the input parameter
     * @param numKnots the number of knots in the spline
     * @param xknots the array of knot x values
     * @param yknots the array of knot y values
     * @return the spline value
     */
    public static float Spline(float x, int numKnots, int[] xknots, int[] yknots) {
        int span;
        int numSpans = numKnots - 3;
        float k0, k1, k2, k3;
        float c0, c1, c2, c3;

        if (numSpans < 1)
                throw new IllegalArgumentException("Too few knots in spline");

        for (span = 0; span < numSpans; span++)
                if (xknots[span+1] > x)
                        break;
        if (span > numKnots-3)
                span = numKnots-3;
        float t = (float)(x-xknots[span]) / (xknots[span+1]-xknots[span]);
        span--;
        if (span < 0) {
                span = 0;
                t = 0;
        }

        k0 = yknots[span];
        k1 = yknots[span+1];
        k2 = yknots[span+2];
        k3 = yknots[span+3];

        c3 = -0.5f*k0 + 1.5f*k1 + -1.5f*k2 + 0.5f*k3;
        c2 = 1f*k0 + -2.5f*k1 + 2f*k2 + -0.5f*k3;
        c1 = -0.5f*k0 + 0f*k1 + 0.5f*k2 + 0f*k3;
        c0 = 0f*k0 + 1f*k1 + 0f*k2 + 0f*k3;

        return ((c3*t + c2)*t + c1)*t + c0;
    }
}
 

Ads help maintain this website.