IOLink  IOL_v1.1.0_release
View concept

A View is the main entry point to use IOLink in order to access to data. For this reason, its concept must be detailed.

View

Basically, views point toward a data, whatever its origin, as long as it is accessible.

A view points toward one data

This data can be local or remote, on disk or in memory.

Multiple views can point toward the same data without duplication.

Many views can point toward the same data

A View can also point toward a data contained in file. Data are accessible directly from the file, without copy in memory (but low performance). It can be useful to read a small part of a huge file.

A view can point toward one file content

A view can point toward a remote data, identified by an URI (Uniform Resource Identifier). A HTTP connexion is setup with remote server at view creation but no data will be exchanged before any operations on the view.

A view can point toward one remote file data

According to data type, you can specialize your view to get type-specific informations. Let's take the case of images.
Your View object can be casted into an ImageView. If the cast is not possible, it means your view is not an image.

An ImageView points toward an image data

A view is strongly linked to a data (local in ram, on disk, in a file, or remote), and follows the RAII idiom (Resource Acquisition Is Initialization). Which means the memory allocated at view creation will be deallocated at view destruction, file opened at view creation will be closed at destruction, etc.

As views are always exchanged through shared pointers, many users can share the same views, and the associated data will be released once nobody use it any longer.

View characteristics

Image view

Thus you have access to your data as an Image.
This image can have multiple dimensions:

  • 2 dimensions for simple image (width and height)
  • 3 dimensions for volume (width, height and depth), video (width, heigh, time series), or else ...
  • 4 dimensions for animated volume (width, height, depth, time series), ...

You have access to basic informations like:

  • number of dimensions
  • shape of the image (size in any dimensions)
  • pixel type (i.e. U8: unsigned-8-bit integer for grayscale images)
Definition or origin, pixel type, shape and dimensions

From ImageView object, you have no access to the image content. You must require the specific capacity: READ. Multiple capacities are available for ImageView and it depends on the data origin.

For example, if the data is a read-only file content, the READ capacity will be the only available one. On the other hand, an in-memory image will have all the capacities:

  • READ (image can be read)
  • WRITE (image can be modified)
  • RESHAPE (image can be resized, and number of dimensions can be changed)
  • BUFFER (you can get a direct pointer on the image data)

ImageView on disk

IOLink provides factories to handle an ImageView onto disk. The difference with the ImageView is that you don't have any RAW-access to data.

You can allocate an ImageView on disk or decide to create a copy of an existing ImageView (in-memory, whatever..) on disk. Performances will be decreased but it will allow to work more easily in memory-limited environments.

Read image content

When you have READ capacity, you can now read value from a single pixel or pixel values from a complete region.

Pixels are read as following:

Reading order of pixels

Read method

By default, IOLink method to read images is row-major order, which means in IOLink that the first dimension of images is read first.

row and column major distinction

Dimensions

IOLink etablishes a convention of priority for dimension order:

  • COLUMN or image width
  • ROW or image height
  • SLICE or image depth
  • CHANNEL
  • SEQUENCE of time or not

COLUMN dimension has always priority over ROW, which has priority over SLICE, etc.

Dimensions cannot be inverted in your image, but according to your need, some can be dropped:

  • image :
    • Dimension 0: COLUMN
    • Dimension 1: ROW
  • volume:
    • Dimension 0: COLUMN
    • Dimension 1: ROW
    • Dimension 2: SLICE
  • images sequence:
    • Dimension 0: COLUMN
    • Dimension 1: ROW
    • Dimension 2: SEQUENCE
  • animated volume:
    • Dimension 0: COLUMN
    • Dimension 1: ROW
    • Dimension 2: SLICE
    • Dimension 3: SEQUENCE
  • multi-channel image
    • Dimension 0: COLUMN
    • Dimension 1: ROW
    • Dimension 2: CHANNEL

Some pre-defined image interpretations are available in ImageTypeId class.

Image Types available in IOLink

Adapting ImageView

Anytime a new view is created from another one (except for densification case) for adaptation or transformation, no duplication of data is done. An implicit adapter is applied on the original view to make the new view fit your needs.

Region adapter is an example of useful adaptation.

Region ImageView

A view can point toward a part of the same image. A new view must be created from original one using the ImageViewFactory. By handling this new ImageView, it will be like pointing toward a smaller image.

For example, in the following figure, ImageView 2 is created from original ImageView, with a region defined by its origin and its shape.

Example of regions in a 2 dimensional image

It can also permit interesting data descrimination.

Example of regions in a 3 dimensional image

In this last image, you have the example of ImageView 3 and ImageView 4 which points toward the same region (a slice), but first ImageView remains a 3-dimensional image (with a flat second dimension) while second one is considered as a 2-dimensional image (the flat dimension has been removed).

Just to make it clear, and as said before, creating a region view from another one does not imply any memory duplication.

Change ImageView pixel type

From an original view with a certain pixel type, it is possible to create another view with a different pixel type.

For example, from a view onto a grayscale image with pixel type is U8 (unsigned char type), you can create a new view onto a RGB888 image which will point toward the same data.

Or the opposite, from a RGB image view, you can create a grayscale view.

At reading, original pixel samples are transformed to match the new type, and at writing, given pixels samples are transformed to match the original type. Transformations can imply some local data duplication.

In the following table are given details of some typical transformations (all transformations are not listed):

Original Pixel Type Destination Pixel Type Sample transformation Comment
UINT8 INT8 (X) --> (X') X is remapped from [0,255] into [-127, 127]
UINT8 VEC3_UINT8 (X) --> (X,X,X) X is duplicated 3 times
INT16 FLOAT (X) --> (X') X is remapped from [-32767, 32767] into [0.0, 1.0]
DOUBLE UINT8 (X) --> (X') X is remapped from [0.0, 1.0] into [0, 255]
VEC3_UINT8 VEC2_UINT16 (X, Y, Z) --> (X', Y') Z is skipped, X and Y are remapped from [0, 255] into [0, 65536]

Isolate a channel

From an original ImageView with a complex pixel type (at least 2 channels: GRAYSCALE and ALPHA for example), you can ask to isolate one particular channel in another view. The result would be a new ImageView, with same shape than the original, but with datatype reduced to its scalar value.

e.g.

Isolate one channel:

  • ImageView VEC3_UINT8 => ImageView UINT8
  • ImageView VEC4_FLOAT => ImageView FLOAT
  • ImageView UINT16 => same ImageView UINT16

Data densification

Each adaptation applied on a view to create a new one can imply some performance reduction, or capacity restriction (i.e. a region view created from an in-memory view won't have raw-access capacity, since data are not necessarly contiguous in memory anymore). You can also have a view toward a remote file with low-performances access.

To solve this problem, you can decide to require data densification, in order to get performance back, and to fully work in-memory (and retrieve raw-access capacity).

A copy in memory method in ImageViewFactory permits to load your view in local memory. Any adaptation applied on the original view will be definitely applied on the final view.

e.g. if you decide to densify a region view (a small part of a larger image), only the region will be copied into local memory

Applying this densification onto an already In-memory view won't have any effect.

Thread safety

A specific adapter can be applied on an ImageView to add locks on every methods, so as to make it compatible with multithreaded environments.

See factory method for more details. The performance overhead should be limited and capabilities on original ImageViews are kept.

By default, views are not threadsafe.

Multi-ImageView

A view can point toward multiple ImageViews. This is a simple way to handle a stack of images. MultiImageView object aggregates ImageViews with heterogenous properties (Pixel Type, dimensions, shape)

MultiImageView principle

Stacking

Specific method in ImageViewFactory permit to stack N-dimension-images into a N+1-dimension-image (shape and pixel type of any ImageViews must be equal).

Stacking a multiImageView

As already explained, IOLink follows a convention for dimension order. This can have impact on the stack operation in the case where the added dimension is named by the user, and is not in last position in the created object.

For example:

A user handles a MultiImageView containing a set of 1000 ImageViews which are known as IMAGE_SEQUENCE (thus, with COLUMN, ROW and SEQUENCE dimensions, in this order).

// shape of each ImageView contained in the MultiImageView
shape = { 640, 480, 700 }
640 -> COLUMN dimension size
480 -> ROW dimension size
700 -> SEQUENCE dimension size

All these IMAGE_SEQUENCE images could represent a volumetric sequence. Consequently, the user wants to stack all these ImageViews to obtain an unique VOLUME_SEQUENCE object. The added SLICE dimension is added before the SEQUENCE dimension, in IOLink convention.

// final ImageView after stacking
// new SLICE dimension is added before the SEQUENCE dimension
shape = { 640, 480, 1000, 700 }

Un-Stacking

It is also possible to unstack a N-dimension-image into N-1 images.

Unstacking into a multiImageView

Deinterlace an ImageView

As previously seen, it is possible to isolate a channel from an ImageView to get a new ImageView. Thus it is also possible to entirely deinterlace an ImageView to obtain a MultiImageView which will contain one ImageView for each original channel.

Deinterlacing an ImageView

A deinterlace method from *MultiImageViewFactory** creates this MultiImageView from any ImageView with a complex datatype (at least 2 channels).

Interlace a MultiImageView

It is also possible to do the opposite. Starting from a MultiImageView containing many frames of same shape and datatype (one for each channel), and interlacing these frames to create an ImageView.

Interlacing a MultiImageView

A interlace method from MultiImageViewFactory creates this ImageView from a MultiImageView whose frames only contain one channel.

Disassemble and Assemble an ImageView

It is possible to deinterlace a N-dimension ImageView (with a vectorial-typed sample) so as to create a N+1 dimension ImageView. A new CHANNEL dimension is created.

e.g.: a RGB ImageView (COLUMN, ROW) will become a RGB ImageView (COLUMN, ROW, CHANNEL)

It is also possible to interlace a N-dimension ImageView (with a CHANNEL dimension) so as to create a N-1 dimension ImageView. CHANNEL dimension is removed.

e.g.: a RGB ImageView (COLUMN, ROW, CHANNEL, SEQUENCE) will become a RGB ImageView (COLUMN, ROW, SEQUENCE)

Disassembling and assembling a MultiImageView

Remark: disassembling could also be done using deinterlacing then stacking methods to create the CHANNEL dimension.

Sub-Sample an ImageView

IOLink provides a way to generate a sub-sampled version of an ImageView. It is a simple method to reduce the ImageView shape by picking only one sample every X samples (X is configurable) in every dimensions.

LodImageView

This LodImageView ("Lod" for "Level Of Definition") is a container of ImageViews, specialized to handle different resolutions of the same image. This allows to have a version of your dataset for any situation:

  • a low-level-resolution version for a quick load and limited ressources
  • many medium-level-resolution versions for intermediate work
  • a high-level-resolution for accurate work, longer to load but will full original details
Different Levels of Definition

Methods provided in the LodImageView interface allow to handle these different LOD images as a pool of ImageView.

Regions of Interest