Когда-нибудь можно будет сказать «cd /usr/ports/lang/ipl && make install clean && man ipl».
Но когда – не знаю.

$ipl
Image processing language interpreter.
Version 0.9.alpha.12 (19 Nov 2018) by Vladimir A. Smirnov.
Usage: ipl <scriptfile>
For brief IPL language description, type ipl --help-ipl.
For brief NSL built-in language description, type ipl --help-nsl.

$ipl --help-ipl

The IPL script can contain:
	"global" section(s);
	definitions of IPL object(s);
	definitions of transform(s);
	definitions of function(s);
	"targets" section(s).

The main purpose of the "global" section is to define aliases. The initial
value of the random number generator can be specified there also. All "global"
sections parsed _before_ any "targets" section. The format of section:

global
{
	random_seed 
	alias  
	alias  
	...
}

where
	 - initial value of random number generator;
	 - string to be replaced by .

The purpose of "targets" section is to specify raster images and IPL
objects that have to be evaluated. Format of "targets" section:

targets
{
	 
	 
	...
	output    ... 
	output    ... 
	...
}

where
	 - class of IPL object (see below);
	 - unique identifier of object;
	 - name of output raster image file;
	 - string that specifies how to handle color channels;
	 - matrices containing data of color channels 0...N.

Internal format of the raster image file is determined by its extension.
Supported formats:
	Windows bitmap (*.bmp)
	TrueVision TARGA (*.tga)
	JPEG (*.jpg) (input only)

The  parameter can be one of the following:
	"RGB": channels 0...3 represents red, green and blue;
	"RGBA": channels 0...4 represents red, green, blue and alpha;
	"CIE": channels 0...3 represents CIE X, Y and Z;
	"HSV": channels 0...3 represents hue, saturation, and value;
	"HSVA": channels 0...4 represents hue, saturation, value and alpha.

The format of IPL object definition:
 
{
	state  
	state  
	...
	  ... 
	  ... 
	...
}

where
	 - name of state field to be set to ;
	 - some operation on current data of object.

The  may be one of the following:
	"custom_width" (unsigned): width of matrix to be loaded/created;
	"custom_height" (unsigned): height of matrix to be loaded/created;
	"custom_size" (unsigned): size of vector to be created;
	"input_powers2" (boolean): resizing flag for matrix to be loaded;
	"input_square" (boolean): resizing flag for matrix to be loaded;
	"frequency_domain" (boolean): affects the interpretation of data;
	"pad_value" (real): padding value for "expand" / "expand_powers2".

The  may be one of the following:
	"matrix": 2D array of real numbers;
	"vector": array of real numbers;
	"decomposition": binary-tree image decomposition.

Valid operations for "matrix" class:
	copy : copies the data from matrix 'src';

	input : loads data from image file;

	get :
		copies contents of source rectangle [left...bottom]
		at [dst_left,dst_top] position of current matrix
		(may be useful for circular shifts of elements);

	set_elem : sets element at 'row' and 'col'
		to 'value';

	set_rect : sets all elements
		in specified rectangle to given 'value';

	shift : circular shift of elements;

	mirror : mirrors
		rows and / or columns of the matrix;

	transpose: transposes the matrix;

	expand : expands or crops the matrix,
		padding it with state->pad_value if necessary;

	expand_powers2: expands the matrix in such a way that both width
		and height becomes powers of 2;

	resize : resizes the matrix using
		subpixel-correct bilinear interpolation;

	save : writes matrix to text file;

	save32 : converts matrix data to fixed-point
		representation (assumes [0..1] range) and writes to TGA file;

	load : reads matrix from text file;

	load32 : reads TGA file and converts data from
		fixed-point representation to [0..1] range;

	constant : sets all elements to given 'value';

	uniform : sets all elements to samples of uniform
		distribution with given 'lower' and 'upper' bounds;

	gaussian : sets all elements to 
		samples of normal distribution with given mean and
		standard deviation;

	row_linear : linearly interpolates from given 'min'
		to given 'max' and writes results to every row;

	col_linear : linearly interpolates from given 'min'
		to given 'max' and writes results to every column;

	fourier_forward: replaces matrix by its 2D Fourier transform;

	fourier_inverse: replaces 2D Fourier transform by its inversion;

	scale : multiplies all elements by given 'value';

	offset : performs either addition of given 'value' to
		all elements of (spatial-domain) matrix, or phase addition
		for frequency-domain matrix;

	mat_scale : per-element multiplication of two matrices
		or (complex) multiplication of two Fourier transforms
		(useful for computing convolutions);

	mat_unscale : per-element division of two matrices
		or (complex) division of two Fourier transforms
		(useful for computing deconvolutions);

	mat_offset : performs either per-element addition of 
		elements of two (spatial-domain) matrices, or per-element
		phase addition of two frequency-domain matrices;

	zero_rows ; clears rows in range ['min','max']
		(operates correctly with Fourier transforms; useful
		for frequency-domain filtering);

	zero_cols : clears columns in range ['min','max']
		(operates correctly with Fourier transforms; useful
		for frequency-domain filtering);

	convolve3x3 : convolves the matrix with 3x3 PSF;

	band_reject : clears both rows and columns in range
		['min','max'] (operates correctly with Fourier transforms;
		useful for frequency-domain filtering);

	band_pass : clears both rows and columns outside the
		range ['min','max'] (operates correctly with Fourier
		transforms; useful for frequency-domain filtering);

	adjust_contrast : linearly interpolates range
		['min';'max'] in current (spatial-domain) matrix to
		range [0,1] (useful for selecting the only specific,
		a-priori known range for visualizing at full contrast;
		shouldn't be confused with "normalize" operation);

	normalize: linearly transforms all elements in such a way that
		minimal value of matrix becomes 0, and maximal becomes 1;

	range_normalize : linearly transforms all
		elements in such a way that minimal value of matrix becomes
		'new_min', and maximal one becomes 'new_max';

	gamma_correction : performs arbitrary transform of all
		elements in such a way that minimal value of matrix becomes
		equal to first element of 'curve', and maximal one becomes
		equal to last element of 'curve'; uses 'curve' as
		input-to-output function (useful for color reduction and
		histogram equalization);

	draw_decomposition : stores (sparse)
		representation of binary image decomposition 'decomp'
		in current matrix;

	draw_decomposition_scale :
		stores representation of binary decomposition 'decomp',
		using, at each depth, colors from vector 'colors';

	draw_decomposition_linear :
		stores representation of binary decomposition 'decomp',
		using, at each depth, colors from 'min' up to 'max';

	matrix_transform : executes
		transform 'name' for current spatial-domain matrix;

	cartesian_transform :
		executes transform 'name' for current frequency-domain
		matrix, passing (Re,Im) pairs on each iteration;

	polar_transform : executes
		transform 'name' for current frequency-domain matrix,
		passing (Magnitude,Phase) pairs on each iteration;

	matrix_pair_transform :
		executes transform 'name' for current and 'other'
		matrices (both matrices must be in spatial domain);

	cartesian_pair_transform :
		executes transform 'name' for current and 'm2'
		matrices (both matrices must be in frequency domain),
		passing (Re1,Im1) and (Re1,Im2) pairs;

	polar_pair_transform :
		executes transform 'name' for current and 'other'
		matrices (both matrices must be in frequency domain),
		passing (Magnitude1,Phase1) and (Magnitude2,Phase2) pairs;

	spectrum: replaces current frequency-domain matrix by its (half-sized)
		power spectrum estimation (adds magnitudes which
		corresponds to maximal and zero frequencies);

	puts : writes 'token' to standard output;

	run_time: prints time since the start of program.


Valid operations for "vector" class:
	copy : copies the data from vector 'src';

	save : writes vector to text file;

	load : loads vector from text file;

	shift : circular shift of elements;

	mirror: mirrors the vector;

	uniform : sets all elements to samples of uniform
		distribution with given 'lower' and 'upper' bounds;

	gaussian : sets all elements to 
		samples of normal distribution with given mean and
		standard deviation;

	constant : sets all elements to given 'value';

	linear : linearly interpolates from 'min' to 'max';

	histogram : computes histogram of matrix 'src',
		lower bound of first bin will be equal to minimal element
		of 'src', upper bound of last bin will be equal to maximal
		element of 'src';

	range_histogram : computes histogram of 'src',
		lower bound of first bin will be equal to 'min', upper
		bound of last bin will be equal to 'max';

	histogram_with_coords : computes histogram
		of matrix 'src', stores center of each bin to 'coords';

	range_histogram_with_coords : computes range histogram
		of matrix 'src', stores center of each bin to 'coords';

	integrate: computes running sum ("discrete integral");

	normalize: linearly transforms all elements in such a way that
		minimal value of vector becomes 0, and maximal becomes 1;

	range_normalize : linearly transforms all
		elements in such a way that minimal value of vector becomes
		'new_min', and maximal one becomes 'new_max';

	vector_transform : executes
		transform 'name' for current spatial-domain vector;

	vector_pair_transform :
		executes transform 'name' for current and 'other'
		spatial-domain vectors;

	puts : writes 'token' to standard output;

	run_time: prints time since the start of program.


Valid operations for "decomposition" class:
	decompose :
		decomposes matrix 'src' with given 'threshold' and,
		each level, computes histograms of size 'histogram_divisions';

	save :
		saves ASCII description of decomposition to file 'file_name';

	puts : writes 'token' to standard output;

	run_time: prints time since the start of program.


Valid channel names for matrix "input" operation
	"red"	"green"	"blue"
	"red"	"green"	"blue"	"alpha"
	"cieX"	"cieY"	"cieZ"
	"hue"	"saturation"	"value"
	"hue"	"saturation"	"value"	"alpha"

Format of transform definition:
 (void|[arg1,arg2,...,argN])
{
	step|pass
		
	step|pass
		
	...
}

where
	 - NSL compound statement (see source/examples :(... );
	 - unique identifier of transform.

If the  follows "step", it will be executed once;
if it follows "pass", it will be executed for every element of the
current IPL object.

The  may be one of the following:

	"vector_transform": iterates through elements of vector;
	"vector_pair_transform": iterates through elements of two vectors;
	"matrix_transform": iterates through elements of matrix;
	"matrix_pair_transform": iterates through elements of two matrices;
	"cartesian_transform": iterates through elements of Fourier transform,
		passing the (Re,Im) pairs;
	"cartesian_pair_transform": iterates through elements of two Fourier
		transforms, passing the (Re,Im) pairs;
	"polar_transform": iterates through elements of Fourier transform,
		passing the (Magnitude,Phase) pairs;
	"polar_pair_transform": iterates through elements of two Fourier
		transforms, passing the (Magnitude,Phase) pairs.

Built-in variables valid for each type of transform:

	"vector_transform":
	"$MAX_IDX": maximal index of element;
	"$IDX": index of element;
	"$ELEM": value of current element.

	"vector_pair_transform":
	"$MAX_IDX": maximal index of element;
	"$IDX": index of element;
	"$ELEM1": value of element of current vector;
	"$ELEM2": value of element of other vector.

	"matrix_transform":
	"$MAX_ROW": maximal index of row;
	"$MAX_COL": maximal index of column;
	"$ROW": current row;
	"$COL": current column;
	"$CELL": value of current cell.

	"matrix_pair_transform":
	"$MAX_ROW": maximal index of row;
	"$MAX_COL": maximal index of column;
	"$ROW": current row;
	"$COL": current column;
	"$CELL1": value of element of current matrix;
	"$CELL2": value of element of other matrix.

	"cartesian_transform":
	"$MAX_ROW": maximal index of row;
	"$MAX_COL": maximal index of column;
	"$ROW": current row;
	"$COL": current column;
	"$NEG_FREQ": one means negative frequency;
	"$RE": real part of current FT cell;
	"$IM": imaginary part of current FT cell.

	"cartesian_pair_transform":
	"$MAX_ROW": maximal index of row;
	"$MAX_COL": maximal index of column;
	"$ROW": current row;
	"$COL": current column;
	"$NEG_FREQ": one means negative frequency;
	"$RE1": real part of cell of current FT;
	"$IM1": imaginary part of cell of current FT;
	"$RE2": real part of cell of other FT;
	"$IM2": imaginary part of cell of other FT.

	"polar_transform":
	"$MAX_ROW": maximal index of row;
	"$MAX_COL": maximal index of column;
	"$ROW": current row;
	"$COL": current column;
	"$NEG_FREQ": one means negative frequency;
	"$MAG": magnitude of current FT cell;
	"$PHASE": phase of current FT cell.

	"polar_pair_transform":
	"$MAX_ROW": maximal index of row;
	"$MAX_COL": maximal index of column;
	"$ROW": current row;
	"$COL": current column;
	"$NEG_FREQ": one means negative frequency;
	"$MAG1": magnitude of cell of current FT;
	"$PHASE1": phase of cell of current FT;
	"$MAG2": magnitude of cell of other FT;
	"$PHASE2": phase of cell of other FT.

Built-in constants valid for any transform and function:

	"Pi": Pi = 3.14159265358979312...;
	"E": e = 2.71828182845904509...;
	"MAXREAL": maximal value of 'real' variable;
	"REAL_ZERO": small, but still invertible value of 'real' variable.

Format of function definition:
function 


where
	 - unique identifier of function;
	 - NSL compound statement, which should contain
	'return' statement (or the assignment to '%' variable).

IPL run completed: success. (alloc: 0 bytes; leak: 0 bytes)

$ipl --help-nsl
===============================
NSL unary operations:
neg:	negates tos[0] (unary minus)
abs:	absolute value of tos[0]
ceil:	smallest integer not less than tos[0]
floor:	largest integer not greater than tos[0]
sqr:	square of tos[0]
sqrt:	square root of tos[0]
sin:	sine of tos[0]
csc:	cosecant of tos[0]
cos:	cosine of tos[0]
sec:	secant of tos[0]
tg:	tangent of tos[0]
ctg:	cotangent of tos[0]
arcsin:	arcsine of tos[0]
arccsc:	arccosecant of tos[0]
arccos:	arccosine of tos[0]
arcsec:	arcsecant of tos[0]
arctg:	arctangent of tos[0]
arcctg:	arccotangent of tos[0]
exp:	exponent of tos[0]
sh:	hyperbolic sine of tos[0]
ch:	hyperbolic cosine of tos[0]
th:	hyperbolic tangent of tos[0]
ln:	natural logarithm of tos[0]
lg:	base 10 logarithm of tos[0]
log2:	base 2 logarithm of tos[0]
arsh:	inverse hyperbolic sine of tos[0]
arch:	inverse hyperbolic cosine of tos[0]
arth:	inverse hyperbolic tangent of tos[0]
===============================
NSL binary operations:
+:	adds tos[1] to tos[0]
-:	subtracts tos[0] from tos[1]
*:	multiplies tos[1] by tos[0]
/:	divides tos[1] by tos[0]
mod:	remainder of tos[1] / tos[0]
^:	raises tos[1] to the power of tos[0]
log:	base tos[0] logarithm of tos[1]
arctg2:	arctangent of fraction tos[1] / tos[0]
<:	returns (tos[1] < tos[0]) ? 1 : 0
>:	returns (tos[1] > tos[0]) ? 1 : 0
==:	returns (abs(tos[1] - tos[0]) < FLOAT_ZERO_EPSILON) ? 1 : 0
!=:	returns (abs(tos[1] - tos[0]) > FLOAT_ZERO_EPSILON) ? 1 : 0
===============================
NSL statements:
assignment:   = ;
"if":  if   [else ]
"var":  var [,,...,];
"return":  return ;
IPL run completed: success. (alloc: 0 bytes; leak: 0 bytes)

В язык ipl встроен язык NSL a.k.a «nano scripting language». На этом языке пишется код обработчиков (ключевые слова чтототам_transform). Тип данных только один - число с плавающей точкой (одинарной или двойной точности – определяется на этапе компиляции интерпретатора). Выражения записываются в обратной польской нотации. Среди управляющих структур – только условный оператор (другие по смыслу не нужны; семантика всех операций чтототам_transform – такая же, как пиксельных шейдеров).

Назад