/*
* libgimpprint curve functions.
*
* Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
* Robert Krawitz (rlk@alum.mit.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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 General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/**
* @file gutenprint/curve.h
* @brief Curve functions.
*/
#ifndef GUTENPRINT_CURVE_H
#define GUTENPRINT_CURVE_H
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/*
* Curve code borrowed from GTK+, http://www.gtk.org/
*/
/**
* The curve type models a linear, spline or gamma curve. curve
* "inherits" from the sequence data structure (implemented via
* containment), since the curve data is represented internally as a
* sequence of numbers, for linear and spline curves. Linear
* Piecewise Curves (LPCs) should be implemented in the future which
* represent a curve in a more compact format.
*
* Various operations are supported, including interpolation and
* composition.
*
* @defgroup curve curve
* @{
*/
struct stp_curve;
/** The curve opaque data type. */
typedef struct stp_curve stp_curve_t;
/** Curve types. */
typedef enum
{
/** Linear interpolation. */
STP_CURVE_TYPE_LINEAR,
/** Spline interpolation. */
STP_CURVE_TYPE_SPLINE
} stp_curve_type_t;
/** Wrapping mode. */
typedef enum
{
/** The curve does not wrap */
STP_CURVE_WRAP_NONE,
/** The curve wraps to its starting point. */
STP_CURVE_WRAP_AROUND
} stp_curve_wrap_mode_t;
/** Composition types. */
typedef enum
{
/** Add composition. */
STP_CURVE_COMPOSE_ADD,
/** Multiply composition. */
STP_CURVE_COMPOSE_MULTIPLY,
/** Exponentiate composition. */
STP_CURVE_COMPOSE_EXPONENTIATE
} stp_curve_compose_t;
/** Behaviour when curve exceeds bounds. */
typedef enum
{
/** Rescale the bounds. */
STP_CURVE_BOUNDS_RESCALE,
/** Clip the curve to the existing bounds. */
STP_CURVE_BOUNDS_CLIP,
/** Error if bounds are violated. */
STP_CURVE_BOUNDS_ERROR
} stp_curve_bounds_t;
/** Point (x,y) for piecewise curve. */
typedef struct
{
/** Horizontal position. */
double x;
/** Vertical position. */
double y;
} stp_curve_point_t;
/**
* Create a new curve. Curves have y=lower..upper. The default
* bounds are 0..1. The default interpolation type is linear. There
* are no points allocated, and the gamma is defaulted to 1. The curve
* is a dense (equally-spaced) curve.
*
* A wrapped curve has the same value at x=0 and x=1. The wrap mode
* of a curve cannot be changed except by routines that destroy the
* old curve entirely (e. g. stp_curve_copy, stp_curve_read).
* @param wrap the wrap mode of the curve.
* @returns the newly created curve.
*/
extern stp_curve_t *stp_curve_create(stp_curve_wrap_mode_t wrap);
/**
* Copy and allocate a curve.
* dest will be created, and then the contents of source will be
* copied into it. dest must not have been previously allocated
* with stp_curve_create().
* @param curve the source curve.
* @returns the new copy of the curve.
*/
extern stp_curve_t *stp_curve_create_copy(const stp_curve_t *curve);
/**
* Copy a curve.
* Both dest and source must be valid curves previously created with
* stp_curve_create().
* @param dest the destination curve.
* @param source the source curve.
*/
extern void stp_curve_copy(stp_curve_t *dest, const stp_curve_t *source);
/**
* Reverse and allocate a curve.
* dest will be created, and then the contents of source will be
* copied into it. dest must not have been previously allocated
* with stp_curve_create().
* @param curve the source curve.
* @returns the new copy of the curve.
*/
extern stp_curve_t *stp_curve_create_reverse(const stp_curve_t *curve);
/**
* Reverse a curve.
* Both dest and source must be valid curves previously created with
* stp_curve_create().
* @param dest the destination curve.
* @param source the source curve.
*/
extern void stp_curve_reverse(stp_curve_t *dest, const stp_curve_t *source);
/**
* Destroy an curve.
* It is an error to destroy the curve more than once.
* @param curve the curve to destroy.
*/
extern void stp_curve_destroy(stp_curve_t *curve);
/**
* Set the lower and upper bounds on a curve.
* To change the bounds adjusting data as required, use
* stp_curve_rescale instead.
* @param curve the curve to use.
* @param low the lower bound.
* @param high the upper bound.
* @returns FALSE if any existing points on the curve are outside the
* bounds.
*/
extern int stp_curve_set_bounds(stp_curve_t *curve, double low, double high);
/**
* Get the lower and upper bounds on a curve.
* @param curve the curve to use.
* @param low a pointer to a double to store the lower bound in.
* @param high a pointer to a double to store the upper bound in.
*/
extern void stp_curve_get_bounds(const stp_curve_t *curve,
double *low, double *high);
/**
* Get the wrapping mode.
* @param curve the curve to use.
* @returns the wrapping mode.
*/
extern stp_curve_wrap_mode_t stp_curve_get_wrap(const stp_curve_t *curve);
/**
* Determine whether the curve is piecewise
* @param curve the curve to use.
* @returns whether the curve is piecewise
*/
extern int stp_curve_is_piecewise(const stp_curve_t *curve);
/*
* Get the range (lowest and highest value of points) in the curve.
* This does not account for any interpolation that may place
* intermediate points outside of the curve.
* @param curve the curve to use.
* @param low a pointer to double to store the lower limit in.
* @param high a pointer to double to store the upper limit in.
*/
extern void stp_curve_get_range(const stp_curve_t *curve,
double *low, double *high);
/**
* Get the number of allocated points in the curve.
* @param curve the curve to use.
* @returns the number of points.
*/
extern size_t stp_curve_count_points(const stp_curve_t *curve);
/**
* Set the curve interpolation type.
* @param curve the curve to use.
* @param itype the interpolation type.
* @returns 1 on success, or 0 if itype is invalid.
*/
extern int stp_curve_set_interpolation_type(stp_curve_t *curve,
stp_curve_type_t itype);
/**
* Get the curve interpolation type.
* @param curve the curve to use.
* @returns the interpolation type.
*/
extern stp_curve_type_t stp_curve_get_interpolation_type(const stp_curve_t *curve);
/**
* Set all data points of the curve. If any of the data points fall
* outside the bounds, the operation is not performed and FALSE is
* returned. This creates a curve with equally-spaced points.
* @param curve the curve to use.
* @param count the number of points (must be at least two and not
* more than 1048576).
* @param data a pointer to an array of doubles (must be at least
* count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_data(stp_curve_t *curve, size_t count,
const double *data);
/**
* Set all data points of the curve. If any of the data points fall
* outside the bounds, the operation is not performed and FALSE is
* returned. This creates a piecewise curve.
* @param curve the curve to use.
* @param count the number of points (must be at least two and not
* more than 1048576).
* @param data a pointer to an array of points (must be at least
* count in size). The first point must have X=0, and each point must
* have an X value at least .000001 greater than the previous point. If
* the curve is not a wraparound curve, the last point must have X=1.
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_data_points(stp_curve_t *curve, size_t count,
const stp_curve_point_t *data);
/**
* Set the data points in a curve from float values. If any of the
* data points fall outside the bounds, the operation is not performed
* and FALSE is returned. This creates a curve with equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of floats (must be at least
* count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_float_data(stp_curve_t *curve,
size_t count, const float *data);
/**
* Set the data points in a curve from long values. If any of the
* data points fall outside the bounds, the operation is not performed
* and FALSE is returned. This creates a curve with equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of longs (must be at least
* count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_long_data(stp_curve_t *curve,
size_t count, const long *data);
/**
* Set the data points in a curve from unsigned long values. If any
* of the data points fall outside the bounds, the operation is not
* performed and FALSE is returned. This creates a curve with
* equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of unsigned longs (must be at
* least count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_ulong_data(stp_curve_t *curve,
size_t count, const unsigned long *data);
/**
* Set the data points in a curve from integer values. If any of the
* data points fall outside the bounds, the operation is not performed
* and FALSE is returned. This creates a curve with equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of integers (must be at least
* count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_int_data(stp_curve_t *curve,
size_t count, const int *data);
/**
* Set the data points in a curve from unsigned integer values. If
* any of the data points fall outside the bounds, the operation is
* not performed and FALSE is returned. This creates a curve with
* equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of unsigned integers (must be at
* least count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_uint_data(stp_curve_t *curve,
size_t count, const unsigned int *data);
/**
* Set the data points in a curve from short values. If any of the
* data points fall outside the bounds, the operation is not performed
* and FALSE is returned. This creates a curve with equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of shorts (must be at least
* count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_short_data(stp_curve_t *curve,
size_t count, const short *data);
/**
* Set the data points in a curve from unsigned short values. If any
* of the data points fall outside the bounds, the operation is not
* performed and FALSE is returned. This creates a curve with
* equally-spaced points.
* @param curve the curve to use.
* @param count the number of the number of points (must be at least
* two and not more than 1048576).
* @param data a pointer to an array of unsigned shorts (must be at
* least count in size).
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_ushort_data(stp_curve_t *curve,
size_t count, const unsigned short *data);
/**
* Get a curve containing a subrange of data. If the start or count
* is invalid, the returned curve will compare equal to NULL (i. e. it
* will be a null pointer). start and count must not exceed the
* number of points in the curve, and count must be at least 2.
* The curve must be a dense (equally-spaced) curve
* @param curve the curve to use.
* @param start the start of the subrange.
* @param count the number of point starting at start.
* @returns a curve containing the subrange. The returned curve is
* non-wrapping.
*/
extern stp_curve_t *stp_curve_get_subrange(const stp_curve_t *curve,
size_t start, size_t count);
/*
* Set part of a curve to the range in another curve. The data in the
* range must fit within both the bounds and the number of points in
* the first curve. The curve must be a dense (equally-spaced) curve.
* @param curve the curve to use (destination).
* @param range the source curve.
* @param start the starting point in the destination range.
* @param returns 1 on success, 0 on failure.
*/
extern int stp_curve_set_subrange(stp_curve_t *curve, const stp_curve_t *range,
size_t start);
/**
* Get a pointer to the curve's raw data.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This call also returns NULL if the curve is a piecewise
* curve.
*/
extern const double *stp_curve_get_data(const stp_curve_t *curve, size_t *count);
/**
* Get a pointer to the curve's raw data as points.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This call also returns NULL if the curve is a dense
* (equally-spaced) curve.
*/
extern const stp_curve_point_t *stp_curve_get_data_points(const stp_curve_t *curve, size_t *count);
/**
* Get pointer to the curve's raw data as floats.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const float *stp_curve_get_float_data(const stp_curve_t *curve,
size_t *count);
/**
* Get pointer to the curve's raw data as longs.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const long *stp_curve_get_long_data(const stp_curve_t *curve,
size_t *count);
/**
* Get pointer to the curve's raw data as unsigned longs.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const unsigned long *stp_curve_get_ulong_data(const stp_curve_t *curve,
size_t *count);
/**
* Get pointer to the curve's raw data as integers.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const int *stp_curve_get_int_data(const stp_curve_t *curve,
size_t *count);
/**
* Get pointer to the curve's raw data as unsigned integers.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const unsigned int *stp_curve_get_uint_data(const stp_curve_t *curve,
size_t *count);
/**
* Get pointer to the curve's raw data as shorts.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const short *stp_curve_get_short_data(const stp_curve_t *curve,
size_t *count);
/**
* Get pointer to the curve's raw data as unsigned shorts.
* @param curve the curve to use.
* @param count a pointer to a size_t to store the curve size in.
* @returns a pointer to the curve data. This data is not guaranteed
* to be valid beyond the next non-const curve call. If the curve is
* a pure gamma curve (no associated points), NULL is returned and the
* count is 0. This also returns NULL if the curve is a piecewise curve.
*/
extern const unsigned short *stp_curve_get_ushort_data(const stp_curve_t *curve,
size_t *count);
/**
* Get the underlying stp_sequence_t data structure which stp_curve_t
* is derived from.
* This can be used for fast access to the raw data.
* @param curve the curve to use.
* @returns the stp_sequence_t. If the curve is a piecewise curve, the
* sequence returned is NULL;
*/
extern const stp_sequence_t *stp_curve_get_sequence(const stp_curve_t *curve);
/**
* Set the gamma of a curve. This replaces all existing points along
* the curve. The bounds are set to 0..1. If the gamma value is
* positive, the function is increasing; if negative, the function is
* decreasing. Count must be either 0 or at least 2. If the count is
* zero, the gamma of the curve is set for interpolation purposes, but
* points cannot be assigned to. It is illegal to set gamma on a
* wrap-mode curve. The resulting curve is treated as a dense
* (equally-spaced) curve.
* @param curve the curve to use.
* @param f_gamma the gamma value to set.
* @returns FALSE if the gamma value is illegal (0, infinity, or NaN),
* or if the curve wraps around.
*/
extern int stp_curve_set_gamma(stp_curve_t *curve, double f_gamma);
/**
* Get the gamma value of the curve.
* @returns the gamma value. A value of 0 indicates that the curve
* does not have a valid gamma value.
*/
extern double stp_curve_get_gamma(const stp_curve_t *curve);
/**
* Set a point along the curve.
* This call destroys any gamma value assigned to the curve.
* @param curve the curve to use.
* @param where the point to set.
* @param data the value to set where to.
* @returns FALSE if data is outside the valid bounds or if where is
* outside the number of valid points. This also returns NULL if
* the curve is a piecewise curve.
*/
extern int stp_curve_set_point(stp_curve_t *curve, size_t where, double data);
/**
* Get a point along the curve.
* @param curve the curve to use.
* @param where the point to get.
* @param data a pointer to a double to store the value of where in.
* @returns FALSE if where is outside of the number of valid
* points. This also returns NULL if the curve is a piecewise curve.
*/
extern int stp_curve_get_point(const stp_curve_t *curve, size_t where,
double *data);
/**
* Interpolate a point along the curve.
* @param curve the curve to use.
* @param where the point to interpolate.
* @param result a pointer to double to store the value of where in.
* If interpolation would produce a value outside of the allowed range
* (as could happen with spline interpolation), the value is clipped
* to the range.
* @returns FALSE if 'where' is less than 0 or greater than the number
* of points, an error is returned. Also returns FALSE if the curve
* is a piecewise curve.
*/
extern int stp_curve_interpolate_value(const stp_curve_t *curve,
double where, double *result);
/**
* Resample a curve (change the number of points). This does not
* destroy the gamma value of a curve. Points are interpolated as
* required; any interpolation that would place points outside of the
* bounds of the curve will be clipped to the bounds. The resulting
* curve is always dense (equally-spaced). This is the correct way
* to convert a piecewise curve to an equally-spaced curve.
* @param curve the curve to use (must not exceed 1048576).
* @param points the number of points.
* @returns FALSE if the number of points is invalid (less than two,
* except that zero points is permitted for a gamma curve).
*/
extern int stp_curve_resample(stp_curve_t *curve, size_t points);
/**
* Rescale a curve (multiply all points by a scaling constant). This
* also rescales the bounds. Note that this currently destroys the
* gamma property of the curve.
* @param curve the curve to use.
* @param scale the scaling factor.
* @param mode the composition mode.
* @param bounds_mode the bounds exceeding mode.
* @returns FALSE if this would exceed floating point limits
*/
extern int stp_curve_rescale(stp_curve_t *curve, double scale,
stp_curve_compose_t mode,
stp_curve_bounds_t bounds_mode);
/**
* Write a curve to a file.
* The printable representation is guaranteed to contain only 7-bit
* printable ASCII characters, and is null-terminated. The curve will
* not contain any space, newline, single quote, or comma characters.
* Furthermore, a printed curve will be read back correctly in all locales.
* These calls are not guaranteed to provide more than 6 decimal places
* of precision or +/-0.5e-6 accuracy, whichever is less.
* @warning NOTE that these calls are not thread-safe! These
* routines may manipulate the locale to achieve a safe
* representation.
* @param file the file to write.
* @param curve the curve to use.
* @returns 1 on success, 0 on failure.
*/
extern int stp_curve_write(FILE *file, const stp_curve_t *curve);
/**
* Write a curve to a string.
* The printable representation is guaranteed to contain only 7-bit
* printable ASCII characters, and is null-terminated. The curve will
* not contain any space, newline, or comma characters. Furthermore,
* a printed curve will be read back correctly in all locales.
* These calls are not guaranteed to provide more than 6 decimal places
* of precision or +/-0.5e-6 accuracy, whichever is less.
* @warning NOTE that these calls are not thread-safe! These
* routines may manipulate the locale to achieve a safe
* representation.
* @param curve the curve to use.
* @returns a pointer to a string. This is allocated on the heap, and
* it is the caller's responsibility to free it.
*/
extern char *stp_curve_write_string(const stp_curve_t *curve);
/**
* Create a curve from a stream.
* @warning NOTE that these calls are not thread-safe! These
* routines may manipulate the locale to achieve a safe
* representation.
* @param fp the stream to read.
* @returns the newly created curve, or NULL if an error occurred.
*/
extern stp_curve_t *stp_curve_create_from_stream(FILE* fp);
/**
* Create a curve from a stream.
* @warning NOTE that these calls are not thread-safe! These
* routines may manipulate the locale to achieve a safe
* representation.
* @param file the file to read.
* @returns the newly created curve, or NULL if an error occurred.
*/
extern stp_curve_t *stp_curve_create_from_file(const char* file);
/**
* Create a curve from a string.
* @warning NOTE that these calls are not thread-safe! These
* routines may manipulate the locale to achieve a safe
* representation.
* @param string the string to read.
* @returns the newly created curve, or NULL if an error occurred.
*/
extern stp_curve_t *stp_curve_create_from_string(const char* string);
/**
* Compose two curves, creating a third curve. Only add and multiply
* composition is currently supported.
* If both curves are gamma curves with the same sign, and the
* operation is multiplication or division, the returned curve is a
* gamma curve with the appropriate number of points.
* Both a and b must have the same wraparound type.
* @param retval a pointer to store the location of the newly-created
* output curve in.
* @param a the first source curve.
* @param b the second source curve.
* @param mode the composition mode.
* @param points the number of points in the output curve (must not
* exceed 1048576). It must be at least two, unless the curve is a
* gamma curve and the operation chosen is multiplication or division.
* If -1, the resulting number of points will be the least common
* multiplier of the number of points in the input and output curves
* (but will not exceed 1048576).
* @returns FALSE if element-wise composition fails.
*/
extern int stp_curve_compose(stp_curve_t **retval,
stp_curve_t *a, stp_curve_t *b,
stp_curve_compose_t mode, int points);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* GUTENPRINT_CURVE_H */