Best way to render Large Size images

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
georgeplusplus
Knows some wx things
Knows some wx things
Posts: 25
Joined: Tue May 11, 2021 1:49 pm

Best way to render Large Size images

Post by georgeplusplus »

I want to create an image window that displays a plot of data.

My problem is the data points are large (about 2 million).

If I allocate a pixel to each data point that would be an image size with a pixel width of 2million.

Obviously there isnt a screen that is 2million pixels wide so this is not practical. The way I thought to go about it was to "virtually draw" the entire graph. Then zoom out until the picture fits in the users screen. That way if the user zooms, the details are preserved.

Am I going about this the right way? Can anyone recommend some code to look at or try to get started?

My goal is to match matplotlibs rendering speed which is about 1-2 seconds for my dataset.
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Best way to render Large Size images

Post by doublemax@work »

Do you have an image that gives an idea of what you want to achieve?

2 million pixels is not that much, e.g. thats 1920x1080. Or is it 2 million in x-direction only and the values go in y-direction?
georgeplusplus
Knows some wx things
Knows some wx things
Posts: 25
Joined: Tue May 11, 2021 1:49 pm

Re: Best way to render Large Size images

Post by georgeplusplus »

doublemax@work wrote: Mon Aug 02, 2021 11:01 am Do you have an image that gives an idea of what you want to achieve?

2 million pixels is not that much, e.g. thats 1920x1080. Or is it 2 million in x-direction only and the values go in y-direction?
Correct it would be 2 million in the x direction only. The Y values only go from 0 to 120 so I think I can get away with 360 or 480 as that pixel value but that still comes out to 720,000,000 pixels.

As I read the data file I am building a List of x-values, I can add something in that same loop that builds the x-values that pre-constructs some sort of image or bitmap if that will help.
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Best way to render Large Size images

Post by doublemax@work »

On which platform do you need this to work?

I wouldn't use a bitmap for that. I'd go for a custom drawn control that renders a subset of the data at a given x-offset.
Do you need to draw points/circles or bars for each data value?

The maximum number of data points you need to render is the x-resolution of the screen, so about 5k max. Even if you zoom out to render all 2 million data points, you don't need to draw 2 million lines. You can either skip values or calculate an average (the latter will be slow).

In order to test if the performance is good enough, write a small sample that renders 5000 vertical lines or rectangles. I would suspect this should be fast enough for realtime display. (If you're under Windows, make sure to use Direct2D renderer)
georgeplusplus
Knows some wx things
Knows some wx things
Posts: 25
Joined: Tue May 11, 2021 1:49 pm

Re: Best way to render Large Size images

Post by georgeplusplus »

It would be for Windows platform. Only lines currently, no circles.

I would be worried about aliasing so looping through for the max value would be mandatory I believe. I understand it would be slower (since I would have to loop through 2million points every time) but is this the only way?

Is it not feasible to virtually render the entire line, then adjust the userscale to draw to the users window size ? or would the above in effect be what I am trying to accomplish.

Also, Do you have any sample code that uses the Direct2D renderer?

Thanks for all the help DoubleMax
User avatar
doublemax@work
Super wx Problem Solver
Super wx Problem Solver
Posts: 474
Joined: Wed Jul 29, 2020 6:06 pm
Location: NRW, Germany

Re: Best way to render Large Size images

Post by doublemax@work »

Is it not feasible to virtually render the entire line, then adjust the userscale to draw to the users window size ? or would the above in effect be what I am trying to accomplish.
I'm note sure if any system can handle bitmaps with these dimensions. 2 millions x 480pixel would already require 1GB RAM when using 1 Byte per pixel. With 3 bytes per pixel, you're already at 3GB. Just try creating a bitmap of that size and see what happens ;)
Do you have any sample code that uses the Direct2D renderer?
Check the "drawing" sample that comes with wxWidgets. It's a little hard to follow, in principle it goes like this:

Code: Select all

void MyCanvas::OnPaint( wxPaintEvent &event )
{
  wxPaintDC pdc(this);
  wxGraphicsRenderer *d2dr = wxGraphicsRenderer::GetDirect2DRenderer();
  wxGraphicsContext *gc = d2dr->CreateContext(pdc);

  // use wxGraphicsContext methods to draw

  delete gc;
}
(from the top of my head, i can't test-compile it right now)
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Best way to render Large Size images

Post by doublemax »

I made some tests and on a 1920 pixel wide screen i get at least 20fps with a graphics height of 480pixel. Even if i calculate max or average values for each pixel.

So this should be no problem performance wise.
(and there is even room for more performance optimization :) )
Use the source, Luke!
Kvaz1r
Super wx Problem Solver
Super wx Problem Solver
Posts: 357
Joined: Tue Jun 07, 2016 1:07 pm

Re: Best way to render Large Size images

Post by Kvaz1r »

I'd recommend to filter out those of points that overlapped with others with some reasonable precise. In that case you will have much less drawing.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Best way to render Large Size images

Post by doublemax »

Kvaz1r wrote: Mon Aug 02, 2021 5:10 pm I'd recommend to filter out those of points that overlapped with others with some reasonable precise. In that case you will have much less drawing.
Yes, that's what i did. I only rendered as many (vertical) lines as visible pixels in x-direction. To my surprise the calculation of max or average values had almost no impact on the performance. Modern memory performance is so incredible fast.
Use the source, Luke!
Rohit Agarwal
Earned some good credits
Earned some good credits
Posts: 119
Joined: Wed May 19, 2021 11:17 pm
Contact:

Re: Best way to render Large Size images

Post by Rohit Agarwal »

georgeplusplus wrote: Mon Aug 02, 2021 8:38 am I want to create an image window that displays a plot of data.

My problem is the data points are large (about 2 million).

If I allocate a pixel to each data point that would be an image size with a pixel width of 2million.

Obviously there isnt a screen that is 2million pixels wide so this is not practical. The way I thought to go about it was to "virtually draw" the entire graph. Then zoom out until the picture fits in the users screen. That way if the user zooms, the details are preserved.

Am I going about this the right way? Can anyone recommend some code to look at or try to get started?

My goal is to match matplotlibs rendering speed which is about 1-2 seconds for my dataset.
I would get the screen size
create a wxMemoryDC based on a wxBitmap which is based on an wxImage of the screen size.
The wxImage is constructed from a data array.
Then depending on scroll and zoom settings,
I would write a function that renders the 2 million point dataset
or some subset of it to the screen size data array via interpolation.
Then Blit the wxMemoryDC which actually represents your rendered image.
So image size is always screen size and your rendering code is dynamic.
You need controls for a zoom and scroll input from the user.
You don't pre-render a really large image and then zoom into parts of it.
You can do this with wxPaintDC, don't need anything beyond that.

Note that each time you update your image array you will have to reset the data in the wxMemoryDC

Code: Select all

  image.SetData( ImageArrayRGB, true );
  image.SetAlpha( ImageArrayA, true );
  memDC.SelectObject( wxNullBitmap );
  bitmap = wxBitmap( image, 32 );        
  memDC.SelectObject( bitmap );      
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Best way to render Large Size images

Post by doublemax »

Note that each time you update your image array you will have to reset the data in the wxMemoryDC
That's a good alternative if the required drawing operations are very simple (like points and lines).

But the conversion from wxImage to wxBitmap is slow (done pixel by pixel), so it would be better to use raw bitmap access to write directly into the bitmap. https://docs.wxwidgets.org/trunk/classw ... _data.html
Use the source, Luke!
georgeplusplus
Knows some wx things
Knows some wx things
Posts: 25
Joined: Tue May 11, 2021 1:49 pm

Re: Best way to render Large Size images

Post by georgeplusplus »

Thanks for all the great suggestions. Definitly gonna give them a try. Ill report back on their performance as well.
georgeplusplus
Knows some wx things
Knows some wx things
Posts: 25
Joined: Tue May 11, 2021 1:49 pm

Re: Best way to render Large Size images

Post by georgeplusplus »

Rendering Worked great it is extremely fast. The image is a bit gritty but I suppose thats what zoom is for. Thank you all for the help and suggestions.
Post Reply