IntensityPoint in IntensityGridSeries

A forum dedicated to WPF version of LightningChart Ultimate.

Moderator: Arction_LasseP

juergen
Posts: 27
Joined: Tue Feb 04, 2014 8:11 am

IntensityPoint in IntensityGridSeries

Post by juergen » Tue Mar 25, 2014 1:29 pm

Hi,
I get images from a ccd camera with a resolution of 1280x1024 pixels.
The data I get is a standard RGB format. I store them as an RGB coded integer format (ARGB).

For displaying the data I use IntensityPoints with IntensityGridSeries in a ViewXY.
It looks good, but I only get about 2-4 images/second.
If I use just Intensity data(heatmap) and Update them by SetValuesData(...) I get about 10 frames/second which is ok.

Are the color values calculated by a shader inside the graphics-card?
If yes, is it a problem to implement a shader with RGB values instead of intensity values to get it faster?

Best,
Jürgen

User avatar
ArctionPasi
Posts: 1365
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland

Re: IntensityPoint in IntensityGridSeries

Post by ArctionPasi » Tue Mar 25, 2014 1:59 pm

When you present it with Fill=Paletted, the colors get decoded in the GPU shader.

Are you now looking for an option to show your data more quickly by using the source point colors (Fill = FromSurfacePoints) without the ValueRangePalette encoding the colors?
LightningChart Support Team, PT

juergen
Posts: 27
Joined: Tue Feb 04, 2014 8:11 am

Re: IntensityPoint in IntensityGridSeries

Post by juergen » Tue Mar 25, 2014 2:05 pm

That's exactly what I'm looking for.

User avatar
ArctionPasi
Posts: 1365
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland

Re: IntensityPoint in IntensityGridSeries

Post by ArctionPasi » Wed Mar 26, 2014 9:40 am

I believe you are using it with PixelRendering = true, right?

The overhead comes from converting the integer ARGB to Color and in data update stage converting that Color back to 32-bit ARGB. The conversions in WPF are way heavier than in Winforms.

So we'd need to add an equivalent to SetValuesData method, say SetColorsData, that would accept a jagged array of type int[][]. It would work a lot faster. Even faster than SetValuesData. Adding this feature as fully functional feature will be several days of work to us, and we are already busy with v.6 development schedule, so I have to propose we'll implement this during next 6 months.
LightningChart Support Team, PT

juergen
Posts: 27
Joined: Tue Feb 04, 2014 8:11 am

Re: IntensityPoint in IntensityGridSeries

Post by juergen » Wed Mar 26, 2014 10:28 am

I had a look in the source and isn't it possible to add a PixelShader to calculate the color from the integer value instead of the Palette values?
If you say "yes" I can try it on my own and write you the result.

I forgot:
In this case I don't need PixelRendering - it doesn't matter if it's used or not.
It's just the speed that is important.

User avatar
ArctionPasi
Posts: 1365
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland

Re: IntensityPoint in IntensityGridSeries

Post by ArctionPasi » Wed Mar 26, 2014 10:52 am

I don't see reason to make it in the shader side...

If using PixelRendering = true, it uses a texture, which takes bitmap bytes in (like your ARGB data). It's then in correct color already, and using a PixelShader only slows it down.

If using PixelRendering = false, vertices are used. Each vertex needs already 32-bit ARGB integer as color.

So you you may want to investigate how to input your array in these.
LightningChart Support Team, PT

quarz
Posts: 14
Joined: Mon Nov 11, 2013 11:23 am
Location: Russia, Moscow

Re: IntensityPoint in IntensityGridSeries

Post by quarz » Thu Sep 25, 2014 3:54 pm

That would be great!
Besides ARGB, it would be useful to have formats RGB, Grayscale 8 bit and Grayscale 16 bit, to avoid unnecessary copying
ArctionPasi wrote: So we'd need to add an equivalent to SetValuesData method, say SetColorsData, that would accept a jagged array of type int[][]. It would work a lot faster. Even faster than SetValuesData. Adding this feature as fully functional feature will be several days of work to us, and we are already busy with v.6 development schedule, so I have to propose we'll implement this during next 6 months.

quarz
Posts: 14
Joined: Mon Nov 11, 2013 11:23 am
Location: Russia, Moscow

Re: IntensityPoint in IntensityGridSeries

Post by quarz » Fri Sep 26, 2014 8:46 am

When do you plan to do this feature?

User avatar
ArctionPasi
Posts: 1365
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland

Re: IntensityPoint in IntensityGridSeries

Post by ArctionPasi » Sat Sep 27, 2014 10:22 pm

This is now done and will be included in 6.2 next week.

EDIT: but we are not going to implement grayscale. Convert the grayscale to ARGB (int) on your side.
LightningChart Support Team, PT

quarz
Posts: 14
Joined: Mon Nov 11, 2013 11:23 am
Location: Russia, Moscow

Re: IntensityPoint in IntensityGridSeries

Post by quarz » Tue Sep 30, 2014 10:08 am

I tried to use SetColorsData, but did not notice the speed increase. On the contrary, "SetColorsData" is in 2 times slower than the "SetValuesData".
Could you check my sources, maybe i did not properly use this feature
Attachments
speed2d.zip
(107.16 KiB) Downloaded 318 times

User avatar
ArctionPasi
Posts: 1365
Joined: Tue Mar 26, 2013 10:57 pm
Location: Finland

Re: IntensityPoint in IntensityGridSeries

Post by ArctionPasi » Tue Sep 30, 2014 2:00 pm

- You don't need to use SetValuesData, only setColorsData, and after updating, call InvalidateColorsOnly.
- Set Fill property only in initialization stage, not every time you update the chart.
- Take SizeX and SizeY out of the loop, otherwise it causes and expensive DependencyProperty call for every cell.
- After these, rnd.Next becomes a bottleneck. You may want to use Parallel.For loop for updating.


Use this code:

Code: Select all

 public partial class MainWindow : Window
    {
        IntensityGridSeries chartData = null;

        public MainWindow()
        {
            InitializeComponent();

            chart1.BeginUpdate();

            chart1.ActiveView = ActiveView.ViewXY;
            chart1.ViewXY.XAxes[0].ValueType = AxisValueType.Number;
            chart1.ViewXY.YAxes[0].ValueType = AxisValueType.Number;
            chart1.ViewXY.XAxes[0].SetRange(0, 1088);
            chart1.ViewXY.YAxes[0].SetRange(0, 1024);
            chart1.ViewXY.LegendBox.Visible = false;

            chartData = new IntensityGridSeries(chart1.ViewXY, chart1.ViewXY.XAxes[0], chart1.ViewXY.YAxes[0]);
            chartData.SetSize(1088, 1024);
            chartData.SetRangesXY(0, 1088, 0, 1024);            
            chartData.MouseInteraction = false;
            chartData.Optimization = IntensitySeriesOptimization.DynamicValuesData;
            chartData.ShowNodes = false;
            chartData.PixelRendering = true;
            chartData.Fill = IntensityFillStyle.FromSurfacePoints; //PT

            chart1.ViewXY.IntensityGridSeries.Add(chartData);

            int iSizeY =  chartData.SizeY;
            int iSizeX = chartData.SizeX; 

            // Set geometry; NOT NEEDED.
            
            //for (int i = 0; i <iSizeY; i++)
            //{
            //    for (int j = 0; j < iSizeY; j++)
            //    {
            //        chartData.Data[j, i].X = i;
            //        chartData.Data[j, i].Y = j;
            //    }
            //}

            pixels = new int[iSizeY][];

            for (int i = 0; i < iSizeY; i++)
            {
                pixels[i] = new int[iSizeX];
            }

            chart1.EndUpdate();


            chartData.SetColorsData(pixels, IntensityGridValuesDataOrder.RowsColumns);  

            System.Windows.Threading.DispatcherTimer ttm = new System.Windows.Threading.DispatcherTimer();
            //ttm.Interval = new TimeSpan(0, 0, 0, 0, 500);
            ttm.Interval = new TimeSpan(0, 0, 0, 0, 1);
            ttm.Tick += new EventHandler(Update);
            ttm.Start();
        }

      
        int[][] pixels = null;

        void Update(object sender, EventArgs e)
        {
            Random rnd = new Random();

            st.Restart();
            int iSizeY = chartData.SizeY;
            int iSizeX = chartData.SizeX; 
            
            // Fill with random data
            int iRandomColor = 255 << 24 | (rnd.Next() % 255) << 16 | (rnd.Next() % 255) << 8 | (rnd.Next() % 255);
            for (int i = 0; i < iSizeY; i++)
            {
                for (int j = 0; j < iSizeX; j++)
                {
                    //rnd.Next becomes the bottleneck. 

                    //pixels[i][j] = 255 << 24 | (rnd.Next() % 255) << 16 | (rnd.Next() % 255) << 8 | (rnd.Next() % 255); 
                    pixels[i][j] = iRandomColor;
                }
            }

            st.Stop();

            // doesn't matter
            wnd.Title = "";// "Prepare data: " + st.ElapsedMilliseconds.ToString() + " ms. ";

            
            st.Restart();

            chart1.BeginUpdate();

            
            chartData.InvalidateColorsOnly(); 
            
            chart1.EndUpdate();

            st.Stop();

            wnd.Title += "Redraw: " + st.ElapsedMilliseconds.ToString() + " ms";
        }

        Stopwatch st = new Stopwatch();
    }


and it's solid 60 FPS refresh rate.
LightningChart Support Team, PT