 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
PaoloItaly Guest
|
Posted: Thu Oct 21, 2004 11:31 am Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Fri Oct 22, 2004 6:52 am Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Mon Oct 25, 2004 8:44 am Post subject: Re: Slow graphics using TImage? |
|
|
| 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
|
Posted: Mon Oct 25, 2004 12:18 pm Post subject: Re: Slow graphics using TImage? |
|
|
What is the dimension of your bitmap ?
|
|
| Back to top |
|
 |
PaoloItaly Guest
|
Posted: Mon Oct 25, 2004 1:53 pm Post subject: Re: Slow graphics using TImage? |
|
|
Attach your loop (minimal), i will take a look
|
|
| Back to top |
|
 |
PaoloItaly Guest
|
Posted: Mon Oct 25, 2004 2:44 pm Post subject: Re: Slow graphics using TImage? |
|
|
| 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
|
Posted: Mon Oct 25, 2004 3:34 pm Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Tue Oct 26, 2004 7:36 pm Post subject: Re: Slow graphics using TImage? |
|
|
"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
|
Posted: Wed Oct 27, 2004 3:40 pm Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Wed Oct 27, 2004 8:56 pm Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Wed Oct 27, 2004 11:40 pm Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Thu Oct 28, 2004 6:34 am Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Tue Nov 02, 2004 8:32 am Post subject: Re: Slow graphics using TImage? |
|
|
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
|
Posted: Tue Nov 02, 2004 9:15 pm Post subject: Re: Slow graphics using TImage? |
|
|
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 |
|
 |
|
|
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
|
|