Possible bug with multiple components in vtkImageAccumulate

Hi all, while investigating an unrelated issue while using vtkImageAccumulate (now solved), I noticed a bit of odd code in vtkImageAccumulateExecute. The part that increments the bin for the component seems to be outside the inner loop that processes each component. It looks like the code that iterates over the components should be more like this:

  while (inPtr != spanEndPtr)
  {
    for (int idxC = 0; idxC < numC; ++idxC)
    {
      // find the bin for this pixel.
      bool outOfBounds = false;
      vtkIdType* outPtrC = outPtr;

      ... gather statistics, get index, etc

      // increment the bin
      if (!outOfBounds)
      {
        ++(*outPtrC);
      }
    }
  }

Quite happy to be shot down in flames and I haven’t tried it with multiple components, but it does look like it would only process the last one in its current state (the last iteration of the outPtrC calculations).

It’s important to understand what vtkImageAccumulate does with the components. For two components, it produces a 2D histogram. And for three components, it produces a 3D histogram.

The outer loop is the loop over the pixels. Each pixel contributes to one bin in the N-dimensional histogram (or no bins, if any component of the pixel is out-of-range with respect to the size that the user has chosen for the the N-dimensional histogram).

So the outOfBounds variable ends up true if we have an out-of-range for any of the pixel’s components.

And the outPtrC variable sums the memory offsets for the bins along each of the N output axes corresponding to the N components (e.g. for column and row, if there are two components).

Note that spacing and origin in this code are the output spacing and origin, that is, they are the bin origin and the bin spacing in one, two, or three dimensions (for 1D, 2D, or 3D histograms).

      while (inPtr != spanEndPtr)
      {
        // find the bin for this pixel.
        bool outOfBounds = false;
        vtkIdType* outPtrC = outPtr;
        for (int idxC = 0; idxC < numC; ++idxC)
        {
          double v = static_cast<double>(*inPtr++);

          // compute the bin index for the current component
          int outIdx = vtkMath::Floor((v - origin[idxC]) / spacing[idxC]);

          // verify that it is in range (i.e. within the histogram bounds)
          if (outIdx >= outExtent[idxC * 2] && outIdx <= outExtent[idxC * 2 + 1])
          {
            outPtrC += (outIdx - outExtent[idxC * 2]) * outIncs[idxC];
          }
          else
          {
            outOfBounds = true;
          }
        }

        // increment the bin
        if (!outOfBounds)
        {
          ++(*outPtrC);
        }
      }

Hi David, thanks for the response. That makes sense now. The key part I was missing was that the output is N dimensional with a unique bin for each possible combination of components. I was thinking it was simply one 1D histogram per component - e.g. bin count * 3 for RGB.