Recent

Author Topic: BGRABitmap rendering speed  (Read 1014 times)

hedgehog

  • Jr. Member
  • **
  • Posts: 64
BGRABitmap rendering speed
« on: May 27, 2025, 10:59:11 am »
I think the rendering speed is slow.
I'm trying to draw a graph of 10,000 points and it's slow.
Is there a fix for this or am I doing something wrong?

wp

  • Hero Member
  • *****
  • Posts: 12859
Re: BGRABitmap rendering speed
« Reply #1 on: May 27, 2025, 11:58:06 am »
Yes, in particular, when I resize the form there is quite slaggy reaction.

Just for comparison: I put the same data in a TAChart, and here the reaction upon form size changes is immediate.

hedgehog

  • Jr. Member
  • **
  • Posts: 64
Re: BGRABitmap rendering speed
« Reply #2 on: May 27, 2025, 01:06:54 pm »
Yes, in particular, when I resize the form there is quite slaggy reaction.

Just for comparison: I put the same data in a TAChart, and here the reaction upon form size changes is immediate.
Yes, of course, the LCL graphics are very fast. (But it does not support antialiasing).
DirectX is also fast.

circular

  • Hero Member
  • *****
  • Posts: 4441
    • Personal webpage
Re: BGRABitmap rendering speed
« Reply #3 on: May 27, 2025, 01:33:58 pm »
Hi hedgehog,

Since the data is mostly angular, you can make rendering about twice as fast by changing the line join style. By default, Canvas2D uses pjsMiter, which draws sharp angles. However, you can switch to pjsRound or pjsBevel to avoid rendering those angles and improve performance.

Code: Pascal  [Select][+][-]
  1.   Bitmap.Canvas2D.strokeStyle(clBlack);
  2.   Bitmap.Canvas2D.lineJoinLCL:= pjsBevel;
  3.   Bitmap.Canvas2D.beginPath;
  4.   Bitmap.Canvas2D.polylineTo(arr);
  5.   Bitmap.Canvas2D.stroke;  

Regards
Conscience is the debugger of the mind

hedgehog

  • Jr. Member
  • **
  • Posts: 64
Re: BGRABitmap rendering speed
« Reply #4 on: May 27, 2025, 02:08:41 pm »
Hi, Circular.

Yes, it increased the speed (a little).
Strangely, I always thought that sharp corners on a polyline are drawn faster than rounded ones.

If I use integer drawing functions in BGRA, can it increase the speed?

wp

  • Hero Member
  • *****
  • Posts: 12859
Re: BGRABitmap rendering speed
« Reply #5 on: May 27, 2025, 03:05:04 pm »
Yes, in particular, when I resize the form there is quite slaggy reaction.

Just for comparison: I put the same data in a TAChart, and here the reaction upon form size changes is immediate.
Yes, of course, the LCL graphics are very fast. (But it does not support antialiasing).
DirectX is also fast.
Well, I always thought that BGRA is faster than LCL. Maybe anti-aliasing makes the difference? Can you turn off anti-aliasing in BGRA?

circular

  • Hero Member
  • *****
  • Posts: 4441
    • Personal webpage
Re: BGRABitmap rendering speed
« Reply #6 on: May 27, 2025, 03:15:46 pm »
Hi hedgehog,

Yes, rounded corners can be slightly slower for a regular shape, with 90 degrees angles for example. However for a curve like this, the angles add up and increase the overlap: while the surface does not grow, it actually has overlapping bits. If you want maximum speed whatever the shape, I suggest to use pjsBevel.

Using integer functions is 100 times faster. You can do that with few changes:
Code: Pascal  [Select][+][-]
  1. var
  2.   ...
  3.   arr: array of TPoint = nil;
  4. begin
  5.   for i:=0 to n-1 do
  6.     arr[i]:= Point(round(border + (points[i].x - x0)*kx), round(border + (1.5 - points[i].y)*ky));
  7.  
  8.   Bitmap.DrawPolyLineAntialias(arr, BGRABlack, true);

If you want to change the pen width to 2, then you'll need to draw the shape multiple times. For example four times to make a squared pen:
Code: Pascal  [Select][+][-]
  1.   Bitmap.DrawPolyLine(arr, BGRABlack, true);
  2.   for i:=0 to n-1 do
  3.     arr[i].Offset(1,0);
  4.   Bitmap.DrawPolyLine(arr, BGRABlack, true);
  5.   for i:=0 to n-1 do
  6.     arr[i].Offset(0,1);
  7.   Bitmap.DrawPolyLine(arr, BGRABlack, true);
  8.   for i:=0 to n-1 do
  9.     arr[i].Offset(-1,0);
  10.   Bitmap.DrawPolyLine(arr, BGRABlack, true);  
  11.  

And to get something a bit smoother, a pen shaped as a "+" :
Code: Pascal  [Select][+][-]
  1.   Bitmap.DrawPolyLine(arr, BGRA(0,0,0,255), true);
  2.   for i:=0 to n-1 do
  3.     arr[i].Offset(1,0);
  4.   Bitmap.DrawPolyLine(arr, BGRA(0,0,0,96), true);
  5.   for i:=0 to n-1 do
  6.     arr[i].Offset(-2,0);
  7.   Bitmap.DrawPolyLine(arr, BGRA(0,0,0,96), true);
  8.   for i:=0 to n-1 do
  9.     arr[i].Offset(1,-1);
  10.   Bitmap.DrawPolyLine(arr, BGRA(0,0,0,96), true);
  11.   for i:=0 to n-1 do
  12.     arr[i].Offset(0,2);
  13.   Bitmap.DrawPolyLine(arr, BGRA(0,0,0,96), true);

Conscience is the debugger of the mind

hedgehog

  • Jr. Member
  • **
  • Posts: 64
Re: BGRABitmap rendering speed
« Reply #7 on: May 27, 2025, 03:26:23 pm »
This is really cool, thank you.
I learned everything I wanted.

P.S. How do you calculate rendering time? GetTickCount64?
« Last Edit: May 27, 2025, 03:45:21 pm by hedgehog »

Seenkao

  • Hero Member
  • *****
  • Posts: 711
    • New ZenGL.
Re: BGRABitmap rendering speed
« Reply #8 on: May 28, 2025, 02:38:46 am »
Для статичных данных я бы посоветовал массив
Code: Pascal  [Select][+][-]
  1. arr: array of TPointF = nil;
сделать общим для класса и определить его при создании формы.

Вы тратите немало времени на очередной пересчёт данных, которые не меняются.


Google translate:
For static data, I would recommend making the array
Code: Pascal  [Select][+][-]
  1. arr: array of TPointF = nil;
common to the class and defining it when creating the form.

You spend a lot of time on another recalculation of data that does not change.

Code: Pascal  [Select][+][-]
  1.   TForm1 = class(TForm)
  2.     BGRAVirtualScreen1: TBGRAVirtualScreen;
  3.     procedure BGRAVirtualScreen1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
  4.     procedure FormCreate(Sender: TObject);
  5.   private
  6.     points: array of TPointF;
  7.     arr: array of TPointF = nil;
  8.     procedure DrawChart(Bitmap: TBGRABitmap);
  9.     procedure DrawChart2(Bitmap: TBGRABitmap);
  10.   public
  11.  
  12.   end;
  13.  
  14. procedure TForm1.FormCreate(Sender: TObject);
  15. const
  16.   range = 2*pi;
  17. var
  18.   x: single;
  19.   i, n: integer;
  20.   kx, ky: double;
  21.   range: double;
  22.   x0: single;
  23. begin
  24.   SetLength(points, cnt+1);
  25.   for i:= 0 to cnt do
  26.   begin
  27.     x:= range*i/cnt;
  28.     points[i].x:= x;
  29.     points[i].y:= sin(x) + (random-0.5)/5;
  30.   end;
  31.  
  32.   n:= Length(points);
  33.   range:= points[n-1].x - points[0].x;
  34.   kx:= R.Width/range;
  35.   ky:= R.Height/3;
  36.   x0:= points[0].x;
  37.   SetLength(arr, n);
  38.  
  39.   for i:=0 to n-1 do
  40.     arr[i]:= PointF(border + (points[i].x - x0)*kx, border + (1.5 - points[i].y)*ky);
  41. end;
  42.  
  43. procedure TForm1.DrawChart2(Bitmap: TBGRABitmap);
  44. const
  45.   border = 20;
  46. var
  47.   R: TRect;
  48.  
  49. begin
  50.   R:= Rect(border, border, Bitmap.Width-border, Bitmap.Height - border);
  51.  
  52.   Bitmap.Canvas2D.strokeStyle(clBlack);
  53.   Bitmap.Canvas2D.beginPath;
  54.  
  55.   Bitmap.Canvas2D.polylineTo(arr);
  56.   Bitmap.Canvas2D.stroke;
  57. end;
Rus: Стремлюсь к созданию минимальных и достаточно быстрых приложений.

Eng: I strive to create applications that are minimal and reasonably fast.
Working on ZenGL

circular

  • Hero Member
  • *****
  • Posts: 4441
    • Personal webpage
Re: BGRABitmap rendering speed
« Reply #9 on: May 28, 2025, 08:50:18 am »
This is really cool, thank you.
I learned everything I wanted.
Awesome, glad that answered your questions.

Quote
P.S. How do you calculate rendering time? GetTickCount64?
Here I did a crude (Now - StartTime)*86400*1000. It's not guaranteed to be super-precise, but it was good enough for my system.
Conscience is the debugger of the mind

hedgehog

  • Jr. Member
  • **
  • Posts: 64
Re: BGRABitmap rendering speed
« Reply #10 on: May 29, 2025, 04:03:58 pm »
Hi, Circular.

Is there a Bitmap.Translate(x,y: integer) function?
Or, does Canvas2D have fast drawing?

circular

  • Hero Member
  • *****
  • Posts: 4441
    • Personal webpage
Re: BGRABitmap rendering speed
« Reply #11 on: May 30, 2025, 09:46:25 am »
Hi hedgehog,

Nope there isn't a global translate function in TBGRABitmap, so that functions like SetPixel are as fast as possible.

Canvas2D is not supposed to do pixel drawing. However CanvasBGRA (TBGRACanvas class) is suited for this: when one draws with a solid pen of width 1, it will definitely use integer coordinates.

So we could implement some transformations into CanvasBGRA, at least translations and integer transforms (flip, rotate 90 degrees, maybe scale by an integer). This would be an integer matrix applied to all coordinates used in the functions. For the clip rectangle, to be readable, the matrix need to be inversible within the integers, so probably it is simpler to not allow scaling.
Conscience is the debugger of the mind

hedgehog

  • Jr. Member
  • **
  • Posts: 64
Re: BGRABitmap rendering speed
« Reply #12 on: May 30, 2025, 11:24:50 am »
Yes, this function
Code: Pascal  [Select][+][-]
  1. Bitmap.CanvasBGRA.Polyline(arr);
works very fast.

But I didn't find the translation function (I guess I'm stupid) :)

circular

  • Hero Member
  • *****
  • Posts: 4441
    • Personal webpage
Re: BGRABitmap rendering speed
« Reply #13 on: May 30, 2025, 12:16:51 pm »
It doesn't exist yet. I was rather suggesting that it could be implemented along with some transforms like rotation / flip.
Conscience is the debugger of the mind

SandyG

  • Full Member
  • ***
  • Posts: 107
Re: BGRABitmap rendering speed
« Reply #14 on: May 31, 2025, 07:52:26 am »
This may not apply to your work, but if you do have any drawing being done inside a component and that component is overlapping any other components it will cause a redraw of anything it may touch.

I was doing an analog gauge component and doing some speed testing at various sizes of the component, and all of a sudden it got really slow. It ended up that the component was just overlapping a tab page with a lot of other things on it, like edits, labels, etc. Drawing crawled really slow when that happened, and as soon as you move it off, back to fast.

Again, may not apply to your case if just drawing, but if in a component like a TGraphicControl can be an issue.

Sandy

 

TinyPortal © 2005-2018