who can explain this for me?(Big Image To Draw) Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

who can explain this for me?(Big Image To Draw)

Post by xin.songtao »

Hi, wxFans!
I use wxBufferedPaintDC to draw the big image ,the image size is larger than 10000*5000,I divide the image to blocks,when the image loaded,the blocks size is small(500*500),and then I use a wxBitmap vector to store the blocks.
In OnPaint , I draw block by block, the following is the code what I use, My question is that,
why all the blocks can not be shown in the machine which has 1024M physical memory. but the machine which has 2048M physical memory.

My code:
Divide the pImg;

Code: Select all

m_IsBitmapVectorOK = false;	

m_numOfBlocks.x  = (int) ceil(pImg->GetWidth()/(float)BLOCKSIZEWIDTH);
m_numOfBlocks.y  = (int) ceil(pImg->GetHeight()/(float)BLOCKSIZEHEIGHT);

if (m_vecBitmap.begin()!=m_vecBitmap.end())
{
	m_vecBitmap.clear();
}	
int index = 0;
for(int j=0;j!=m_numOfBlocks.y;j++)
{
	for(int i=0;i!=m_numOfBlocks.x;i++)
	{
		{
			wxImage subImg = pImg->GetSubImage(wxRect(	i*BLOCKSIZEWIDTH,
				j*BLOCKSIZEHEIGHT,
				i==m_numOfBlocks.x-1?m_nOrigWidth-i*BLOCKSIZEWIDTH:BLOCKSIZEWIDTH,
				j==m_numOfBlocks.y-1?m_nOrigHeight-j*BLOCKSIZEHEIGHT:BLOCKSIZEHEIGHT));

			if (!subImg.IsOk())
			{				
				return false;
			}
			m_vecBitmap.push_back( wxBitmap(subImg) );
			index++;
		}	
	}
}
m_IsBitmapVectorOK = true;		

OnPaint event

Code: Select all


			wxPaintDC dc(this);
			wxBufferedDC bufferDc(&dc);

wxMemoryDC memDc;

bufferDc.SetBackground(wxColour(218,218,218));
bufferDc.Clear();
int index = 0;

if (m_IsBitmapVectorOK)
{
	bufferDc.DestroyClippingRegion();
	bufferDc.SetClippingRegion(wxPoint(0,0),GetClientSize());
	
	for(int j=0;j<m_numOfBlocks.y;j++)
	{
		for(int i=0;i<m_numOfBlocks.x;i++)
		{			
			{
				memDc.SelectObject( m_vecBitmap.at(index) );					
				bufferDc.SetUserScale( m_dZoomFactor,m_dZoomFactor );	
				wxPoint pt = wxPoint(
					i*BLOCKSIZEWIDTH,			//BLOCKSIZEWIDTH is 500
					j*BLOCKSIZEHEIGHT			//BLOCKSIZEHEIGHT is 500
					);
				bufferDc.Blit(pt,
					wxSize(m_vecBitmap.at(index).GetWidth(),m_vecBitmap.at(index).GetHeight()),
					&memDc,
					wxPoint(0,0),
					wxCOPY);

				bufferDc.SetUserScale( 1.0,1.0 );
				memDc.SelectObjectAsSource(wxNullBitmap);
			}
			index++;
		}
	}
}
In the two ways, It will display all the blocks(the whole image).
first:

Code: Select all

wxBufferedPaintDC bufferDc(this);  // when repleace the wxBufferedPaintDC with wxPaintDC ,it will Display all the blocks too, but  Flicker
second:
to use the compute which has more physical memory.

I want to know why? Is the bufferDc question?

thanks for all the reply!!
Last edited by xin.songtao on Sun Mar 22, 2009 9:11 am, edited 1 time in total.
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Post by catalin »

Maybe there is just not enough memory for the buffer?...

If you draw only one image or else if do not have overlapping drawings, you can use a regular wxPaintDC but disable erase background event and should not get any flicker.
Edit: This is "ok" if you repaint the whole surface every time, otherwise you may get "leftovers"/"artifacts"
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

Maybe there is just not enough memory for the buffer?...
I agree with you.

And i also do this ,but the flicker is still exist.
EVT_ERASE_BACKGROUND( MyCtrl::OnEraseBackGround)

Maybe I will try the other ways.

Thanks !
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Post by catalin »

AFAIK the flicker is due to the multiple Blit-s.
But why do you still use the wxMomoryDC+Blit? You can directly paint the blocks on the wxPaintDC at (i*blockW, j*blockH) coordinates, right? :roll:

p.s. why don't you move the SetUserScale calls outside the 'for' loops?
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

1、
p.s. why don't you move the SetUserScale calls outside the 'for' loops?
This is a imperfect code, i have move the SetUserScale outside the loops.
But why do you still use the wxMomoryDC+Blit? You can directly paint the blocks on the wxPaintDC at (i*blockW, j*blockH) coordinates, right? Rolling Eyes
2、
I had a test on the the machine which has 1024M physical memory,and use the wxPaintDC+wxMemoryDC, the whole image could not display yet. (the image size is 10000*5000).

3、
while, to use the wxBufferedPaintDC + DrawBitmap to draw,it will seem that overdo compression to the image,when the zoomfactor small than 1.0. :( :(
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Post by catalin »

xin.songtao wrote:
But why do you still use the wxMomoryDC+Blit? You can directly paint the blocks on the wxPaintDC at (i*blockW, j*blockH) coordinates, right? Rolling Eyes
2、
I had a test on the the machine which has 1024M physical memory,and use the wxPaintDC+wxMemoryDC, the whole image could not display yet. (the image size is 10000*5000).
I was suggesting that you do the painting without a wxMemoryDC when you do not use double buffering.
xin.songtao wrote:3、
while, to use the wxBufferedPaintDC + DrawBitmap to draw,it will seem that overdo compression to the image,when the zoomfactor small than 1.0. :( :(
I do not understand this part..
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

I should append some pictures.

when use the BufferDC,
bufferDc.SetUserScale( m_dZoomFactor,m_dZoomFactor );
bufferDc.DrawBitmap( bitmap,pt );
bufferDc.SetUserScale( 1.0,1.0);


the left is normal, the right is bufferDC

Image
catalin
Moderator
Moderator
Posts: 1618
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Post by catalin »

Yes, that is correct.

When you set the user scale only for the bufferDC it will have no effect, since you will actually see what is drawn on the "normal" DC.
So if you need to change the user scale do it for the "normal" DC (only..).

Mind that for a bitmap with size (w, h) drawn on a DC with user scale (uX, uY) on the screen you'll have ( w*uX, h*uY ) surface in pixels used, but the size of the bitmap is always the same (w, h).
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

Thanks catalin!
I have change the bufferDC to wxPaintDC.
sis
Earned a small fee
Earned a small fee
Posts: 21
Joined: Wed Mar 18, 2009 6:07 pm

solution for stained image under msw with buffer

Post by sis »

xin.songtao wrote:while, to use the wxBufferedPaintDC + DrawBitmap to draw,it will seem that overdo compression to the image,when the zoomfactor small than 1.0. Sad Sad
or just use this:

I had the same problem.
I received the solution
http://trac.wxwidgets.org/ticket/10675#comment:3
----
"troelsk… added:

Do you call dc.DrawBitmap somewhere here?

If so, try dropping in this line and see if it helps
::SetStretchBltMode((HDC)dc.GetHDC(), COLORONCOLOR);

(http://trac.wxwidgets.org/ticket/3400)"
----
And ::SetStretchBltMode((HDC)dc->GetHDC(),COLORONCOLOR);
did repair MyPrintOut::OnPrintPage as well.
xin.songtao
Experienced Solver
Experienced Solver
Posts: 86
Joined: Wed Apr 18, 2007 6:10 am
Location: Shanghai China

Post by xin.songtao »

wxBufferedPaintDC:
Note that at the time of writing,
using buffering with wxBUFFER_CLIENT_AREA does not work with scaling
(SetUserScale).
Post Reply