Difference between revisions of "Image Accessor Integration"

From mitk.org
Jump to navigation Jump to search
(Publish)
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
__NOTOC__
 
__NOTOC__
<!-- ## page was renamed from internal/ImageAccessorIntegration -->
+
== How to integrate the new ImageAccessor class ==
= How to integrate the new [[ImageAccessor]] class =
 
  
'''The concept of image accessors is explained at Doxygen -> Related Pages -> Images.
+
'''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!'''
  
Line 16: Line 15:
  
 
All those issues have a specific reason, which is explained in the following section together with replacement guidelines and code examples.  
 
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 ===
 
=== Step-by-step procedures to replace existing code ===
Line 21: Line 21:
 
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.
 
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.
  
# '''Always prefer a read accessor to a write accessor!'''<<BR>>
+
# '''Always prefer a read accessor to a write accessor!'''<br />
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.<<BR>><<BR>>
+
::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.<br /><br />
  
 
# '''Only access an image data pointer, if its associated image accessor is valid!'''
 
# '''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.
+
::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) ====
+
 
 +
==== 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:
 
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:
Line 37: Line 38:
 
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:
 
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">
<pre><nowiki>#!cplusplus
 
 
// Access GetData() of an ImageDataItem object
 
// Access GetData() of an ImageDataItem object
const void* pointer = image->GetVolume(0)->GetData();
+
const void* pointer = image->GetVolumeData(0)->GetData();
</nowiki></pre>
+
</syntaxhighlight>
  
 
Precedent code needs to be replaced by:
 
Precedent code needs to be replaced by:
  
<pre><nowiki>#!cplusplus
+
<syntaxhighlight lang="cpp">
 
// Order access to an ImageDataItem object
 
// Order access to an ImageDataItem object
 
try  
 
try  
 
{
 
{
   mitk::ImageReadAccessor imgA(image, image->GetVolume(0));
+
   mitk::ImageReadAccessor imgA(image, image->GetVolumeData(0));
 
   const void* pointer = imgA.GetData();
 
   const void* pointer = imgA.GetData();
 
}
 
}
Line 56: Line 56:
 
   // deal with the situation not to have access
 
   // deal with the situation not to have access
 
}
 
}
</nowiki></pre>
+
</syntaxhighlight>
 
 
  
 
A replacement of a GetData() call in Image is applied in almost the same manner. Only the constructor call of ImageReadAccessor changes:
 
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">
<pre><nowiki>#!cplusplus
 
 
// Access GetData() of an Image object
 
// Access GetData() of an Image object
 
const void* pointer = image->GetData();
 
const void* pointer = image->GetData();
</nowiki></pre>
+
</syntaxhighlight>
 
 
  
 
Precedent code needs to be replaced by:
 
Precedent code needs to be replaced by:
  
 
+
<syntaxhighlight lang="cpp">
<pre><nowiki>#!cplusplus
 
 
// Order access to a whole Image object
 
// Order access to a whole Image object
 
try  
 
try  
Line 82: Line 78:
 
   // deal with the situation not to have access
 
   // deal with the situation not to have access
 
}
 
}
</nowiki></pre>
+
</syntaxhighlight>
  
  
==== Changing method signature of [[IpPicDescriptor]]-cast (3) ====
+
==== 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:
 
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">
<pre><nowiki>#!cplusplus
 
 
mitkIpPicDescriptor* ipPic = mitkIpPicNew();
 
mitkIpPicDescriptor* ipPic = mitkIpPicNew();
 
CastToIpPicDescriptor(image, ipPic);
 
CastToIpPicDescriptor(image, ipPic);
Line 97: Line 92:
  
 
mitkIpPicFree(ipPic);
 
mitkIpPicFree(ipPic);
</nowiki></pre>
+
</syntaxhighlight>
 
 
  
 
Needs to be replaced by:
 
Needs to be replaced by:
  
 
+
<syntaxhighlight lang="cpp">
<pre><nowiki>#!cplusplus
 
 
try  
 
try  
 
{
 
{
Line 118: Line 111:
 
   // deal with it
 
   // deal with it
 
}
 
}
</nowiki></pre>
+
</syntaxhighlight>
 +
 
 +
 
 +
[[Category:Development]]

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>