BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: Slow graphics using TImage?

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Graphics)
View previous topic :: View next topic  
Author Message
PaoloItaly
Guest





PostPosted: Thu Oct 21, 2004 11:31 am    Post subject: Re: Slow graphics using TImage? Reply with quote



One question:
the following code is inside a loop ?
Quote:
. pBitmap1->Canvas->MoveTo(x1,y1);
. pBitmap1->Canvas->LineTo(x2,y2);
. Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
.
. Image1->Repaint();
If so, put outside your loop

Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
Image1->Repaint();

Back to top
PaoloItaly
Guest





PostPosted: Fri Oct 22, 2004 6:52 am    Post subject: Re: Slow graphics using TImage? Reply with quote



Try to bypass VCL graphics
HDC temp = pBitmap1->Canvas->Handle;
loop
::MoveToEx(temp, x1, y1, NULL);
::LineTo(temp, x2, y2);
and let me know

Bye


Back to top
PaoloItaly
Guest





PostPosted: Mon Oct 25, 2004 8:44 am    Post subject: Re: Slow graphics using TImage? Reply with quote



Quote:
What kind of methods/package am I using with the
::MoveToEx/::LineTo-methods?
You are calling Windows API directly, the same functions that VCL use

internally
Quote:
Is there a better way to get double buffer than using the copyRect-method?
You can use ::BitBlt, another Windows API




Back to top
PaoloItaly
Guest





PostPosted: Mon Oct 25, 2004 12:18 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

What is the dimension of your bitmap ?


Back to top
PaoloItaly
Guest





PostPosted: Mon Oct 25, 2004 1:53 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

Attach your loop (minimal), i will take a look


Back to top
PaoloItaly
Guest





PostPosted: Mon Oct 25, 2004 2:44 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

Quote:
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
Image1->Repaint();
}

Why you are refreshing the image inside your loop ?
If you want to give to user the idea to see realtime drawings :
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
if ((i % 20) == 0)
Image1->Repaint();
}
Image1->Repaint();
In this way you repaint the control only after 20 loops, but the user can
see the
evolution of your drawing



Back to top
Mark Borgerson
Guest





PostPosted: Mon Oct 25, 2004 3:34 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

In article <417d116a (AT) newsgroups (DOT) borland.com>,
[email]paolot (AT) FAKETHESPAMMERsirius-es (DOT) it[/email] says...
Quote:
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
Image1->Repaint();
}

Why you are refreshing the image inside your loop ?
If you want to give to user the idea to see realtime drawings :
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
if ((i % 20) == 0)
Image1->Repaint();
}
Image1->Repaint();
In this way you repaint the control only after 20 loops, but the user can
see the
evolution of your drawing

Even then, you should probably have a timer to control the repaint
process---if you want to show the progress in a uniform manner
independent of CPU speed.

In any case, ImRect includes about 1.4Mbytes (for 24-bit color),
so the CopyRect has to move a lot of Bytes. And it will take
a lot more CPU than a simple memcpy(), since the CopyRect has
to respect clipping rectangle and cope with stretching.

Then Image1->RePaint has to do the same thing over again to move
the image to the graphics hardware buffer.

You might optimize the loop by using CopyRect to move only
the part of the image that you have changed (the rectangle
you have drawn). Then, even at the end of the loop,
the CopyRect only has to cope with about 400 x 400
pixels---or about 1/2 the image area.

Mark Borgerson


Back to top
David Cameron
Guest





PostPosted: Tue Oct 26, 2004 7:36 pm    Post subject: Re: Slow graphics using TImage? Reply with quote


"Anders Törnqvist" <anders.tornqvist (AT) af (DOT) se> wrote

Quote:
I have done an application that draws a lot of lines that needs to be
updated quite a lot. I draw on an off-screen-bitmap and copy it to an
TImage. This is Extremely slow and CPU consuming. Is there another way?
What
am I doing wrong. I really need to speed up the application. HELP!

The method I use looks more or less like the code below:

. TImage *Image1;
. Graphics::TBitmap *pBitmap1;
.
....
.
. TRect ImRect;
. ImRect.Right = pBitmap1->Width;
. ImRect.Bottom = pBitmap1->Height;
.
. pBitmap1->Canvas->MoveTo(x1,y1);
. pBitmap1->Canvas->LineTo(x2,y2);
. Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
.
. Image1->Repaint();

/Anders Törnqvist



Are you are calling MoveTo - LineTo to display several *CONNECTED* lines in
a loop?
If so, it would be quicker to to create an array of TPoints and use the
TCavnvas::PolyLine function.
If the lines are disjointed you will still need to use MoveTo-LineTo.

HTH,
Dave



Back to top
Mark Borgerson
Guest





PostPosted: Wed Oct 27, 2004 3:40 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

In article <417df045$1 (AT) newsgroups (DOT) borland.com>, [email]anders.tornqvist (AT) af (DOT) se[/email]
says...
Quote:
Paolo:
The loop in the demo program represents the process of emptying a socket in
my real application, I have to refresh the image inside the loop otherwise
it´s not refreshed often enough. I do not refresh it after every little
change, quite the opposite. Because of it being to slow i can only refresh
about 2-3 times every second :(

Mark:
It is a good idea to only copy parts of the image, but since my real
application has a scrolling image where new data is inserted to the right
and the old information is moved to the left I guess it´s not really that
simple. But it should be possible, I´ll think about it...

Too bad that TCanvas and TImage don't have a ScrollRect function. Then

you could simply scroll your image to the left an appropriate number
of pixels, draw the new part on the right, and CopyRect to the
screen image. That is the way I handled strip charts many years
ago on the Macintosh and (I think) with OWL. There is a Windows
function ScrollDC() which will move the contents of a window, but
I can't find a wrapper for it for TCanvas or TImage.

Another possibility is to try the following:

1. Do a CopyRect from the screen to the offscreen bitmap, but
have the destination offset N pixels to the left. The
offscreen map now has the scrolled image--with some old
data at the right.
2. Draw the new data at the right of the offscreen map, including
clearing the rectangle, drawing axes, and new points.
3. call the Paint method, which does a CopyRect from the offscreen
image to the screen image.


The real test would be if this works when the scrolling chart is
partially hidden by another window in front of it.


Then you can tackle the real test----maintain a history and let the
user scroll back through the last N minutes (after the data input
has stopped). I suppose that you could do this with a REALLY large
offscreen bitmap, where you simply moved the source rectangle for
a CopyRect. That takes a LOT more memory than simply maintaining
a list of data points and regenerating the graph, though.



Mark Borgerson


Quote:
"Mark Borgerson" <mark2 (AT) oes (DOT) to> skrev i meddelandet
news:MPG.1be6bcdf23aabe39989681 (AT) newsgroups (DOT) borland.com...
In article <417d116a (AT) newsgroups (DOT) borland.com>,
[email]paolot (AT) FAKETHESPAMMERsirius-es (DOT) it[/email] says...
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
Image1->Repaint();
}

Why you are refreshing the image inside your loop ?
If you want to give to user the idea to see realtime drawings :
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
if ((i % 20) == 0)
Image1->Repaint();
}
Image1->Repaint();
In this way you repaint the control only after 20 loops, but the user can
see the
evolution of your drawing

Even then, you should probably have a timer to control the repaint
process---if you want to show the progress in a uniform manner
independent of CPU speed.

In any case, ImRect includes about 1.4Mbytes (for 24-bit color),
so the CopyRect has to move a lot of Bytes. And it will take
a lot more CPU than a simple memcpy(), since the CopyRect has
to respect clipping rectangle and cope with stretching.

Then Image1->RePaint has to do the same thing over again to move
the image to the graphics hardware buffer.

You might optimize the loop by using CopyRect to move only
the part of the image that you have changed (the rectangle
you have drawn). Then, even at the end of the loop,
the CopyRect only has to cope with about 400 x 400
pixels---or about 1/2 the image area.

Mark Borgerson





Back to top
Mark Borgerson
Guest





PostPosted: Wed Oct 27, 2004 8:56 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

In article <417fd75c$1 (AT) newsgroups (DOT) borland.com>, [email]anders.tornqvist (AT) af (DOT) se[/email]
says...
Quote:
Do you really think that will be faster? I first have to copy most of the
screen to the off-screen-bitmap and then copy everything back to the screen.
From what I have seen so far it is the copyRect that takes most time, not
the drawing...

I guess that depends on the complexity of the drawing and how often
you are adding data to the screen. If you are adding a single data
point at the right edge of the screen 100 times per second and
having to redraw all the onscreen data points and the grid lines
100 times per second, that could be quite time consuming It is
also unnecessary because smooth scrolling only requires you to
update the screen about 30 times per second.

A better algorithm might help a lot. For instance:

once per second, copy the screen to the offscreen bitmap. Offset
the CopyRect so that the offscreen map is moved left by 1 second.
Now draw the grid for the next 1 second's width at the right side As
points come in, plot them at or near the
right end of the graph. When you copyrect back to the screen, adjust the
source rectangle so it just includes the last point on the right.
Note that you will adjust the source rectangle with each point plotted,
but you will only need to CopyRect to the screen 30 times per second.
That part can be done with a timer method that calls repaint.

Note that the offscreen bitmap will have to be wider by 1 second's worth
of data.
Quote:

Is there a way to change the colordepth of an TBitmap? I changed it to
monochrome and the speed increased with 100 %. Monochrome is not a real
option but if I could set it to 8 bits that would be enough and I think the
copyRect would be quite a lot faster(?).

At some point, the width has to match the hardware, which is usually
set to 24bits these days.

Mark Borgerson


Quote:

"Mark Borgerson" <mark2 (AT) oes (DOT) to> skrev i meddelandet
news:MPG.1be9613b97ff945a989682 (AT) newsgroups (DOT) borland.com...
In article <417df045$1 (AT) newsgroups (DOT) borland.com>, [email]anders.tornqvist (AT) af (DOT) se[/email]
says...
Paolo:
The loop in the demo program represents the process of emptying a socket
in
my real application, I have to refresh the image inside the loop
otherwise
it´s not refreshed often enough. I do not refresh it after every little
change, quite the opposite. Because of it being to slow i can only
refresh
about 2-3 times every second :(

Mark:
It is a good idea to only copy parts of the image, but since my real
application has a scrolling image where new data is inserted to the right
and the old information is moved to the left I guess it´s not really that
simple. But it should be possible, I´ll think about it...

Too bad that TCanvas and TImage don't have a ScrollRect function. Then
you could simply scroll your image to the left an appropriate number
of pixels, draw the new part on the right, and CopyRect to the
screen image. That is the way I handled strip charts many years
ago on the Macintosh and (I think) with OWL. There is a Windows
function ScrollDC() which will move the contents of a window, but
I can't find a wrapper for it for TCanvas or TImage.

Another possibility is to try the following:

1. Do a CopyRect from the screen to the offscreen bitmap, but
have the destination offset N pixels to the left. The
offscreen map now has the scrolled image--with some old
data at the right.
2. Draw the new data at the right of the offscreen map, including
clearing the rectangle, drawing axes, and new points.
3. call the Paint method, which does a CopyRect from the offscreen
image to the screen image.


The real test would be if this works when the scrolling chart is
partially hidden by another window in front of it.


Then you can tackle the real test----maintain a history and let the
user scroll back through the last N minutes (after the data input
has stopped). I suppose that you could do this with a REALLY large
offscreen bitmap, where you simply moved the source rectangle for
a CopyRect. That takes a LOT more memory than simply maintaining
a list of data points and regenerating the graph, though.



Mark Borgerson


"Mark Borgerson" <mark2 (AT) oes (DOT) to> skrev i meddelandet
news:MPG.1be6bcdf23aabe39989681 (AT) newsgroups (DOT) borland.com...
In article <417d116a (AT) newsgroups (DOT) borland.com>,
[email]paolot (AT) FAKETHESPAMMERsirius-es (DOT) it[/email] says...
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
Image1->Repaint();
}

Why you are refreshing the image inside your loop ?
If you want to give to user the idea to see realtime drawings :
for(int i=0;i<300;i++) {
pBitmap1->Canvas->Rectangle(10,10,100+i,100+i);
Image1->Canvas->CopyRect(ImRect,pBitmap1->Canvas,ImRect);
if ((i % 20) == 0)
Image1->Repaint();
}
Image1->Repaint();
In this way you repaint the control only after 20 loops, but the user
can
see the
evolution of your drawing

Even then, you should probably have a timer to control the repaint
process---if you want to show the progress in a uniform manner
independent of CPU speed.

In any case, ImRect includes about 1.4Mbytes (for 24-bit color),
so the CopyRect has to move a lot of Bytes. And it will take
a lot more CPU than a simple memcpy(), since the CopyRect has
to respect clipping rectangle and cope with stretching.

Then Image1->RePaint has to do the same thing over again to move
the image to the graphics hardware buffer.

You might optimize the loop by using CopyRect to move only
the part of the image that you have changed (the rectangle
you have drawn). Then, even at the end of the loop,
the CopyRect only has to cope with about 400 x 400
pixels---or about 1/2 the image area.

Mark Borgerson








Back to top
Mark Borgerson
Guest





PostPosted: Wed Oct 27, 2004 11:40 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

In article <MPG.1be9ab5cf2e9aa5f989684 (AT) newsgroups (DOT) borland.com>, mark2
@oes.to says...
Quote:
In article <417fd75c$1 (AT) newsgroups (DOT) borland.com>, [email]anders.tornqvist (AT) af (DOT) se[/email]
says...
Do you really think that will be faster? I first have to copy most of the
screen to the off-screen-bitmap and then copy everything back to the screen.
From what I have seen so far it is the copyRect that takes most time, not
the drawing...

I guess that depends on the complexity of the drawing and how often
you are adding data to the screen. If you are adding a single data
point at the right edge of the screen 100 times per second and
having to redraw all the onscreen data points and the grid lines
100 times per second, that could be quite time consuming It is
also unnecessary because smooth scrolling only requires you to
update the screen about 30 times per second.

A better algorithm might help a lot. For instance:

once per second, copy the screen to the offscreen bitmap. Offset
the CopyRect so that the offscreen map is moved left by 1 second.
Now draw the grid for the next 1 second's width at the right side As
points come in, plot them at or near the
right end of the graph. When you copyrect back to the screen, adjust the
source rectangle so it just includes the last point on the right.
Note that you will adjust the source rectangle with each point plotted,
but you will only need to CopyRect to the screen 30 times per second.
That part can be done with a timer method that calls repaint.

Note that the offscreen bitmap will have to be wider by 1 second's worth
of data.

I got interested in the possibilities for this algorithm, and worked up

a quick demo, which seems to work quite well. If you would like the
program (for BCB 4) I'll zip up the executable (78K) and the sources
and email them to you. If I get another free afternoon soon, perhaps
I'll polish it up a bit and convert it to a more generic stripchart
component. Right now, it has a lot of numeric constants scattered
through the code.

Mark Borgerson

Back to top
A2011
Guest





PostPosted: Thu Oct 28, 2004 6:34 am    Post subject: Re: Slow graphics using TImage? Reply with quote

Hi Mark,

I would be very happy if you could send me the sourcecode to your example!
Sounds like something that could help me a lot.

/Anders (anders.tornqvist (AT) af (DOT) se)


"Mark Borgerson" <mark2 (AT) oes (DOT) to> skrev i meddelandet
news:MPG.1be9d1d6ba366072989685 (AT) newsgroups (DOT) borland.com...
Quote:
In article <MPG.1be9ab5cf2e9aa5f989684 (AT) newsgroups (DOT) borland.com>, mark2
@oes.to says...
In article <417fd75c$1 (AT) newsgroups (DOT) borland.com>, [email]anders.tornqvist (AT) af (DOT) se[/email]
says...
Do you really think that will be faster? I first have to copy most of
the
screen to the off-screen-bitmap and then copy everything back to the
screen.
From what I have seen so far it is the copyRect that takes most time,
not
the drawing...

I guess that depends on the complexity of the drawing and how often
you are adding data to the screen. If you are adding a single data
point at the right edge of the screen 100 times per second and
having to redraw all the onscreen data points and the grid lines
100 times per second, that could be quite time consuming It is
also unnecessary because smooth scrolling only requires you to
update the screen about 30 times per second.

A better algorithm might help a lot. For instance:

once per second, copy the screen to the offscreen bitmap. Offset
the CopyRect so that the offscreen map is moved left by 1 second.
Now draw the grid for the next 1 second's width at the right side As
points come in, plot them at or near the
right end of the graph. When you copyrect back to the screen, adjust the
source rectangle so it just includes the last point on the right.
Note that you will adjust the source rectangle with each point plotted,
but you will only need to CopyRect to the screen 30 times per second.
That part can be done with a timer method that calls repaint.

Note that the offscreen bitmap will have to be wider by 1 second's worth
of data.

I got interested in the possibilities for this algorithm, and worked up
a quick demo, which seems to work quite well. If you would like the
program (for BCB 4) I'll zip up the executable (78K) and the sources
and email them to you. If I get another free afternoon soon, perhaps
I'll polish it up a bit and convert it to a more generic stripchart
component. Right now, it has a lot of numeric constants scattered
through the code.

Mark Borgerson



Back to top
Atul Deopujari
Guest





PostPosted: Tue Nov 02, 2004 8:32 am    Post subject: Re: Slow graphics using TImage? Reply with quote

Hi Anders,
I have also been bugged by this problem for a long time. Finally, I
have got the solution.

The idea is as follows:
You draw on a bitmp and paste the bitmap on a PaintBox->Canvas. The
PaintBox is docked on the form on which you want to draw.
Setting PaintBox->ControlStyle to csOpaque is very important.
The form also has explicit horizontal and vertical scroll bars.

Looking at <http://bcbdev.com/faqs/faq34.htm> will also help.

Working with the implicit ScrollBars of the form is difficult. You have
to have explicit scrollbars and control what portion you have to draw
using the scrollbar properties. Also, depending on the size of the
drawing you have to adjust the scrollbar properties (Max, Min,
SmallChange, LargeChange, Pagesize).

If you wish, I can send you the code and the executable for a sample
application that I have written.

Best,
Atul



A2011 wrote:

Quote:
Hi Mark,

I would be very happy if you could send me the sourcecode to your example!
Sounds like something that could help me a lot.

/Anders (anders.tornqvist (AT) af (DOT) se)



Back to top
Mark Borgerson
Guest





PostPosted: Tue Nov 02, 2004 9:15 pm    Post subject: Re: Slow graphics using TImage? Reply with quote

In article <418745f6$1 (AT) newsgroups (DOT) borland.com>,
[email]atul_deopujari (AT) persistent (DOT) co.in[/email] says...
Quote:
Hi Anders,
I have also been bugged by this problem for a long time. Finally, I
have got the solution.

The idea is as follows:
You draw on a bitmp and paste the bitmap on a PaintBox->Canvas. The
PaintBox is docked on the form on which you want to draw.
Setting PaintBox->ControlStyle to csOpaque is very important.
The form also has explicit horizontal and vertical scroll bars.

Looking at <http://bcbdev.com/faqs/faq34.htm> will also help.

But I wouldn't consider those examples a great way to speed up
drawing, as the final code example:

void TForm1::PaintWaterLevel(void)
{
Graphics::TBitmap *MemBitmap = new Graphics::TBitmap;
MemBitmap->Width = PaintBox1->Width;
MemBitmap->Height = PaintBox1->Height;

MemBitmap->Canvas->Brush->Color = clWhite;
TRect rect = PaintBox1->ClientRect;
MemBitmap->Canvas->FillRect(rect);

rect.Top += 200 - (WaterLevel);
MemBitmap->Canvas->Brush->Color = clBlue;
MemBitmap->Canvas->FillRect(rect);

PaintBox1->Canvas->Draw(0,0,MemBitmap);
delete MemBitmap;
}

creates and deletes a bitmap with every call to PaintWaterLevel.
It would seem more efficient to have that bitmap created once
at startup, and deleted with the destructor.

The discussion in the cite about avoiding flicker is useful, though.


Quote:

Working with the implicit ScrollBars of the form is difficult. You have
to have explicit scrollbars and control what portion you have to draw
using the scrollbar properties. Also, depending on the size of the
drawing you have to adjust the scrollbar properties (Max, Min,
SmallChange, LargeChange, Pagesize).

If you wish, I can send you the code and the executable for a sample
application that I have written.

Best,
Atul



A2011 wrote:

Hi Mark,

I would be very happy if you could send me the sourcecode to your example!
Sounds like something that could help me a lot.

/Anders (anders.tornqvist (AT) af (DOT) se)




Mark Borgerson


Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Graphics) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.