vtkImageResliceMapper and ResampleToScreenPixels on HiDPI display

Hello community,

We have done the migration from the old vtkImagePlaneWidget to the less old vtkImageResliceMapper in our software. This greatly improve the quality of the rendering when we are zooming, but on some setup (especially HidDPI displays) when we turn on the option ResampleToScreenPixels to get the high quality rendering the static rendering (without interaction) becomes real slow.

Is it possible to hack the vtkImageResliceMapper in order to resample only in “logical pixel” and not in “physical ones” ? For exemple if the widget size is 1024x1024, on a retina display it becomes 2048x2048 and since AFAIK the reslice is all done on the CPU, it can become really slow (especially with multiple views that update at the same time).

Ideally i would like to use the Viewport size divided by the screen scale factor in order to compute the extent of the reslice …

@dgobbi since you are the writer of this class maybe you have a clue on how to do that ? :slight_smile:

Thanks

Hi Simon,

It’s good to hear that the vtkImageResliceMapper is (for the most part) working well for you. The class could be modified to use logical pixels for the resample size, since it could rely on texture interpolation to then upsample to physical pixels. There would be tiny artifacts at the edge of the image, but the artifacts would be smaller than a logical pixel.

I don’t think there is any quick hack for this, however. The vtkImageResliceMapper code would have to be modified in two or three different places. It’s a change that I’d really like to make, but I’m not sure when I might have time.

Hi David,
Yes I’m really enjoying the simplicity of the new class, we are doing oblique MPR here and mask blending, it’s so much less code !

Meanwhile, I may have found a “Quick&Dirty” solution for my problem that seems to be working !
In vtkImageResliceMapper’s header I’ve added :

vtkSetClampMacro(ImageDecimateFactor, double, 1, 10);
vtkGetMacro(ImageDecimateFactor, double);

double ImageDecimateFactor;               // Decimate the image

And in the cxx line 860 :

xsize = static_cast<int>(static_cast<double>(xsize) / this->ImageDecimateFactor);
ysize = static_cast<int>(static_cast<double>(ysize) / this->ImageDecimateFactor);

Hence in my code I can call something like :

myResliceMapper->SetImageDecimateFactor( QScreen::devicePixelRatio() );

I know it’s really ugly … Maybe you have a better solution ?

It would be nice if we could get more control other the final extent
Thanks a lot for your work anyway !

Hi Simon,

That’s a reasonable solution, it’s a similar idea to the SetImageSampleDistance(double) method used by vtkGPUVolumeRayCastMapper. But something more automatic would be nice. People shouldn’t have to set a parameter in the mapper just because of HiDPI. Also the static_cast<int>() means that people won’t always get the factor that they ask for.

If you have any ideas about what the programming interface would look like, I would be glad to hear.

David

Hi David,

Yes, it’s the same idea than that part of the GPU volume mapper in VTK :slight_smile:

About the control on the final extent, maybe an enum instead of the ResampleToScreenPixels boolean with several possible, options :
VTK_SLICE_SIZE_MATCH_SCREEN_PIXELS (=ResampleToScreenPixels to True)
VTK_SLICE_SIZE_FOLLOW_INPUT (=ResampleToScreenPixels to False)
VTK_SLICE_SIZE_FIXED_SIZE

And if a user select the last one, there should be another method :
SetSliceFixedSize( int a_xsize, int a_ysize );
Just an idea …

I have another question, on that page it is said that the vtkImageSliceMapper provide a bicubic hardware accelerated interpolation. Is there any option to activate that ? It seems to me that the only thing that is used is the classical bilinear interpolation of vtkTexture.
I would like to achieve something like what is done in Osirix since the version 7.
Now the question become : what would be the easiest to implement something like this at the texture level :

Simon

Hi Simon,

The bicubic interpolator for vtkImageSliceMapper was part of the old OpenGL backend for VTK. When vtkImagSliceMapper was re-written for the new OpenGL2 backend, all of its shader code was discarded (too old, didn’t fit the new architecture).

A new bicubic glsl shader could definitely be added to VTK, but I do not know where it would be added. Shader injection is one of the parts of the VTK rendering architecture that I am not familiar with.

Thanks for your suggestions about the screen pixels API, I’ll give it some more thought.

Thanks David,

Hello @ken-martin :slight_smile:
Maybe you have a clue on where to start in order to add a bicubic glsl interpolation on a vtkTexture with the new OpenGL2 backend ?
I’ve tried to exposed the member “PolyDataActor” in vtkOpenGLImageSliceMapper in order to be able to play with some shader replacement from our framework without success for now. Anyway I think it might be more useful to integrate properly such a feature into vtkTexture and to expose that as an option :
VTK_TEXTURE_INTERPOLATION_NEAREST
VTK_TEXTURE_INTERPOLATION_LINEAR
VTK_TEXTURE_INTERPOLATION_BICUBIC

Any help would be appreciated
Kind regards
Simon