Array Class Reference
N-dimensional arrays over scalar data.
More...
#include <array.h>
Visible Fields
Structures
• |
min
| : Vector * |
• |
max
| : Vector * |
|
|
Enumerated Scalars
|
Array_Kind
| : { PLAIN_KIND, RGB_KIND, RGBA_KIND, COMPLEX_KIND } |
|
Color_Index
| : { RED_INDEX, GREEN_INDEX, BLUE_INDEX, ALPHA_INDEX } |
|
Complex_Index
| : { REAL_INDEX, IMAG_INDEX } |
|
|
Descriptive Types
Routines
Creation and Basic Manipulation
Dimn_Type |
ADIMN
(Array *a) |
Indx_Type |
AINDX
(Array *a) |
Size_Type |
ASIZE
(Array *a) |
Offs_Type |
AOFFS
(Array *a) |
Array * |
Make_ArrayG
(Array_Kind kind, Value_Type type, int ndims, Dimn_Type *dims) |
Array * |
Make_Array_With_ShapeG
(Array_Kind kind, Value_Type type, Coordinate *shape F) |
Array * |
Make_Array_From_ArraysG
(Array_Kind kind, int n, Array **arrays) |
Array * |
Make_Array_Of_DataG
(Array_Kind kind, Value_Type type, int ndims, Dimn_Type *dims, void *data) |
Coordinates
Coordinate * |
CoordG
(string list) |
void |
Print_Coord
(FILE *f, Coordinate *coord F) |
Coordinate * |
Coord1G
(Dimn_Type d1) |
Coordinate * |
Coord2G
(Dimn_Type d2, Dimn_Type d1) |
Coordinate * |
Coord3G
(Dimn_Type d3, Dimn_Type d2, Dimn_Type d1) |
Coordinate * |
Coord4G
(Dimn_Type d4, Dimn_Type d3, Dimn_Type d2, Dimn_Type d1) |
Coordinate * |
AppendCoord
(Dimn_Type d, Coordinate *coord RM) |
Coordinate * |
PrependCoord
(Coordinate *coord RM, Dimn_Type d) |
Coordinate * |
Idx2CoordAG
(Array *a, Indx_Type idx) |
Indx_Type |
Coord2IdxA
(Array *a, Coordinate *coord F) |
Coordinate * |
Idx2CoreAG
(Array *a, Indx_Type idx) |
Coordinate * |
Idx2CoreG
(Indx_Type idx) |
Conversion, Element-Wise Ops, Padding, Clipping, and Down-Sampling
Array * |
Convert_ArrayG
(Array *a, Array_Kind kind, Value_Type type, int scale, int|double factor) |
Array * |
Convert_Array_Inplace
(Array *a RM, Array_Kind kind, Value_Type type, int scale, int|double factor) |
Range_Bundle * |
Array_Range
(Range_Bundle *range RO, AForm *a) |
APart * |
Array_Op_Scalar
(APart *a RM, Operator op, Value_Type type, Value v) |
APart * |
Complex_Op_Scalar
(APart *a RM, Operator op, Value_Type type, Value v, Value w) |
APart * |
Array_Fct_Val
(APart *a RM, Value (*fct)(void * valp)) |
APart * |
Array_Fct_Idx
(APart *a RM, Value (*fct)(Coordinate *coord)) |
Array * |
Apply_MapG
(Array *image, Array *map) |
Array * |
Down_SampleG
(AForm *source, Coordinate *box F) |
Array * |
Clip_ArrayG
(AForm *source, Coordinate *beg F, Coordinate *end F) |
Array * |
Pad_ArrayG
(AForm *source, Coordinate *anchor F, Coordinate *shape F) |
Detailed Description
An array is the central object of the Mylib library and is used throughout. This page
describes primarily those routines and matters that pertain to arrays in and of themselves.
All the fields of an Array object's structure are visible to the user in order to facilitate
access. One may freely change the values of the elements in an array without concern for
unanticipated side-effects. However, we recommend that you do not make any changes to the
dimensions, type, kind, or any other facet of an array that changes its size unless you
have familiarized yourself with the object conventions and how Mylib's object manager works
by reading the document
Object.Management.
Anatomy of an Array
An array can have any number of dimensions ndims and the size of each dimension
is given by dims[i] for i from 0 to ndims-1 where 0 is the innermost (and fastest moving)
dimension.
The elements of an array of are all of a given type that is one of the ten scalar
Value_Types that
cover unsigned integers, signed integers, and floating point values of all standard sizes.
Moreover, for the signed and unsigned integer types, the scale-field specifies the number
of bits used to encode the value. Typically this is just the number of bits in the underlying
element type (e.g. 32 if INT32_TYPE, or UINT32_TYPE), but it may be
a smaller number if desirable. This is motivated by the frequent occurence in microscopy
data, of 12-bit or 10-bit D/A converters in a microscope's CCD camera.
One might, for example, recieve an array with elements of type UINT16_TYPE and a scale of 12.
This makes almost no difference to any routine in the package which will happily treat
the values as uint16, except when the array is read or written to a TIFF file
(e.g. Read_Image, Read_Images, etc.),
or when one converts an array from one type and scale to another
(e.g. Convert_Array, Convert_Image, etc.)
The data field is a void pointer to the elements of the array stored as a linear vector.
To obtain a pointer to the appropriate type use one of the routines AUINT8, AUINT16, ...
AFLOAT64 below (these are actually simple macros). The elements are layed out
with dims[0] being the fastest moving dimension, i.e., for an n-dimensional array
the index of
A[xn-1,...,x1,x0]
is
(... (xn-1*dims[n-2] + xn-2)*dims[n-3] + ...)*dims[0] + x0
using Horner's rule. While it could be computed from dims and ndims, Mylib keeps the
size of an array as a field (NB: this is not the size in bytes, but the number of elements
in the array).
There are four kinds of arrays: plain, rgb, rgba, and complex that are indicated by the
values of the enum Array_Kind. Every kind of array is basically an n-dimensional array
over the ten scalar types, but in the case of all but PLAIN_KIND arrays, there is a
restriction on one of the dimensions. Specifically, if an array is of RGB_KIND or RGBA_KIND
then the outermost dimension must be 3 and 4, respectively, one (n-1)-dimensional sub-array
of red, green, blue, and alpha values. If an array is of COMPLEX_KIND then the innermost
dimension is 2, where the first element in this dimension is the real part, and the second
the imaginary part of a complex number. As an example, consider a 3 x 5 x 2 array, A.
It can be interpreted as either a 3 x 5 x 2 plain array, a 5 x 2 array of rgb colors, or
a 3 x 5 array of complex numbers, depending on its kind.
That is, (A[0,y,x],A[1,y,x],A[2,y,x]) can represent an rgb-triple or color, or
A[x,y,0] + i A[x,y,1] can represents a complex number. The choice to have color be
the outer rather than the inner dimension is unconventional, but it gives one the ability
to work independently on a red, green, blue, or alpha sub-array easily, with no real
downside to setting or computing on color-tuples in terms of code or efficiency on today's
machines with 4-or-more-way interleaved caches.
The shape of an array is the ndims element vector of its dimensions dims. For example,
for the array A in our example above, it's shape is the vector (3,5,2). The core shape
of an array is its shape less the special dimension attributed to its kind. For example,
A has core shape (3,5) if it is of COMPLEX_KIND, (5,2) if it is of RGB_KIND, and
(3,5,2) if it is of PLAIN_KIND. Care must be taken that some routines work with core
shapes (e.g. all the drawing routines) while most work directly with an array's shape.
While rgb and rgba arrays are typically of type UINT8_TYPE or UINT16_TYPE, and complex
array are typically FLOAT32_TYPE or FLOAT64_TYPE, we do not so restrict them nor do
our tiff reader/writer routines. For the alpha channel the convention is that alpha
is between 0. and 1. for floating point types, and for integer types, no transparency
or 100% opacity, is denoted by the largest possible positive value
encodable with the number of bits given by the type and scale, e.g. 1024 = 2^10-1 when
type = UINT8_TYPE and scale = 10, and 32677 = 2^15-1 when type = INT16_TYPE
and scale = 16.
Finally, every array has an associated text tag, text, whose length is tlen.
The text tag is generally the empty string for ordinary arrays, but one can label
arrays with arbitrarily long strings if they find it useful. In particular, the
Print_Inuse_List routine will list the text tag of each array so one can identify
them in the usage analysis report when trying to debug an object memory leak. Furthermore
the text tag is read/written from and to the JF_TAGGER tag of a TIFF file by Mylib, so
it can be used as a means to encode arbirary amounts of meta-data about an array or image.
Creating and Accessing Arrays
There are currently four ways to generate a new array from scratch: Make_Array,
Make_Array_With_Shape, Make_Array_Of_Data and Make_Array_From_Arrays. The first
two routines take parameters that specify the kind, type, and core shape of the array
desired. Make_Array recieves the shape as an ndim,dims pair and Make_Array_With_Shape
recieves it in the form of an integer Coordinate. Make_Array_Of_Data takes a
linear data array supplied by the caller and wraps an array object around it, taking
ownership of the data vector. Make_Array_From_Arrays takes an array of pointers to say
n arrays all of the same shape α, generates an array of shape (n,&alpha), and
fills it in with the values of the n arrays. For example, one can construct an
RGB_KIND array from three planes as follows:
Array **planes[3];
planes[0] = a_red_array;
planes[1] = a_green_array;
planes[2] = a_blue_array;
color = Make_Array_From_Arrays(RGB_KIND,3,planes);
One can set the text tag of an array with Set_Array_Text and append to it with
Append_To_Array_Text. There are also simple routines to get and set a given element
of an array: Get_Array_Value and Set_Array_Value. These are provided mostly as an
example for users in order to make sure they understand how elements are indexed and
accessed. Any serious computation over an array is expected to be done directly with
indices into an array's data or with the aid of the array traversal mechanisms provided
by the Slice and Frame classes.
One can select sub-slices of an array by peeling away the outer dimension with Get_Array_Plane.
The idea is to be efficient and not create a new array object, but rather a "fake" array that
is valid as long as the underlying real array object is not modified. This "fake" array is
an Array_Bundle that is just the outer struct of an array object whose dims, data, and
text pointers are into a real array's structure. Get_Array_Plane takes a valid
Array_Bundle and modifies it so that upon return the bundle models the requested sub-array.
The tricky part is that the bundle must initially be set up by assigning it to the outer-struct
of a real array object. For example, the code below, takes the color
array from the example above, and peals off each color sub-array:
Array_Bundle red, green, blue;
red = green = blue = *color;
Get_Array_Plane(&red,0);
Get_Array_Plane(&green,1);
Get_Array_Plane(&blue,2);
If a real independent, and proper object is need for a sub-array then call
Copy_Array on
the fetched plane, e.g. Copy_array(&red).
Moreover, more than one layer of outer dimensions can be peeled away:
Array_Bundle bundle;
Get_Array_Plane(Get_Array_Plane(&(bundle=*color),1),3);
gets the 3rd z-plane of the green pixels when color
is a 3D RGB_KIND array.
One can produce an ASCII print out of an array, slice, or frame with Print_Array. The
caller can specify the indentation, the output stream to be written to, and the format in
which to print the numbers. Obviously this capability is not designed for very large
arrays, but more for small examples to help one develope a code using Mylib. Moreover,
arrays are typically so frequently used in a code that there is the possibility of failing
to free or kill one, creating a memory leak. To facilitate the developers efforts we provide
the routine Print_Inuse_List that gives a report of all the currently active arrays,
slices, and frames at the current moment. A typical output follows:
Arrays:
1 : 3 int32 = 12
1 : 3 int32 = 12
3 : 3 x 4 x 5 int32 = 240
Slices:
1 : (0,0,0) - (2,3,4) int32
Frames:
1 : 8 x 8 x 8 int32 = 12.3Kb
Generalization and Specializations of Arrays: AForms, Matrices, ...
There are a large number of type definitions in the header of this page -- e.g. Matrix,
Vector, etc. -- that are effectively all equivalent to Array.
The intent is to document the kind, type, and/or dimensionality of the array that is
being operated upon. For example, if one sees a routine declaration where the
argument is a Complex_Matrix, then one knows that the argument should be a
FLOAT32_TYPE or FLOAT64_TYPE, 2D array of either PLAIN_KIND or COMPLEX_KIND.
In general, if a routine
takes an argument that can only be a subset of all the possible array types, kinds, and
dimensionalities, then the routine actually checks that the argument meets those constraints
before proceeding, and conversely if it returns such a typed retult, then one can be sure
that it satisfies the constraints of the type name.
In the direction of generalization, note that the key attributes of an array-like object is that
it is an n-dimensional lattice of values of some Value_Type that may be interpreted
specially based on its Array_Kind. In addition to Arrays, Mylib also supports Slices
that are any hyper-rectangular sub-region of an underlying array, and Frames that are
hyper-rectangular shape windows that can be moved over an underlying array (but need not
lie within its lattice). Any routine that takes an Array as a read-only argument could
equally well take a Slice or a Frame as the argument. The union of the three classes
is termed an array form and an AForm class is introduced to model this generalization of
the three base classes. Note carefully that many of the "array" routines on this page have
been generalized to take AForms as arguments. Similarly, note that any routine that takes
an Array as an argument for which only it's elements will be modified (and not it's shape,
type, etc.), could equally well take a Slice as an argument (but not a Frame as a frame
may not lie with the boundary of its underlying array), in which case only the elements of
the underlying array delimited by the slice's hyper-rectangle are modified. The union of
the Array and the Slice classes is termed an array part and an APart type is introduced
to model this genalization. Again, note that many of the "array" routines on this page have been
generalized to take AParts as arguments.
Coordinates
Many if not most Mylib routines address an element of an array with an index directly
into the linear vector pointed at by the data field. But conceptually an address into
an n-dimensional array, is an integer coordinate
(x0,x1...xn)
into the n-dimensional lattice --
[0,dims[0]-1] x [0,dims[1]-1] x ... x [0,dims[n]-1]
-- of the array. In the subsection on the anatomy of an array above we showed how to
map such a coordinate to an index into the data vector, that is, we specified the mapping
Mylib uses to assign lattice positions to linear positions in data's linear vector.
It is clearly conceptually easier for a human being to think in terms of coordinates than
in terms of indices. So Mylib supports the idea of a Coordinate which is itself an
array that is 1-dimensional and of type Dimn_Type (a signed 32-bit integer).
There are routines that create coordinates with specific values and lengths
(Coord, Coord1, Coord2, Coord3, Coord4),
routines that convert coordinates to indices and vice versa
(Idx2CoordA, Idx2CoreA, Coord2IdxA),
routines that add dimensions to a coordinate
(AppendCoord, PrependCoord),
and routines to round real-valued n-dimensional points to the nearest coordinate
(Floor_Coord, Ceiling_Coord, Nearest_Coord).
Coordinates are also used to specify the shape of an array (see AForm_Shape for an
example) and to model offsets relative to a point in an array's n-dimensional lattice
(see Make_Frame for an example). Coordinates are generally short-lived objects and
so the convention is that most routines that recieve coordinates as input parameters,
free or subsume them before returning.
The routines Idx2CoordA and Coord2IdxA convert between coordinates and array indices.
Note carefully that the conversions require a parameter specifying the array in question as
the shape of the array must be known in order to perform the conversion.
As an alternative to always supplying the array as an argument, we maintain a global
current basis which can be set with Set_Coord_Basis or Use_Array_Basis and
retrieved with Get_Coord_Basis. The conversions of Idx2Coord and Coord2Idx (note the
'A' is missing from the names) take place with respect to the current basis. Clearly the use
of the current basis is not re-entrant, but the routines for setting it are thread-safe.
For code that must be re-entrant, you must use Idx2CoordA and Coord2IdxA.
For arrays whose kind is not PLAIN_KIND, one often needs to describe coordinates as if the
special dimension (i.e. the outermost for RGB_KIND and RGBA_KIND, and the innermost for
COMPLEX_KIND) were not present. This is particularly true of drawing routines (see
the Draw module) where a "brush" of kind PLAIN_, RGB_, RGBA_, or COMPLEX_KIND is
being applied to an array of the given kind. We consider such a truncated coordinate a
core coordinate in direct analogy to the idea of the core shape of an array. Many
routines in the library will accept either a core coordinate or a complete coordinate.
In those instances, it is generally the case that:
when a core coordinate is being used as a point, the special dimension is assumed to be 0,
and when being used as a shape or basis, it gets filled in with the width of the special
dimension. Idx2CoreA and Idx2Core convert an array index into a core coordinate
(where any offset in the special dimension is ignored), and Coord2IdxA and Coord2Idx
will accept core coordinates and assume the coorindate for the special dimension is 0.
Note, that Idx2Core requires that the current basis also records the kind of the basis
as well.
Basic Array Routines
Converting an array from one type, kind, and/or scale to another is frequently required.
Convert_Array performs such a conversion generating a new array for the result, whereas
Convert_Array_Inplace does so in the existing memory blocks of the array in question,
increasing the size of said blocks if necessary. Similarly, Convert_Image and
Convert_Image_Inplace convert arrays that are presumed to model an image where the
routine Image_Check will ascertain if a given array is an image.
An array is considered an image if all values are between 0 and
2scale-1−1
for a signed integer array, are all between 0 and
2scale−1
for an unsigned integer array, and between 0. and 1., inclusive, for a floating point array.
There are quite a few routines for performing basic element-by-element functions on an
array. Array_Range computes the range of values in an array, and Scale_Array and
Scale_Array_To_Range offer two ways to scale and offset the values in an array.
Array_Op_Scalar combines every element of an array with a particular scalar value
via any of the ten supported Operators and Array_Op_Array does an element-wise
combination between two arrays. There are also Complex_Op_Scalar, Complex_Op_Array,
and Complex_Op_Complex that require the first argument be a COMPLEX_KIND array and
for these routines the combining is done via complex arithmetic when it makes sense.
Array_Fct_Val replaces each element of an array with a new value that is any caller-defined
function of its current value, while Array_Fct_Idx replaces each element with a caller-defined
function of its coordinate in the array's lattice. Threshold_Array binarizes an array
against a background/foreground threshold value.
Array multiplication and index-table mapping are two operations that can be generalized
to arrays of any dimension provided the innermost dimension of the first array equals the
outermost dimension of the second for multiplication, and the range of values in the first
array equals the innermost dimension of the second for mapping. The routines Array_Multiply
and Apply_Map realize these generalized versions of the operations. For fast matrix
multiplication for linear algebra, one should use Matrix_Multiply in the Linear Algebra
module. On the other hand if you read a color-mapped image in the Image I/O module then
one should use Apply_Map to perform the color mapping if desired.
Finally, there are routines to clip, pad, and downsample an array. They come in a
generator version that makes a new array holding the result
(Clip_Array, Pad_Array, and Down_Sample),
and in-place versions that perform the operation in the memory of the subject array,
expanding said if necessary
(Clip_Array_Inplace, Pad_Array_Inplace, and Down_Sample_Inplace).
One should particularly note that
how an array gets padded is a function of the current boundary effect.
Visible Fields Documentation
Indicates whether an array can be interpreted as an rgb, rgba, or complex array, as opposed
to just an ordinary or plain array.
If an RGB_KIND array, then the outermost dimension is 3 and
(A[0,α],A[1,α],A[2,α])
is an rgb color triple for each index sequence α.
If an RGBA_KIND array, then the outermost dimension is 4 and
(A[0,α],A[1,α],A[2,α],A[3,α])
is an rgba color for each α.
If an COMPLEX_KIND array, then the innermost dimension is 2 and
A[α,0] + [i] A[α,1]
is a complex number for each α.
Specifies the type of the elements of an array which can be one of the ten number types
supported in C.
If the array has integer elements, then this field specifies the number of bits used to
encode the values. It cannot be more than the number of bits in the type. A typical
example where this field comes into play would be 12-bit microscopy data, for which type
would be UINT16_TYPE and scale would be 12. This field only has an effect when
converting an array (e.g. Convert_Array) or when reading or writing the array to a TIFF
file (where only the number of bits per value is read or written).
The number of dimensions of the array.
dims[i] gives the size of the ith dimension of the array for
i from 0 to ndims-1.
The length of the text tag text.
An arbirary text tag for the array. Typically empty, but you can use it to label an array
so you can identify it in a space usage report produced by Print_Inuse_List, or you can
place, say xml-encoded meta-data describing the image acquisition parameters of the microscope
that produced the data. This tag is read and written to and from the JF_TAGGER tag of a
TIFF file for this purpose.
A void pointer to the elements of the array stored as a linear vector.
To obtain a pointer to the appropriate type use one of the routines AUINT8, AUINT16, ...
AFLOAT64 below (these are actually simple macros). The elements are layed out
with dims[0] being the fastest moving dimension, i.e., for an n-dimensional array
the index of
A[xn-1,...,x1,x0]
is
(... (xn-1*dims[n-2] + xn-2)*dims[n-3] + ...)*dims[0] + x0
using Horner's rule.
The total number of elements in the array.
Structure Documentation
Used to serve as a short term construct that can be passed as an array to any routine that
does not modify that array argument. It is just the outer struct of an array object:
the dims vector, data vector, and text tag all point to another array's memory
(so do not modify that array until the Array_Bundle is no longer in use).
This is not often used save for efficiency or simplicity. For example, for a 3D array A
one can get the ith z-plane as an Array_Bundle using Get_Array_Plane
as follows:
Array_Bundle plane;
Range_Bundle range;
...
plane = *A;
Get_Array_Bundle(&plane,i);
Array_Range(&range,&plane);
Used by Array_Range so that it can record the minimum and maximum value seen in the
AForm in question.
This bundle is passed to routines like Region_Extent and SWC_Tree_Extent so that they can
be filled in with the minimum and maximum vectors, min and max, respectively, of the
smallest bounding box that encloses all the elements of the object in question. The type of the
arrays for min and max depends on the routine, e.g. Region_Extent fills in Coordinates
and SWC_Tree_Extent fills in Double_Vectors.
Enumerated Scalars Documentation
Array_Kind | : { PLAIN_KIND, RGB_KIND, RGBA_KIND, COMPLEX_KIND } |
The four supported kinds of an array.
Color_Index | : { RED_INDEX, GREEN_INDEX, BLUE_INDEX, ALPHA_INDEX } |
The indices into the red, green, blue, and alpha sub-arrays of a color array. Primarily
defined for those that wish to write more descriptive code as one can equally well use
0, 1, 2, and 3 as the indices.
Complex_Index | : { REAL_INDEX, IMAG_INDEX } |
The indices for the real and imaginary parts of the innermost dimension of a complex array.
Primarily defined for those that wish to write more descriptive code as one can equally well
use 0 and 1 for this purpose.
Routine Documentation
uint8 |
AUINT8 (Array *a) |
uint16 |
AUINT16 (Array *a) |
uint32 |
AUINT32 (Array *a) |
uint64 |
AUINT64 (Array *a) |
int8 |
AINT8 (Array *a) |
int16 |
AINT16 (Array *a) |
int32 |
AINT32 (Array *a) |
int64 |
AINT64 (Array *a) |
float32 |
AFLOAT32 (Array *a) |
float64 |
AFLOAT64 (Array *a) |
Each function returns a pointer to the data of array a that is of the type implied
by its name. These functions are implemented as macros.
Each function returns a pointer to the data of array a that is of the type implied
by its name. For example, if a is a Coordinate then while one could access its elements
with AINT32(a), it is better to do so with ADIMN(a), as the latter will remain
correct even if the type of Dimn_Type were to change. These functions are implemented as macros.
Creates an array of the given kind, type, and core shape, that is, if kind is other
than PLAIN_KIND, then the shape specified by ndims and dims does not include the extra
dimension for the kind which is automatically added.
Creates an array where the Coordinate shape gives the dimensionality
and size of each dimension of the core shape of the matrix. See Coord for one way to
easily make a shape (e.g. you could write
Make_Array_With_Shape(RGB_KIND,UINT8_TYPE,Coord("4,2,3")).
The shape coordinate is freed before returning.
The parameter arrays is expected to be contain n pointers to arrays that all have the same
type, kind, and shape α. Creates an array with shape
(n,α)
that is the concatenation of the n arrays. The n array objects are unaffected by the
construction as their elements are copied to the new array.
NB: If kind is COMPLEX_KIND then the arrays pointed at must all be of COMPLEX_KIND,
otherwise all the array must be of PLAIN_KIND. Moreover, if
kind is RGB_KIND then n must be 3 and if kind is RGBA_KIND then n must be 4.
Creates an array whose data vector is the one supplied as the last
argument data. The argument conventions are otherwise exactly as for Make_Array.
The data vector must be of size at least size*sizeof(type) bytes and the
memory management of this vector is taken over by the array class.
void |
Set_Array_Text (Array *a M, string text) |
Set the text tag of array a to text.
void |
Append_To_Array_Text (Array *a M, string text) |
Append text to the text tag of array a.
Get the value of the element at coordinate coord in array a. The coordinate coord
is freed upon return and the value is passed back in a Value structure.
Set the value of the element at coordinate coord in array a to v. The coordinate coord
is freed upon return and the value v is passed to the routine in a Value structure.
Select the planeth (n-1)-dimension sub-array of the,
say n-dimensional, Array_Bundle a, which is basically just the outer struct of
an array object, where the dims, data, and text fields point to the memory of some
real array object. A bundle is initialized by assigning it the value of a proper array's
struct. Get_Array_Plane returns a pointer to a after modifying
its fields (in the bundle only) so that it now models the selected sub-array. For example,
the code below, takes the color
array from the example above, and peals off each color sub-array:
Array_Bundle red, green, blue;
red = green = blue = *color;
Get_Array_Plane(&red,0);
Get_Array_Plane(&green,1);
Get_Array_Plane(&blue,2);
If a real independent, and proper object is need for a sub-array then call
Copy_Array on
the fetched plane, e.g. Copy_Array(&red).
Moreover, more than one layer of outer dimensions can be peeled away:
Array_Bundle bundle;
Get_Array_Plane(Get_Array_Plane(&(bundle=*color),1),3);
gets the 3rd z-plane of the green pixels when color
is a 3D RGB_KIND array.
void |
Print_Array (AForm *a, FILE *output, int indent, string format) |
Print an array or slice or frame in a tabular form on the open FILE output. The display
depends on the kind of the array and is indented by indent spaces from the left margin.
The format string must be appropriate for the type of data in the array, e.g. "%10lld"
for an INT64_TYPE array, or "%6.4f" for a FLOAT32_TYPE array.
void |
Print_Inuse_List (FILE *output, int indent) |
Prints out a report of the current set of arrays, slices, and frames currently
in use by the program to the specified output, indented by the amount specified by indent.
The routine expects the string list to be a comma-separated list of integer constants.
The routine generates a coordinate corresponding to the list, e.g.
Coord("3,4,2") produces a 3-element coordinate.
Print the coordinate coord as an comma-separated list of integers to the file f.
Generate a k-element coordinate (d1,d2,d3,...) according to the name of the routine
and the number of its arguments.
Add integer d as the outermost dimension of coordinate coord and return a pointer to
the modified coordinate.
Add integer d as the innermost dimension of coordinate coord and return a pointer to
the modified coordinate.
Generates the coordinate in array a's lattice corresponding to index idx into its
data vector.
Returns the index corresponding to the position of coordinate coord within the lattice of
array a.
Sets the current basis for Mylib to the given shape and kind. Specifying the kind
is important as it affects the operation of Idx2Core which must know if any of the dimensions
of shape are special.
void |
Use_Array_Basis (Array *a) |
Sets the current basis for Mylib to that of the array a.
Generates a coordinate that models the shape of the current basis, and returns
in the value pointed at by kind the kind of the current basis.
Returns the coordinate in the current basis corresponding to index idx.
Returns the index corresponding to the position of coordinate coord within the lattice of
the current basis.
Generates the core coordinate in array a's lattice corresponding to index idx into its
data vector.
Generates the core coordinate in the lattice of the current basis corresponding to
index idx.
Generate the coordinate produced by taking the floor of every element of point.
Generate the coordinate produced by taking the ceiling of every element of point.
Generate the coordinate produced by taking rounding every element of point to the nearest
integer.
Converts the array a to one of the specified kind, type, and scale in a newly generated
array, say t, and returns a pointer to it. The result is as if the assignement
t[i] = Mapping(a[i])*β
were made for each core element (i.e. RGB-triple, complex number, ...) where i ranges over
the core shape of a, Mapping converts between different kinds of elements,
and β is a scaling factor. If the types of a and t are different then the the
right hand side is computed in a's type space and then the type conversion takes place
during the assignment as per C's type rules.
If the kind remains unchanged, the Mapping is the identity fucntion. Otherwise the table
below gives the function implied by each source/target kind pair. The free variable i is
assumed to range over all possible core coordinates of a (and t).
Conversion | Mapping |
PLAIN to RGB |
t[0,i] = t[1,i] = t[2,i] = a[i] |
PLAIN to RGBA |
t[0,i] = t[1,i] = t[2,i] = a[i], t[3,i] = &alpha(t) |
RGB to RGBA |
t[c,i] = a[c,i] for c ∈ {0,1,2}, t[3,i] = &alpha(t) |
RGBA to RGB |
t[c,i] = a[c,i]*a[3,i] / α(a) for c ∈ {0,1,2} |
RGB to PLAIN |
t[i] = .30*a[0,i] + .59*a[1,i] + .11*a[2,i] |
RGBA to PLAIN |
t[i] = (.30*a[0,i] + .59*a[1,i] + .11*a[2,i])*a[3,i] / α(a) |
PLAIN to COMPLEX |
t[i,0] = a[i], t[i,1] = 0 |
COMPLEX to PLAIN |
t[i] = (a[i,0]2 + a[i,1]2).5 |
KIND X to KIND Y |
KIND X to PLAIN to KIND Y |
The last row of the table is intended to capture any conversion not specified in the previous
rows of the table. For example, a COMPLEX_KIND to RGB_KIND transformation is conceptually
the result of first converting the COMPLEX_KIND to a PLAIN_KIND and then converting the
PLAIN_KIND to an RGB_KIND. The quantity &alpha(x) is
(a) 2 x->scale−1 if the type of x is one of the unsigned integer types,
(b) 2 x->scale-1−1 if the type of x is one of the signed integer types,
and
(c) 1 if the type of x is one of the floating point types. Intuitively it is the fully
opaque value for the alpha component of an RGBA_KIND array of the same type as x.
Conceptually after being mapped as per the table above, each value is then scaled by a factor
β except for an alpha component if it has been newly introduced. The value of β
is determined by the parameter factor as follows. If the type of a or the type of t
is a floating point type, then the parameter factor is interpreted as a double value
and it is β. Otherwise, factor is interpreted as an int argument and the value
of β is effectively 2-factor. We say "effectively" because the
multiplication by β is actually accomplished with a left or right bit shift.
The scale of t is simply set to the scale parameter; one must set factor appropriately
if an actually scale change in the value resulting from the kind Mapping is required.
Convert a in the same way as Convert_Array above, but do so in-place, that is, a is
overwritten with the converted result and a pointer to a is returned.
boolean |
Image_Check (Array *a) |
Check whether or not an array is an image.
An array is considered an image if all its values are between 0 and
2 scale-1−1
for a signed integer array, are all between 0 and
2 scale−1
for an unsigned integer array, and between 0. and 1., inclusive, for a floating point array.
Converts an image into one of the given kind, type, and scale in a newly generated array
that is returned as the result. Unlike Convert_Array, values are scaled so that the relative
intensity of a pixel element is preserved. For example, if a has type UINT16_TYPE and scale
12, then
(a) if type is UINT8_TYPE and scale is 8, then values of a will be right-shifted 4 bits,
(a) if type is FLOAT32_TYPE, then values of a will be divided by the floating point value
2 scale−1, and (c) if type is INT32_TYPE and scale is 24, then
the values of a will be left-shifted 11 bits.
Convert image a in the same way as Convert_Image above, but do so in-place, that is, a is
overwritten with the converted result and a pointer to a is returned.
Returns the smallest and largest value in array in the maxval and minval fields of the
Range_Bundle.
APart * |
Scale_Array (APart *a RM, double factor, double offset) |
Each element of a is first ofset by offset and then scaled by factor, i.e.
a[i] = factor * (a[i] + offset) for all i in basis of a.
Scales every element of a so that the largest (after scaling) equals
max and the smallest equals min. Returns a for convenience.
Combines each element in a with the value v of type type according to
the selected Operator op. The table below lists the operational effect. Not carefully that
if a and v are not of the same type, then results are coreced for the operation and
assignment according to the rules of the C-language. v must be a positive integer if either
of the two shift operators is requested.
Operator | Effect |
SET_OP | a[i] = v |
ADD_OP | a[i] = a[i] + v |
SUB_OP | a[i] = a[i] - v |
MUL_OP | a[i] = a[i] * v |
DIV_OP | a[i] = a[i] / v |
POW_OP | a[i] = a[i] ^ v |
LSH_OP | a[i] = a[i] << v |
RSH_OP | a[i] = a[i] >> v |
MIN_OP | a[i] = min(a[i],v) |
MAX_OP | a[i] = max(a[i],v) |
Assumes a is of COMPLEX_KIND and combines each complex element of a with
the complex number v+iw. All arithmetic is done in the field of complex numbers.
However, for the shift and min/max operators, the operations are performed on the real and imaginary
parts separately, e.g. for LSH_OP, a[i].real <<= v and a[i].imag <<= w.
v and w must be positive integers if either of the two shift operators is requested.
Combine, element-wise, the elements of the arrays a and b with Operator op, leaving the
result in the element of a. a and b do not have to be the same size,
type, or kind. If b is larger than a, then the first a->size elements of b are combined
with the elements of a. If b is smaller than a, then the elements of b are used in a
circular fashion until every element of a has been operated upon. This is reflected in the
table below by the use of the expression b[i%|B|] where |B| is, b->size, the size of b.
Operator | Effect |
SET_OP | a[i] = b[i%|B|] |
ADD_OP | a[i] = a[i] + b[i%|B|] |
SUB_OP | a[i] = a[i] - b[i%|B|] |
MUL_OP | a[i] = a[i] * b[i%|B|] |
DIV_OP | a[i] = a[i] / b[i%|B|] |
POW_OP | a[i] = a[i] ^ b[i%|B|] |
LSH_OP | a[i] = a[i] << b[i%|B|] |
RSH_OP | a[i] = a[i] >> b[i%|B|] |
MIN_OP | a[i] = min(a[i],b[i%|B|]) |
MAX_OP | a[i] = max(a[i],b[i%|B|]) |
The effect is similar to Array_Op_Array above except that a must be of COMPLEX_KIND and
each non-complex element of b is combined with each complex element of a and complex
arithmetic is used for all but the shift and min/max operators. To be a bit more precise, if
p is the index corresponding to a core coordinate c of a, then the complex number
a[c,0] + i a[c,1] is combined with b[p%|B|] according to op. For, the
shift and min/max operators, the b-value is applied to both parts of the a-value, e.g.
x+iy << e is (x<<e) + i (y<<e).
The effect is similar to Array_Op_Array above except that a and b must both be of
COMPLEX_KIND and complex arithmetic is used to combine elements except for the shift
and min/max operators which take place on the real and imaginary parts separately, e.g.
x+iy << c+id is (x<<c) + i (y<<d).
For each element of a, the routine calls the handler fct with a void pointer
to the element and replaces the element with whatever Value fct returns.
For each element of a, the routine calls the handler fct with the Coordinate of the
element and replaces the element with whatever Value fct returns.
Binarizes the image with respect to threshold cutoff. That is, every element whose value
is less than or equal to cutoff is set to 0, and every element other element is set to 1.
Multiply arrays a and b where they must both be of the same type and the innermost
dimension of a must be of the same length as the outermost dimension of b. If either
a or b is of COMPLEX_KIND then complex arithmetic is performed and a COMPLEX_KIND
array is returned. The kind of the arrays is otherwise ignored and a PLAIN_KIND array
returned.
The routine handles all type situations and complex multiplication and is therefore not
as efficient as the carefully-crafted Matrix_Multiply routine in the Linear Algebra
module for multiplying Double_Matrixes together.
A general routine for mapping array data, but specifically inspired by image "color maps".
The array image must be of PLAIN_KIND and unsigned integer type. The array map must
have dimension at least 1 and its inner dimension must be equal to m =
2 image->scale, i.e. the range of values in image. Suppose the shape
of map is (α,m). Each value v in image is replaced with the *array*
map[β,v]β of shape α.
Thus the resulting array is of shape α.shape(image) and has the type and scale of map.
A new array is created to hold the result and a pointer to it is returned.
Downsample array source where the downsampling in each dimension is given by box.
For example, Coord("2,3,4"), would downsample a 3 dimensional array by
4 pixels in dimension 0, 3 pixels in dimension 1, and 2 pixels in dimension 2. If the
array is RGB_KIND, RGBA_KIND, or COMPLEX_KIND then the downsample vector need only
specify the downsampling in the core shape, in which case the downsampling in the special
dimesnion is assumed to be 1 (i.e. no downsampling). A pixel in the result is the average
of the pixels it replaces. A new array is generated for the result and a pointer to it
returned.
Select the subset of source in the rectangle whose opposing corners are at the
coordinates beg and end. For example, if beg = (2,4,3) and end = (6,7,8) then the
sub-array source[2..6][4..7][3..8] will be returned. If the array is RGB_KIND,
RGBA_KIND, or COMPLEX_KIND, then one is free to use core coordinates as well, in which
case the entire range of the special dimension is assumed.
Place the array source in a padded array of shape shape where its origin (index 0 pixel)
is placed at coordinate anchor in the padded array. shape must be not smaller than the shape
of source in every dimension. The padded array is padded according to the
current boundary effect. (NB: Padding with zero's is the most efficient, the other
padding effects take an extra pass over the boundary pixels.)
If the array is RGB_KIND, RGBA_KIND, or COMPLEX_KIND, then shape and anchor
can be a core shape and core coordinate, in which case the special dimension is not
padded and the origins of the special dimension are aligned.
Same effect as Down_Sample except that it only applies to Arrays and modifies source
to hold the downsampled result and returns a pointer to source.
Be sure to pack the array
Pack_Array)
if you want to free up the space no longer
required by the downsampled array.
Same effect as Clip_Array except that it only applies to Arrays and modifies source
to hold the clipped result and returns a pointer to source.
Same effect as Pad_Array except that it only applies to Arrays and modifies source
to hold the padded result and returns a pointer to source.
|