module Raster:`sig`

..`end`

Raster data.

**WARNING.** This interface is subject to change in the future.

Raster data organizes data samples of any dimension in discrete 1D, 2D (images) or 3D space.

A sample has a *semantics* that defines its
dimension and the meaning of its *components*. For example a 4D
sample could represent a linear sRGBA sample. Samples are stored
in a linear buffer of *scalars* of a given
type. A sample can use one scalar per component,
can be packed in a single scalar or may have no direct obvious
relationship to buffer scalars (compressed data). The
sample format defines the semantics and
scalar storage of a sample.

A *raster data* value is a collection of samples indexed
by width, height and depth (i.e. x, y, z) stored in a buffer. It
defines the sample data, the extents of the index and the sample
format. The optional resolution in samples per meters of
a raster data can specify its physical dimension.

**Spatial convention.** If the sample index has to be interpreted
spatially. It must be interpreted relative to the origin of a
right-handed coordinate system. This means that the first sample,
indexed by `(0,0,0)`

is the bottom-left backmost sample
(bottom-left sample for a 2D image).

**Index sizes.** Index sizes are specified using
size types which are made of floats as it is more
pratical in most scenarios. These floats should however be * integral* floats. The function `Gg.Raster.v`

, `Gg.Raster.Sample.scalar_count`

and `Gg.Raster.sub`

ensure this by applying `Gg.Float.round`

to these values.
This means that the raster size functions when called with
`meters = false`

will always return sizes that are integral floats that
you can convert to integers safely without having to think about
rounding issues. Note also that index sizes are always strictly
positive.

module Sample:`sig`

..`end`

Sample semantics and formats.

type`t =`

`Gg.raster`

The type for raster data.

`val v : ``?res:Gg.v3 ->`

?first:int ->

?w_stride:int ->

?h_stride:int ->

[ `D1 of float | `D2 of Gg.size2 | `D3 of Gg.size3 ] ->

Sample.format -> Gg.buffer -> t

`v res first w_stride h_stride size sf buf`

is raster data with
sample format `sf`

and buffer `b`

.
`size`

, specify the index extents. height and depth if unspecified default to`1`

. All extents must be strictly positive.`first`

,*buffer scalar*index where the data of the first sample is stored.`w_stride`

, number of*samples*(**not**buffer scalars) to skip to go from the first sample of a line to the first sample of the next line. Defaults to the index width.`h_stride`

, number of*lines*to skip to go from the first line of a plane to the first line of the next plane. Defaults to the index height.`res`

, is an optional sample resolution specification in samples per meters.

For certain sample formats `first`

, `w_stride`

and `h_stride`

can be
used to specify subspaces in the collection of samples, see `Gg.Raster.sub`

.

The function `Gg.Raster.scalar_strides`

can be used to easily compute the
linear buffer scalar index where a sample `(x,y,z)`

starts.

**Raises** `Invalid_argument`

if the elements of `size`

are not stricly
positive, if `first`

is negative, if `w_stride`

or `h_stride`

are
smaller than the index width or height or if the scalar type of
`sf`

doesn't match `(Raster.buffer_scalar_type b)`

.

`val res : ``t -> Gg.v3 option`

`res r`

is `r`

's resolution in sample per meters, if any.`val get_res : ``t -> Gg.v3`

`val first : ``t -> int`

`first r`

is the `val w_stride : ``t -> int`

`w_stride r`

is the number of `val h_stride : ``t -> int`

`h_stride r`

is the number of `val sample_format : ``t -> Sample.format`

`sample_format r`

is `r`

's sample format.`val buffer : ``t -> Gg.buffer`

`buffer r`

is `r`

's format.
In these functions have an optional `meter`

argument that
defaults to `false`

. If `false`

the result is in integral number
of *samples*. If `true`

the result is in *meters* according
to the rasters' resolution. If the raster has no
resolution, `Gg.Raster.res_default`

is used in all dimensions.

`val wi : ``t -> int`

`wi r`

is `r`

's index width in number of samples.`val hi : ``t -> int`

`hi r`

is `r`

's index height in number of samples.`val di : ``t -> int`

`d r`

is `r`

's index height in number of samples.`val w : ``?meters:bool -> t -> float`

`w r`

is `r`

's index width.`val h : ``?meters:bool -> t -> float`

`h r`

is `r`

's index height.`val d : ``?meters:bool -> t -> float`

`d r`

is `r`

's index depth.`val size1 : ``?meters:bool -> t -> Gg.size1`

`size1 r`

is `r`

's index width.`val size2 : ``?meters:bool -> t -> Gg.size2`

`size2 r`

is `r`

's index width and height.`val size3 : ``?meters:bool -> t -> Gg.size3`

`size3 r`

is `r`

's index width, height and depth.`val box1 : ``?meters:bool -> ?mid:bool -> ?o:float -> t -> Gg.box1`

`box1 meters mid o r`

is a box with origin `o`

and size ```
(size1
meters r)
```

. If `mid`

is `true`

(defaults to `false`

), `o`

specifies the mid point of the box. `o`

defaults to 0.`val box2 : ``?meters:bool -> ?mid:bool -> ?o:Gg.p2 -> t -> Gg.box2`

`box2 meters mid o r`

is a box with origin `o`

and size ```
(size2
meters r)
```

. If `mid`

is `true`

(defaults to `false`

), `o`

specifies the mid point of the box. `o`

defaults to `Gg.P2.o`

.`val box3 : ``?meters:bool -> ?mid:bool -> ?o:Gg.p3 -> t -> Gg.box3`

`box3 meters mid o r`

is a box with origin `o`

and size
`(size3 meters r)`

. If `mid`

is `true`

(defaults to `false`

),
`o`

specifies the mid point of the box. `o`

defaults to `Gg.P3.o`

.`val dim : ``t -> int`

`dim r`

is `r`

's index dimension from 1 to 3. Note that
this is not derived from the case size given to `Gg.Raster.v`

for creating `r`

.
It is derived from the size `(w,h,d)`

as follows: `(w,1,1)`

means 1,
`(w,h,1)`

with `h > 1`

means 2, `(w,h,d)`

with `h,d > 1`

means 3.`val kind : ``t -> [ `D1 | `D2 | `D3 ]`

`val sub : ``[ `D1 of Gg.box1 | `D2 of Gg.box2 | `D3 of Gg.box3 ] ->`

t -> t

`sub region`

is a raster corresponding to a subset of the
index of `r`

. Both `r`

and the resulting raster share
the same buffer. The integral origin of the box defines the
new sample origin of the raster data and its integral
size the new size of the index.
If the dimension of the box is smaller than the raster the
result is in the first line (`y = 0`

) and/or layer (`z = 0`

) of
the raster `r`

.

**Raises** `Invalid_argument,`

if the sample format of `r`

is packed,
if the origin is out of bounds or if new size is larger than
`r`

's size.

`val scalar_strides : ``t -> int * int * int`

`scalar_strides r`

is `(x_stride, y_stride, z_stride)`

where
`x_stride`

is the number of buffer scalars from sample to sample.`y_stride`

is the number of buffer scalars from line to line.`z_stride`

is the number of buffer scalars from plane to plane.

`(x,y,z)`

starts is given by:
```
(Raster.first r) + z * z_stride + y * y_stride + x * x_stride
```

`Invalid_argument`

if the sample format of `r`

is
packed.`val equal : ``t -> t -> bool`

`equal r r'`

is `r = r'`

.`val compare : ``t -> t -> int`

`compare r r'`

is `Pervasives.compare r r'`

.`val pp : ``Format.formatter -> t -> unit`

`pp ppf t`

prints a textual represenation of `t`

on `ppf`

. Doesn't
print the buffer samples.`val res_default : ``float`

`res_default`

is 11811spm (300spi).`val spm_of_spi : ``float -> float`

`spm_of_spi spi`

is the samples per meter corresponding to
the samples per inch `spi`

.`val spm_to_spi : ``float -> float`

`spm_to_spi spm`

is the samples per inch corresponding to the
samples per meters `spm`

.