Recent

Author Topic: Draw area from BGRA to BGRA  (Read 13651 times)

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Draw area from BGRA to BGRA
« on: December 21, 2012, 05:27:06 pm »
Hi,
I need help with drawing only some shape to BGRABitmap.

I draw shape by PolygonF on source BGRABitmap. And then how to move only that area (array of TPointF) to another BGRABitmap ?
I see that I can use BGRABitmap.PutImage but (for speed reasons, source and destination bitmaps are big) I need copy only some pixels (PolygonF).
 

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #1 on: December 21, 2012, 06:09:58 pm »
I need a break :)

in generally I putImage each time when I draw shape (polygon), and it was a serious mistake (speed).
Source and destination bitmap have same size so I fix this :) I draw shapes on transparent source bitmap and then "at end" I putImage (with all shapes) to destination.

sorry about the hassle

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #2 on: December 23, 2012, 12:55:59 pm »
Yes.

You can also use a clipping region when you do the PutImage. Define ClipRect to be the region where something must be changed.

Anyway, you're right, better avoid doing too many PutImage.
Conscience is the debugger of the mind

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #3 on: December 28, 2012, 09:41:24 pm »
Thanks for hint with clipping.
Examining the speed, I discovered that the as example PolygonF (CanvasBGRA) is slower then Canvas.
FBitmap.ComputeWidePolygon = ComputeWidePolylinePoints in BGRAPen most slows.
I found that when I set:
    CanvasBGRA.Pen.EndCap:=pecRound;       
    CanvasBGRA.Pen.JoinStyle:=pjsMiter;

is a little faster, but is there any other way to speed up ?

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #4 on: December 29, 2012, 11:56:18 am »
There is no simple way.

Maybe polygon intersection could be computed faster (in BGRAFillInfo, used when actually drawing the polygon).

About computing the contour with ComputeWidePolylinePoints, well, I don't know. Are you sure the time is spent computing it?
Conscience is the debugger of the mind

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #5 on: December 29, 2012, 08:49:39 pm »
this is my tests:

pol is array of TPointF, there is about 3500 polygons.

CanvasBGRA.PolygonF(pol,true,false)
gives me: 1,45~1,49 sec.

without borders:
CanvasBGRA.PolygonF(pol,true,true)
gives me: 0,35~0,36 sec.

so, without polyline border is about 4 times faster.

I test also with this modification, in BGRACanvas (for check speed with polygon as border)


Code: [Select]
procedure TBGRACanvas.PolygonF(const APoints: array of TPointF; Winding: Boolean; FillOnly: Boolean = False);
...
  if not NoPen and not FillOnly then
  begin
    ApplyPenStyle;
    //multi.AddPolygon(FBitmap.ComputeWidePolygon(APoints,Pen.ActualWidth),Pen.ActualColor);
    multi.AddPolygon(APoints,Pen.ActualColor);
  end;

gives me: 0,51~0,55 sec.

it seems that a lot of time it takes to generate a path border BGRAPen.ComputeWidePolylinePoints.

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #6 on: December 29, 2012, 10:22:21 pm »
To compare, you would need to comment this line :
//multi.Draw(FBitmap);

 and try both
Conscience is the debugger of the mind

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #7 on: December 29, 2012, 10:36:09 pm »
Ok, this is my tests:
Code: [Select]
procedure TBGRACanvas.PolygonF(const APoints: array of TPointF; Winding: Boolean; FillOnly: Boolean = False);
...
  if not NoPen and not FillOnly then begin
     ApplyPenStyle;
     multi.AddPolygon(FBitmap.ComputeWidePolygon(APoints,Pen.ActualWidth),Pen.ActualColor);
  end;
  //multi.Draw(FBitmap);
  multi.Free;   
CanvasBGRA.PolygonF(pol,true,false);
gives me: 1,18~1,19 sec.


CanvasBGRA.PolygonF(pol,true,true);
gives me: 0,30 sec.

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #8 on: December 30, 2012, 09:25:19 pm »
Ok that's a big difference.

And how much is it compared to the total time (including drawing) ?

Is it 1,18 / 1,45 = 81% of the time ?

And 0,30 / 0,35 = 85 % of the time ?

I am surprised. I do not know how to improve this. But for sure my code in BGRAPen may not be optimal. I was happy enough that it was working :)
Conscience is the debugger of the mind

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #9 on: December 30, 2012, 11:06:15 pm »
Ok that's a big difference.

And how much is it compared to the total time (including drawing) ?

Is it 1,18 / 1,45 = 81% of the time ?

And 0,30 / 0,35 = 85 % of the time ?

yes, exactly

I am surprised. I do not know how to improve this. But for sure my code in BGRAPen may not be optimal. I was happy enough that it was working :)

yes, it's great it draws very quickly :)
I do not know exactly how this procedure work, but I wonder if AntialiasingMode = amOff the contour with ComputeWidePolylinePoints should not be calculated faster ? this code in BGRAPen is the same for AntialiasingMode = amOff/anOn ?

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #10 on: January 01, 2013, 03:23:43 pm »
Maybe it could use less precision for computing round junctions, but that would not be a big change I suppose, and most of the algorithm does not depend on the precision : computing line intersections is needed anyway.
Conscience is the debugger of the mind

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #11 on: January 01, 2013, 03:31:36 pm »
I see some duplicates on contour points, below code should improve this,
instead
Code: [Select]
  procedure AddPt(pt: TPointF);
  begin
    if nbStyled = length(styledPts) then
      setlength(styledPts,nbStyled*2+4);
    styledPts[nbStyled] := pt;
    inc(nbStyled);
  end;
should be
Code: [Select]
  procedure AddPt(pt: TPointF);
  begin
    if nbStyled = length(styledPts) then
      setlength(styledPts,nbStyled*2+4);
    if (nbStyled = 0) or (pts <> styledPts[nbStyled-1]) then begin
       styledPts[nbStyled] := pt;
       inc(nbStyled);
    end;
  end;
this modification speed up a little  ~5%.
For my tests I check with some prec. 0.5 and this is much better
Code: [Select]
  procedure AddPt(pt: TPointF);
  begin
    if nbStyled = length(styledPts) then
      setlength(styledPts,nbStyled*2+4);
    if (nbStyled=0) or (abs(pt.x-styledPts[nbStyled-1].x)>0.5) or (abs(pt.y-styledPts[nbStyled-1].y)>0.5) then begin
      styledPts[nbStyled] := pt;
      inc(nbStyled);
    end;
  end;
What do you think about this? is it safe?

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #12 on: January 02, 2013, 10:57:09 pm »
Hmm, removing exact duplicates is ok.

Removing approximate duplicates is not "safe", because the resulting polygon can be inconsistent (not too bad, but not good either) with the expected shape.

Maybe it can be simplified by changing the code that call that procedure. For example what I said about rounded junctions or caps, that can be drawn with less precision.


Conscience is the debugger of the mind

bigeno

  • Sr. Member
  • ****
  • Posts: 266
Re: Draw area from BGRA to BGRA
« Reply #13 on: January 02, 2013, 11:24:12 pm »
Thanks, but that's more than my power  :)
I hope you find some time to see if you can do something about it.  8)

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Draw area from BGRA to BGRA
« Reply #14 on: January 03, 2013, 12:37:59 pm »
Thank you too for investigating. Now I know there is something to do here.  8-)
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018