Accessing a possibly non-existent function in a ImageFileReader object


(Gabriel A. Devenyi) #1

Suppose that I create reader based ImageFileReader, and I want to do
reader->SetX(true).

But depending upon the file that was passed into ImageFileReader, “SetX” might not exist.

Is it possible to get this to work without checking the extension of the file beforehand? I.e. how could I handle this in the general case.

My naive ideas:

  • is there some way to check if SetX exists before calling it?
  • can I do a try/catch on this call and just suppress the result?

Related to:


(Dženan Zukić) #2

ImageFileReader is a class which you shouldn’t need to modify. MINCImageIO can have SetX method. Since C++ does as much checking as it can at compile time, the Pythonic try r->SetX() except print('SetX does not exist') has no equivalent in C++. Something like this might work:

auto imageIO=reader->GetImageIO();
if (imageIO->GetNameOfClass()=="MINC") // some specific IO
{
  auto mincIO = dynamic_cast<MINCImageIO>(imageIO);
  if (mincIO)
  {
    mincIO->SetX(true); //compile error here if MINCImageIO doesn't have method SetX
  }
}

(Gabriel A. Devenyi) #3

Thanks @dzenanz

Just to be clear, I was under the impression could do something like:

using ReaderType = itk::ImageFileReader< ImageType >;
typename ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName( input_image );
//If I am able to assume that input_image is always of type MINC
reader->SetX(true);
reader->Update();

Is that not the case? Do I instead need to always use the example you provided, where I generate a pointer to the underlying class and then access that function?


(Francois Budin) #4

To be able to add a new function into itk::ImageFileReader, you would have to modify the class, or template specialize it. The only template parameter that this class takes is your image type, which in turn takes a pixel type and a dimension. The IO is not specified as a template parameter, and therefore you cannot, as is, use some template specialization or SFINAE techniques to do what you want.
The current way of doing what you are talking about is:

  1. Do what @dzenanz suggested and add that new function on the IO
  2. Do not add a function but simply add data in the metadata dictionary. This is probably what you want to do if you are only talking about data/values to be added to your object.

A different approach would be to create a new type of image, which would take a dummy template parameter. That dummy template parameter could be used to specialize your reader based on your knowledge at compile time in this case. Note, I haven’t tested that option, but I would think that it works.


(Gabriel A. Devenyi) #5

Thanks @fbudin, to be clear, I actually already have a patch against the MINCIO adding a function which changes certain coordinate system interpretations. I’m just confirming now how I would go about accessing this function in a generic way where the reader/writer code is implemented with ImageFileReader/Writer, and where the actual input file type is unknown.


(Francois Budin) #6

Reading again what you wrote, I now understand that you are trying to get the value, not set it. I think the current way to do this with ITK is to instantiate your imageIO (MINCIO in your case), and pass that to your reader. One could think about adding a parameter map to the reader (e.g. New SetParameters(std::map<…>). This parameter map would be passed down to the imageIOs. Another solution would be to pass down the reader metadata dictionary to the IO. I don’t think anything like that is currently done. Passing a parameter map would be more explicit, and that map would be limited to input parameters, whereas using the metadata dictionary kind of mixes inputs and outputs.