Difference between revisions of "Image Accessor Integration"

From mitk.org
Jump to navigation Jump to search
 
Line 2: Line 2:
 
== How to integrate the new ImageAccessor class ==
 
== How to integrate the new ImageAccessor class ==
  
'''The concept of image accessors is explained on Doxygen -> Related Pages -> Images ([http://docs.mitk.org/nightly-qt4/MitkImagePage.html#MitkImagePage_AccessImageData here]).
+
'''The concept of image accessors is explained on Doxygen -> Related Pages -> Images ([http://docs.mitk.org/nightly/MitkImagePage.html#MitkImagePage_AccessImageData here]).
 
Please make yourself familiar with this concept before going on!'''
 
Please make yourself familiar with this concept before going on!'''
  

Latest revision as of 16:21, 1 June 2016

How to integrate the new ImageAccessor class

The concept of image accessors is explained on Doxygen -> Related Pages -> Images (here). Please make yourself familiar with this concept before going on!

In most cases the use of image accessors is self-explanatory. Thus, this document does not focus on explaining easy pixel value alterations. Instead mostly pointer related accesses are regarded and several guidelines to replace existing code are provided. By that, backward compatibility can be retained by applying step-by-step procedures.

With the new image accessors, old access methods of the Image and ImageDataItem classes will be changed or removed. But before making those changes, the old access methods will be marked as deprecated for one whole Release cycle.

Following issues have to be dealt with:

  1. The Method GetData() in Image will not be accessible anymore.
  2. The Method GetData() in ImageDataItem will not be accessible anymore.
  3. The method signature of an IpPicDescriptor-cast will be altered.

All those issues have a specific reason, which is explained in the following section together with replacement guidelines and code examples.


Step-by-step procedures to replace existing code

Although following solutions can be applied easily, it might be beneficial to think about particular code fragments thoroughly. The two following rules of thumb should be regarded carefully.

  1. Always prefer a read accessor to a write accessor!
For example, the decision between a read- or write-acces can make a clear difference in runtime performance, since read-accessors can run concurrently. Thus, it is highly recommended to investigate if a pointer to image data can be changed into const. Sometimes a small alteration can be enough, but at least a bug should be reported to mention the possibility of changing a pointer to const.

  1. Only access an image data pointer, if its associated image accessor is valid!
Otherwise it cannot be guaranteed, that the accessed memory area is consistent. For example, an image write accessor could alter image data at the same time.


Removing GetData() from Image and ImageDataItem (1/2)

To keep track of image accesses, it is necessary to get rid of methods which provide an unsupervised memory address as GetData() does. Instead, the memory address will be provided by the image accessor. A replacement can be done by applying following steps:

  1. Demand an image accessor by calling its constructor (e.g. ImageReadAccessor)
  2. Commit the Image and if required the ImageDataItem to that constructor
  3. Call GetData() of the image accessor instance

A call of GetData() in the image accessor provides the same pointer as it was provided by GetData() in Image resp. in ImageDataItem (if it was commited). In the following code example a replacement of the GetData() call in ImageDataItem is shown:

<syntaxhighlight lang="cpp"> // Access GetData() of an ImageDataItem object const void* pointer = image->GetVolumeData(0)->GetData(); </syntaxhighlight>

Precedent code needs to be replaced by:

<syntaxhighlight lang="cpp"> // Order access to an ImageDataItem object try {

 mitk::ImageReadAccessor imgA(image, image->GetVolumeData(0));
 const void* pointer = imgA.GetData();

} catch(mitk::Exception& e) {

 // deal with the situation not to have access

} </syntaxhighlight>

A replacement of a GetData() call in Image is applied in almost the same manner. Only the constructor call of ImageReadAccessor changes:

<syntaxhighlight lang="cpp"> // Access GetData() of an Image object const void* pointer = image->GetData(); </syntaxhighlight>

Precedent code needs to be replaced by:

<syntaxhighlight lang="cpp"> // Order access to a whole Image object try {

 mitk::ImageReadAccessor imgB(image);
 const void* pointer = imgB.GetData();

} catch(mitk::Exception& e) {

 // deal with the situation not to have access

} </syntaxhighlight>


Changing method signature of IpPicDescriptor-cast (3)

Although there is a rare use of the old image structure IpPicDescriptor, a support will be provided. Since the legacy cast methods only work for Image or ImageDataItem pointers, which cannot be supervised, the cast methods will be altered to work with image accessors. It won't be enough to commit the !Image pointer and the address of the IpPicDescriptor, it will be also necessary to provide a pointer to ImageWriteAccessor. Following code example shows how to deal with the new method signatures:

<syntaxhighlight lang="cpp"> mitkIpPicDescriptor* ipPic = mitkIpPicNew(); CastToIpPicDescriptor(image, ipPic);

// do all necessary computations with ipPic

mitkIpPicFree(ipPic); </syntaxhighlight>

Needs to be replaced by:

<syntaxhighlight lang="cpp"> try {

 mitkIpPicDescriptor* ipPic = mitkIpPicNew();
 mitk::ImageWriteAccessor imageAccess(image);
 CastToIpPicDescriptor(image, &imageAccess, ipPic);
 // do all necessary computations with ipPic
 
 mitkIpPicFree(ipPic);

} catch(mitk::Exception& e) {

 // deal with it

} </syntaxhighlight>