Is image.GetOffsetTable()[0] always equal to 1?

itkShapedImageNeighborhoodRange.h has the following assert:

const OffsetValueType* const offsetTable = image.GetOffsetTable();
assert((offsetTable != nullptr) && (offsetTable[0] == 1));

Is it safe to assume that the first value of the offset table of an image is always exactly 1? I mean, is the assert correct, for any image type?

Not using it is a violation of the data model that ITK has. This abstraction can enable different data layouts for the image buffer. Consider the definition of thePyBuffer with its shape, strides and offsets. ITK has a similar defined abstract interface. Supporting this model in ITK proper code is an example of the distinction of what is expected in ITK proper code vs remove modules/review code.

However, recently many of the ITK defined models and interfaces are being thrown out the window, it may be that there is no longer an inclination to support the traditional ITK data models, and heavy weight abstractions.

Practically, the assumptions that offsetTable[0] == 1 is correct. This really should not be a debug only assert, but should always generate an itk exception if this assumption is violated.

1 Like

Thanks, Brad! ShapedImageNeighborhoodRange could certainly be adjusted to fully support offsetTable[0] >= 2. But that would somewhat reduce its performance. :hushed: So I wonder if it’s worth it for now, given that such image types aren’t being used in practice…

Here is where itkShapedImageNeighborhoodRange.h deliberately skips multiplication by offsetTable[0] (at the 4th line of code):

reference operator*() const ITK_NOEXCEPT
{
  const OffsetType currentOffset = (*m_CurrentOffset);
  auto* result = m_ImageBufferPointer + GetClampedIndex(currentOffset[0] + m_Location[0], m_ImageSize[0]);

  for (ImageDimensionType i = 1; i < ImageDimension; ++i)
  {
    result += GetClampedIndex(currentOffset[i] + m_Location[i], m_ImageSize[i]) * m_OffsetTable[i];
  }

  return reference(result, m_NeighborhoodAccessor);
}

I hope that’s acceptable :slightly_smiling_face:

Did you quantify the performance difference? Do you have timing results from the experiment?

With my test from Removal of `virtual` keywords from ConstNeighborhoodIterator - #4 by blowekamp (topic item 4) I observed a very small increase of the run-time duration, when adding support for offsetTable[0] != 1, from ~12 to ~13 seconds. (Compiled by MSVC2015 x64 Release.) The performance drop certainly remains well below 10%. :slightly_smiling_face:

My next question is actually: Could an offsetTable[i] value possibly be negative? Or is it safe to assume that offsetTable[i] >= 0 (for any unsigned integer i < ImageDimension)?

Just for the record: The OffsetTable assumptions that we discussed here, are now removed from ShapedImageNeighborhoodRange:

Thanks for your feedback!

Kind regards, Niels