Changing color space of vtkAlgorithmOutput to BGR for vtkImageExport?

Hello,

I’m trying to export an image from a vtkAlgorithmOutput source to a C array in BGRA32 format. The export itself is working fine as long as vtkImageMapToColors is used to (apparently) ensure 8 bits per color component. Now, I only need to swap the red and blue channels in the exported image.
(For context, I’m developing a Slicer extension, and the input_image is pulled from one of its slice views, at probably 16 bits per component.)

This is what I have so far:

struct BGRA32 {
    uint8_t b, g, r, a;
};
vtkAlgorithmOutput* input_image = /* ... */;
auto mapper = vtkSmartPointer<vtkImageMapToColors>::New();
auto exporter = vtkSmartPointer<vtkImageExport>::New();
std::vector<BGRA32> output_data;

mapper->SetInputConnection(input_image);
exporter->SetInputConnection(mapper->GetOutputPort());
exporter->GetDataDimensions(dims.data());

output_data.resize(exporter->GetDataMemorySize() / sizeof(BGRA32));
exporter->Export(output_data.data());

I can do a manual byte swap on the exported data afterwards:

for (auto& pixel : output_data) {
    std::swap(pixel.b, pixel.r);
}

But it’s rather slow to iterate over the whole image once again after the fact. Can VTK itself do this color space conversion somehow?

(Interestingly, none of the SetOutputFormatTo*() methods in vtkImageMapToColors seems to have any effect on the output, I’m always getting RGBA, even with SetOutputFormatToLuminance(), for example.)

The vtkImageMapToColors class only performs a mapping if it is given a lookup table. In the absence of a lookup table, it just passes the input to the output with no modification. So this class is of no use for converting from one color format to another color format (unless the original color format is greyscale).

So what can I use instead?

There is no direct support for BGRA in VTK and the only place RGBA to BGRA mappings occur are in a couple I/O classes where is done with similar efficiency and simplicity as your swap() code.

So to improve efficiency, I see some possible approaches, in order of complexity:

  1. use vtkSMPTools to accelerate your current swap() approach via multithreading, or
  2. derive a subclass of vtkImageMapToColors that performs a swap after the color mapping (thereby taking advantage of the multithreading already performed by vtkImageMapToColors), or
  3. derive a subclass of vtkScalarsToColors (which is the base class of vtkLookupTable) that directly produces BGRA instead of RGBA.

The complexity of solution (3) is far greater than the complexity of (1) and (2), so even though it is a viable solution I would not recommend it.

Getting back to a comment that I gave in my previous reply, when you use vtkImageMapToColors, since you want it to always produce 4-bytes-per-color as output (regardless of input), you must provide it with a LUT that is set up as follows:

auto mapper = vtkSmartPointer<vtkImageMapToColors>::New();
auto lut = vtkSmartPointer<vtkScalarsToColors>::New();

lut->SetVectorModeToRGBColors(); // how to deal with multi-component input
mapper->SetOutputFormatToRGBA(); // this is the default, of course
mapper->SetLookupTable(lut);

For data that isn’t in the range [0,255] it is also necessary to use lut->SetRange(low, high) so that the values will be scaled appropriately.