ImFusion C++ SDK 4.5.0
ImFusion::SharedImage Class Reference

#include <ImFusion/GL/SharedImage.h>

Image shared on multiple devices. More...

Detailed Description

Image shared on multiple devices.

This class aids in resource synchronization between CPU and different GPU APIs. It is constructed with a derived image instance either in memory or one of the graphics APIs, an empty base descriptor class is not allowed. In addition to the built-in representations such as MemImage and GlImage it also supports custom representations provided by plugins through the CustomImage interface.

Internally, for each image representation, a shared pointer is held. Synchronization is fully encapsulated and will be performed even on const instances of this class because mere synchronization between devices does not modify the semantic content of an image.

For individual image access, adhere to the following guidelines:

  1. Use descriptor() or img() to obtain a const image descriptor regardless of the image location.
  2. Use sharedMem(), sharedGl(), and sharedCustom<T>() for getting a shared_ptr to the respective image. If the desired representation is absent or outdated, it will be synchronized, even if the method is called on a const object. Thus, make sure to call these methods only if synchronization is allowed, for instance with a valid GL context when calling sharedGl().
  3. The same holds for methods mem(), gl(), and custom<T>(), which return non-owning raw pointers held by sharedMem(), sharedGl(), and sharedCustom<T>() respectively.
  4. Use hasMem(), hasGl(), hasCustom<T>() to check for an up-to-date representation while making sure that no synchronization is performed. The returned shared_ptr implicitly casts to bool. Furthermore, it allows for working and to work with the potentially available representation in a thread-safe way. If you use SharedImage in a multi-threaded environment, do not: if (img.hasGl()) { auto gl = img.gl(); // wrong, could have been overridden in other thread since hasGl() ... } but instead: if (auto gl = img.hasGl()) { // correct, guaranteed to return either valid image or nullptr ... }
  5. If you change the image in one representation, e.g. in memory, make sure to call setDirtyMem(), setDirtyGl(), setDirtyCustom<T>(), so that all other representations are marked as outdated.
  6. Explicitly call makeExclusive() to remove all representations except one from this container. This might be useful for memory management, e.g. to free GL textures.
Warning
By definition a GlImage can not store more than 4 channels (this is a general limitation of OpenGL). SharedImage will deal with this as follows: When syncing a MemImage -> GlImage, the GL representation will only contain the first 4 channels, any extra channels will be discarded. Subsequent calls to setDirtyGl() will not have any effect but only issue a warning because the GlImage is incomplete, and you would lose data otherwise. If you nevertheless want to sync back to MemImage, you need to do this manually to acknowledge that you may lose data. You can do this for instance by using GlImage::download() to create a MemImage followed by SharedImage::assign() or SharedImage::update().
See also
Using Image Data

Classes

struct  Representation

Public Types

enum  CloneOptions { Everything = 0 , NoMask = 1 << 0 , NoDeformation = 1 << 1 , ShallowImageCopy = 1 << 2 }
 Bitset enumeration to configure which aspects of a SharedImageSet to copy. More...

Public Member Functions

 SharedImage (std::shared_ptr< Image > img)
 Creates a new SharedImage wrapping the given image.
template<typename T>
 SharedImage (TypedImage< T > &&img)
 Creates a new SharedImage by moving the given TypedImage in.
 SharedImage (GlImage &&img)
 Creates a new SharedImage by moving the given GlImage in.
 SharedImage (const ImageDescriptor &descriptor)
 Convenience overload to create a new SharedImage holding a MemImage as described by the ImageDescriptor.
 SharedImage (const ImageDescriptorWorld &descriptorWorld)
 Convenience overload to create a new SharedImage holding a MemImage as described by the ImageDescriptorWorld.
 SharedImage (const SharedImage &otherSharedImage)
 Copy constructor performs a deep copy of the underlying image data.
 SharedImage (const SharedImage &otherSharedImage, Flags< CloneOptions > copyOptions)
 Copy constructor variant that also allows for partial copies.
 SharedImage (SharedImage &&otherSharedImage)
 Move constructor will move all contents from otherSharedImage.
SharedImageoperator= (const SharedImage &otherSharedImage)
 Assignment will perform a deep copy of the underlying image data.
SharedImageoperator= (SharedImage &&otherSharedImage)
 Move assignment will move all contents from otherSharedImage.
virtual std::unique_ptr< SharedImageclone (Flags< CloneOptions > cloneOptions=Everything) const
 More flexible version of the copy constructor that also allows for partial copies.
virtual std::unique_ptr< SharedImagecloneWithImage (std::shared_ptr< Image > img, Flags< CloneOptions > cloneOptions=Everything) const
 Same as clone() but uses the given image instead of copying from this.
Image::Location location () const
 Specifies the original location of the image.
const Imageimg () const
 Return the image descriptor of the currently up-to-date location.
const ImageDescriptordescriptor () const
 Return the image descriptor of the currently up-to-date location.
ImageDescriptorWorld descriptorWorld () const
 Return the world image descriptor of the currently up-to-date location.
bool assign (std::shared_ptr< Image > img)
 Set img as new main image representation and set the dirty flag accordingly.
bool update (const MemImage &img)
 Update the MemImage and set the dirty flag so that the next OpenGL access will upload this image.
bool update (const GlImage &img)
 Update the GlImage and set the dirty flag so that the next CPU access will download this image.
void prepare (bool shiftOnly=false)
 Prepare the image in memory for most common scenarios Integral types are converted to unsigned representation if applicable, double-precision will be converted to single-precision float.
void sync () const
 Synchronize both MemImage and GlImage representations, shorthand for calling both syncMem() and syncGl().
void syncMem () const
 Synchronize MemImage, creating it if it does not exist.
template<typename T>
void syncCustom () const
 Synchronize a custom image type where T must inherit the CustomImage interface, creating it if it does not exist.
void syncGl () const
 Synchronize OpenGL image, creating it if it does not exist.
void setDirtyMem ()
 Manually label MemImage as dirty (i.e.
bool setDirtyGl ()
 Manually label GlImage as dirty (i.e.
template<typename T>
void setDirtyCustom ()
 Manually label custom image type T as dirty (i.e.
bool makeExclusive (Image::Location location) const
 Synchronizes the given location and deletes all other representations stored to free memory.
template<typename T>
bool makeExclusive () const
Data::Kind kind () const
 Return the data kind of the base interface.
Geometry::AlignedBox bounds () const
 Returns the axis-aligned bounding box of the unmasked and undeformed image in world space.

Public Attributes

Signal< const SharedImage * > signalChanged
 Called when the content of a SharedImage has changed (every time one of the setDirty() methods has been called).
Signal< const SharedImage * > signalDeformationChanged
 Called when a Deformation object is assigned or removed from the SharedImage.
Signal< const SharedImage * > signalMaskChanged
 Called when a Mask object is assigned or removed from the SharedImage.
Signal< const SharedImage * > signalDeleted
 Called when this instance is deleted.

Protected Types

using CreateImageFromMemFunction = std::shared_ptr<Image> (*)(const std::shared_ptr<const MemImage>&)

Protected Member Functions

virtual void cloneMetadata (const SharedImage &metadataSource, Flags< CloneOptions > cloneOptions)
 Copies modality, matrix, and optionally mask and deformation from metadataSource into this.
void validateMask ()
 Removes the mask if it is no longer compatible with the image.
bool checkConsistency () const
 Checks the internal state for consistency between all image representations.
std::shared_ptr< ImagesharedImageImpl (const std::type_index &imageType, CreateImageFromMemFunction createFromMem)
 Returns a shared_ptr to the requested image representation, synchronizing or creating it if needed.
std::shared_ptr< const ImagesharedImageImpl (const std::type_index &imageType, CreateImageFromMemFunction createFromMem) const
 Returns a shared_ptr to the requested image representation, synchronizing or creating it if needed.
std::shared_ptr< ImagehasImageImpl (const std::type_index &imageType)
 Returns a shared_ptr to the requested image representation if it exists and is up-to-date, without synchronizing.
std::shared_ptr< const ImagehasImageImpl (const std::type_index &imageType) const
 Returns a shared_ptr to the requested image representation if it exists and is up-to-date, without synchronizing.
virtual Representation syncImpl (const std::type_index &imageType, CreateImageFromMemFunction createFromMem) const
 Ensures the requested image representation is up-to-date, synchronizing or creating it if necessary.
void setDirtyImpl (const std::type_index &imageType)
 Marks the requested image representation as the main one and all others as dirty.
virtual bool makeExclusiveImpl (const std::type_index &imageType, CreateImageFromMemFunction createFromMem) const
 Makes the requested image representation the only one stored, removing all others.
Representation findRepresentation (const std::type_index &imageType) const
 Finds the representation for the given image type.
virtual Representation addOrReplaceRepresentation (const std::type_index &imageType, std::shared_ptr< Image > img, bool isDirty) const
 If the representation for the given image type exists, it is replaced with img, otherwise img is added as new representation.
virtual void representationAccessed (const std::type_index &imageType, const Representation &representation) const
 Internal method to allow observers to track representation accesses.
virtual void rawPointerAccessed () const
 Internal method to allow observers to track raw pointer accesses (mem(), gl(), custom(), etc.). No-op per default.

Static Protected Member Functions

static std::type_index constrainedTypeIndex (const Image &image)

Protected Attributes

Data::Modality m_modality = Data::NA
 Image modality.
mat4 m_matrix = mat4::Identity()
 The optional image matrix.
std::shared_ptr< Deformationm_deformation
 Optional non-linear transformation.
std::shared_ptr< Maskm_mask
 Optional mask.
std::vector< Representationm_images
 List of Image representations.
Imagem_mainImage = nullptr
bool m_glImgHasStrippedChannels = false
 Indicates that the GL representation was created from an image with > 4 channels.
Geometry::AlignedBox m_bounds
 Cached version of the axis-aligned bounding box in world space.
bool m_boundsDirty = true
 Flag whether m_bounds needs to be recomputed.

Access to direct members of SharedImage

void setModality (Data::Modality m)
 Set image modality.
Data::Modality modality () const
 Return the modality of this data.
void setMask (std::shared_ptr< Mask > mask)
 Sets a mask for this image.
std::shared_ptr< Maskmask () const
 Returns the mask for this image.
void setDeformation (std::shared_ptr< Deformation > def)
 Sets a deformation for this image.
std::shared_ptr< Deformationdeformation () const
 Returns the deformation for this image or nullptr if no deformation is set.

Query an up-to-date representation.

These functions will always perform an implicity synchronization if needed. Use hasMem() to check if synchronization is required or to obtain an already existing image without synchronization.
std::shared_ptr< MemImagesharedMem ()
 Returns the image in memory.
std::shared_ptr< const MemImagesharedMem () const
std::shared_ptr< GlImagesharedGl ()
 Returns the image as OpenGL texture.
std::shared_ptr< const GlImagesharedGl () const
template<typename T>
std::shared_ptr< T > sharedCustom ()
 Returns the image as custom image type, where T must inherit the CustomImage interface.
template<typename T>
std::shared_ptr< const T > sharedCustom () const
MemImagemem ()
 Returns the image in memory.
const MemImagemem () const
GlImagegl ()
 Returns the image as OpenGL texture.
const GlImagegl () const
template<typename T>
T * custom ()
 Returns the image as custom image type, where T must inherit the CustomImage interface.
template<typename T>
const T * custom () const

Query whether an up-to-date representation is present and return it.

If a nullptr is returned this indicates that a sync would be required. Use sharedMem() or mem() if implicit synchronization is desired. The returned shared pointer implicitly casts to bool, so you can use it as follows:
if (auto mem = img.hasMem())
...
const Image * img() const
Return the image descriptor of the currently up-to-date location.
MemImage * mem()
Returns the image in memory.
std::shared_ptr< const MemImagehasMem () const
 Query whether an up-to-date memory image is present.
std::shared_ptr< MemImagehasMem ()
std::shared_ptr< const GlImagehasGl () const
 Query whether an up-to-date OpenGL image is present.
std::shared_ptr< GlImagehasGl ()
template<typename T>
std::shared_ptr< T > hasCustom ()
 Query whether an up-to-date image of the requested type is present, where T must inherit the CustomImage interface.
template<typename T>
std::shared_ptr< const T > hasCustom () const

Image matrix access

By convention this matrix transforms world coordinates to image coordinates.

See also
Coordinate Systems
void setMatrix (const mat4 &m)
 Sets the transformation matrix from world space to image space.
const mat4 & matrix () const
 Returns the transformation matrix from world space to image space.
mat4 matrixToWorld () const
 Returns the transformation matrix from image space to world space.
void setMatrixToWorld (const mat4 &value)
 Sets the transformation matrix from image space to world space.
const mat4 & matrixFromWorld () const
 Returns the transformation matrix from world space to image space.
void setMatrixFromWorld (const mat4 &value)
 Sets the transformation matrix from world space to image space.

Convenience functions for coordinate transformations of images

vec3 pixelToWorld (const vec3 &pixel) const
 Convert a 3D pixel/voxel position to world coordinates taking into account the image matrix.
vec3 worldToPixel (const vec3 &world) const
 Convert 3D world coordinates to pixel/voxel position taking into account the image matrix.
mat4 pixelToWorldMatrix () const
 Returns a 4x4 matrix to transform from image pixel space to world space.
mat4 worldToPixelMatrix () const
 Returns a 4x4 matrix to transform from world space to image pixel space.
mat4 textureToWorldMatrix () const
 Returns a 4x4 matrix to transform from texture space to world space.
mat4 worldToTextureMatrix () const
 Returns a 4x4 matrix to transform from world space to texture space.
mat4 textureToImageMatrix () const
 Returns a 4x4 matrix to transform from texture space to image space.
mat4 imageToTextureMatrix () const
 Returns a 4x4 matrix to transform from image space to texture space.

Convenience functions to access underlying image descriptor directly

int width () const
 Return the width of the base interface.
int height () const
 Return the height of the base interface.
int slices () const
 Return the number of slices of the base interface.
int channels () const
 Return the number of channels of the base interface.
vec3 spacing () const
 Return the image spacing.
void setSpacing (const vec3 &spacing)
 Set the image spacing on all existing image representations.
void setSpacing (const vec3 &spacing, bool metric)
 Set the image spacing on all existing image representations, and whether the spacing is metric.
int dimension () const
 Return the image dimensions.
vec3i dimensions () const
 Return the image dimensions.
size_t size () const
 Return the image size.
vec3 extent () const
 Return the image extent.

Member Enumeration Documentation

◆ CloneOptions

Bitset enumeration to configure which aspects of a SharedImageSet to copy.

Enumerator
Everything 

Perform a deep copy of the image data and shallow copies of the mask and deformation.

NoMask 

Do not copy the attached mask.

NoDeformation 

Do not copy the attached deformation.

ShallowImageCopy 

Do not deep copy the SharedImages but only copy the shared_ptrs.

Constructor & Destructor Documentation

◆ SharedImage()

ImFusion::SharedImage::SharedImage ( std::shared_ptr< Image > img)
explicit

Creates a new SharedImage wrapping the given image.

Parameters
imgPointer to the image to initialize the SharedImage with, must not be null.
Note
You can also pass any std::unique_ptr<Image> as it implicitly converts to a std::shared_ptr of same type.

Member Function Documentation

◆ cloneWithImage()

virtual std::unique_ptr< SharedImage > ImFusion::SharedImage::cloneWithImage ( std::shared_ptr< Image > img,
Flags< CloneOptions > cloneOptions = Everything ) const
virtual

Same as clone() but uses the given image instead of copying from this.

This can be used to conveniently create a SharedImage with the output of a computation, while retaining the metadata of the source SharedImage. Metadata (modality, matrix, mask, deformation) is copied from this according to cloneOptions.

◆ img()

const Image * ImFusion::SharedImage::img ( ) const

Return the image descriptor of the currently up-to-date location.

Deprecated
Use descriptor() instead.

◆ setMask()

void ImFusion::SharedImage::setMask ( std::shared_ptr< Mask > mask)

Sets a mask for this image.

Only masks that are compatible with the image can be set. Incompatible masks will be ignored. The signalMaskChanged signal is emitted whenever the mask pointer changes.

◆ mask()

std::shared_ptr< Mask > ImFusion::SharedImage::mask ( ) const

Returns the mask for this image.

Returns nullptr if no mask is set or the current mask is not compatible to the image anymore.

◆ assign()

bool ImFusion::SharedImage::assign ( std::shared_ptr< Image > img)

Set img as new main image representation and set the dirty flag accordingly.

This function will move/sink in the image. Use update() if you want to copy the image data instead.

◆ update() [1/2]

bool ImFusion::SharedImage::update ( const MemImage & img)

Update the MemImage and set the dirty flag so that the next OpenGL access will upload this image.

This function will copy the image data into the SharedImage. Use the assign() if you want to move/sink the image in instead.

◆ update() [2/2]

bool ImFusion::SharedImage::update ( const GlImage & img)

Update the GlImage and set the dirty flag so that the next CPU access will download this image.

This function will copy the image data into the SharedImage. Use the assign() if you want to move/sink the image in instead.

◆ prepare()

void ImFusion::SharedImage::prepare ( bool shiftOnly = false)

Prepare the image in memory for most common scenarios Integral types are converted to unsigned representation if applicable, double-precision will be converted to single-precision float.

Furthermore, if shiftOnly is false it will rescale the present intensity range to [0..1] for floating point types or to the entire available value range for integral types.

Note
Pointers to the underlying image data may be invalidated as a result.

◆ syncGl()

void ImFusion::SharedImage::syncGl ( ) const

Synchronize OpenGL image, creating it if it does not exist.

Note
This method throws an exception if OpenGL texture creation fails.

◆ setDirtyMem()

void ImFusion::SharedImage::setDirtyMem ( )

Manually label MemImage as dirty (i.e.

the other representations must be updated). An implicit synchronization will happen automatically the next time another representation is requested.

◆ setDirtyGl()

bool ImFusion::SharedImage::setDirtyGl ( )

Manually label GlImage as dirty (i.e.

the other representations must be updated) An implicit synchronization will happen automatically the next time another representation is requested.

Note
This function will have no effect if the GlImage was originally created from a MemImage with more that 4 channels (cf. class documentation above).

◆ setDirtyCustom()

template<typename T>
void ImFusion::SharedImage::setDirtyCustom ( )

Manually label custom image type T as dirty (i.e.

the other representations must be updated) An implicit synchronization will happen automatically the next time another representation is requested.

◆ makeExclusive()

bool ImFusion::SharedImage::makeExclusive ( Image::Location location) const

Synchronizes the given location and deletes all other representations stored to free memory.

Returns
True if successful.
Note
This function is only implemented for the locations MEMORY, OPENGL.

◆ cloneMetadata()

virtual void ImFusion::SharedImage::cloneMetadata ( const SharedImage & metadataSource,
Flags< CloneOptions > cloneOptions )
protectedvirtual

Copies modality, matrix, and optionally mask and deformation from metadataSource into this.

Parameters
metadataSourceSource to copy metadata from.
cloneOptionsControls whether mask and deformation are copied (Everything, NoMask, NoDeformation), the ShallowImageCopy flag is ignored.

◆ checkConsistency()

bool ImFusion::SharedImage::checkConsistency ( ) const
nodiscardprotected

Checks the internal state for consistency between all image representations.

Returns false if representations are out of sync or inconsistent.

◆ sharedImageImpl() [1/2]

std::shared_ptr< Image > ImFusion::SharedImage::sharedImageImpl ( const std::type_index & imageType,
CreateImageFromMemFunction createFromMem )
protected

Returns a shared_ptr to the requested image representation, synchronizing or creating it if needed.

The createFromMem function is used to create the requested representation from a MemImage. Side effect: May trigger synchronization and create new representations (e.g., MemImage, GlImage, or custom).

◆ sharedImageImpl() [2/2]

std::shared_ptr< const Image > ImFusion::SharedImage::sharedImageImpl ( const std::type_index & imageType,
CreateImageFromMemFunction createFromMem ) const
protected

Returns a shared_ptr to the requested image representation, synchronizing or creating it if needed.

The createFromMem function is used to create the requested representation from a MemImage. Side effect: May trigger synchronization and create new representations (e.g., MemImage, GlImage, or custom).

◆ syncImpl()

virtual Representation ImFusion::SharedImage::syncImpl ( const std::type_index & imageType,
CreateImageFromMemFunction createFromMem ) const
protectedvirtual

Ensures the requested image representation is up-to-date, synchronizing or creating it if necessary.

The createFromMem function is used to create the requested representation from a MemImage. Side effect: May create new representations and update internal state.

Returns
The representation on success; check repr.isValid() for failure (e.g. conversion failed).

◆ setDirtyImpl()

void ImFusion::SharedImage::setDirtyImpl ( const std::type_index & imageType)
protected

Marks the requested image representation as the main one and all others as dirty.

Side effect: Updates m_mainImage, marks other representations as dirty, emits signalChanged, and may update mask/bounds.

◆ makeExclusiveImpl()

virtual bool ImFusion::SharedImage::makeExclusiveImpl ( const std::type_index & imageType,
CreateImageFromMemFunction createFromMem ) const
protectedvirtual

Makes the requested image representation the only one stored, removing all others.

Creates it if necessary.

If T is void, all representations are removed. This is only used internally to clear m_images, e.g. when moving. In that case, the value of createFromMem is ignored.

The createFromMem function is used to create the requested representation from a MemImage. Side effect: Updates m_mainImage, clears other representations, and may update mask/bounds.

◆ findRepresentation()

Representation ImFusion::SharedImage::findRepresentation ( const std::type_index & imageType) const
protected

Finds the representation for the given image type.

Returns
The representation, or an invalid one (repr.isValid() == false) if not found.

◆ addOrReplaceRepresentation()

virtual Representation ImFusion::SharedImage::addOrReplaceRepresentation ( const std::type_index & imageType,
std::shared_ptr< Image > img,
bool isDirty ) const
protectedvirtual

If the representation for the given image type exists, it is replaced with img, otherwise img is added as new representation.

Returns
A copy of the stored representation.

◆ representationAccessed()

virtual void ImFusion::SharedImage::representationAccessed ( const std::type_index & imageType,
const Representation & representation ) const
protectedvirtual

Internal method to allow observers to track representation accesses.

No-op per default.

Parameters
representationA snapshot (copy) of the representation that was accessed

Member Data Documentation

◆ signalChanged

Signal<const SharedImage*> ImFusion::SharedImage::signalChanged

Called when the content of a SharedImage has changed (every time one of the setDirty() methods has been called).

Note
This method may be called frequently during the processing of algorithms. When connecting to this signal, make absolutely sure to not include any expensive operations! Otherwise you may introduce a performance hit to the entire application. All you should do is setting a dirty flag yourself if needed.

◆ signalMaskChanged

Signal<const SharedImage*> ImFusion::SharedImage::signalMaskChanged

Called when a Mask object is assigned or removed from the SharedImage.

Note
Listeners are not immediately notified when a mask becomes incompatible with the image, but only after the first call to SharedImage::mask().

◆ signalDeleted

Signal<const SharedImage*> ImFusion::SharedImage::signalDeleted

Called when this instance is deleted.

Warning
Use with caution, only pointer comparison is allowed! This method is called from a SharedImage instance in the destructor of the very base class, therefore no type information for dynamic casts or other class attributes are available anymore.

◆ m_glImgHasStrippedChannels

bool ImFusion::SharedImage::m_glImgHasStrippedChannels = false
mutableprotected

Indicates that the GL representation was created from an image with > 4 channels.

Since OpenGL does not support this the GL representation only stores the first 4 channels. A subsequent call to setDirtyGl() has no effect to avoid data loss.


The documentation for this class was generated from the following file:
  • ImFusion/GL/SharedImage.h
Search Tab / S to search, Esc to close