现在做一个功率谱显示的程序,用到要把1000*500的WORD类型二维数组转为BITMAP,其中数组中存储颜色索引值。程序每100ms接收一行新数据并进行循环刷新显示,也就是原499行数据是不变的,只是在二维数组的最后添加一行新数据,删除其原来的第一行数据。现在的问题是程序能运行,但反应很慢。不知该如何优化。我的设想是每次将新的数据生成的图像与原图进行拼接,这样就不用刷新原来的499行元素,只刷新新的一行就可以了。但不知道具体该如何实现。下图为某安捷伦软件的截图:
下面为我写的代码:
void CGraghCtrl::DrawSpectrogram(CDC* pDC)//绘制瀑布图
{
for(int i=0;i<vctPubu.size();i++)
{
for(int j=0;j<vctPubu[i].size();j++)
{
COLORREF yColor=Data2Color(vctPubu[i][j]);
CPen pen(PS_SOLID, 2, yColor);
pDC->SelectObject(&pen);
pDC->MoveTo(ColxToScreen(j), ColyToScreen(i));
pDC->LineTo(ColxToScreen(j+1), ColyToScreen(i));
}
}
}
其中vctPubu中为存储颜色索引的二维vector,Data2Color()为自定义的word转Color的函数。这段代码直接在onpaint中调用:
// 消息响应函数
void CGraghCtrl::OnPaint()
{
WaveMiddle=(m_rcClient.Height()- m_layout.page.nBottomMargin-m_layout.page.nTopMargin)/2;
CPaintDC dc(this);
CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象
MemDC.CreateCompatibleDC(&dc);//随后建立与屏幕显示兼容的内存显示设备
MemBitmap.CreateCompatibleBitmap(&dc,m_rcClient.Width(),m_rcClient.Height());
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
DrawSpectrogram(&MemDC);// 这个函数完成图形的绘制
dc.BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), &MemDC, 0, 0, SRCCOPY);//将内存中的图拷贝到屏幕上进行显示
MemDC.SelectObject(pOldBit);
MemBitmap.DeleteObject();
MemDC.DeleteDC();
}
恳请大侠帮忙
没做过,给你提供些资料。
1.http://blog.csdn.net/liehuo123/article/details/6561100
2.http://blog.csdn.net/jiangxinyu/article/details/6222302
3.http://hi.baidu.com/posithe/blog/item/3789f30134b90b8ce850cd63.html
谢谢lonely_rain的回答,虽然作用不大。继续在线等
@薄祥雷: 我想作用也大不了,我没做过,也给不了实质性的意见。有多力使多大劲呗!
@lonely_rain: 呵呵,谢谢回答了,同样让我长了不少见识,以后有啥粗笨的活,可以找小弟帮忙
@薄祥雷: 多交流,多沟通,相互学习呗!
其实你这里的问题并不是其余的499行完全不刷新,虽然有499行数据是不变的,但是他们在屏幕上的位置是发生了平移的,现在第i行是原来的第i+1行的数据,而你的显示区域是不变的,刷新在所难免。你现在发现反应很慢,应该是因为接受到新一行数据之后会进行所有数据的一个绘制。
解决方案可以去看一下双缓存方面的东西,在显示当前数据、接受下一行数据的之前先在第二片缓存中绘制除去第一行数据的那些数据,在接收到最新一行数据后更新到第二片缓存区域,然后第二片缓存的绘制时间只是绘制一行数据,这样应该不会感觉缓慢了。
谢谢你的回答,我试试
@lonely_rain: 我感觉也是所有数据必然会参与刷新,但我感觉 pDC->MoveTo(ColxToScreen(j), ColyToScreen(i)); pDC->LineTo(ColxToScreen(j+1), ColyToScreen(i));的方式是不是效率很低,有没有其他将数组数据转为图像的方法呢
@薄祥雷: 是不是要用到多线程呢
@薄祥雷: 网上找个bmp类,直接写到缓存。
@Wang Hui: 多线程也可以,非多线程也没问题,当然为了处理起来更迅速一点,多线程比较好。
作过类似的东西,附加码识别时用到过。我把代码贴你。
public Bitmap GetBitMap(Matrix _matrix,bool isMap ) { if (_matrix == null) { throw new ImageMapException("图片数据为空!!"); } Bitmap bmp = new Bitmap(_matrix.ColCount, _matrix.RowCount); for (int i = 0; i < bmp.Width; i++) { for (int j = 0; j < bmp.Height; j++) { Color tmpColor; if (!isMap) { tmpColor = Color.FromArgb(_matrix[i, j]); } else { if (_matrix[i, j] == 0) { tmpColor = Color.FromArgb(IM_WHITE); } else { tmpColor = Color.FromArgb(IM_BLACK); } } bmp.SetPixel(i, j, tmpColor); } } return bmp; }
Matrix 就是一个存了个二维数组的类
谢谢你的回答
@薄祥雷: tmpColor = Color.FromArgb(IM_BLACK)的颜色获取方式,以及 bmp.SetPixel(i, j, tmpColor);对我启发很大,我想这应该比pdc->moveto lineto 的方式效率高点
@薄祥雷:我还想问一下,获得的bmp怎么显示出来呢?
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
DrawSpectrogram(&MemDC);// 这个函数完成图形的绘制
dc.BitBlt(0, 0, m_rcClient.Width(), m_rcClient.Height(), &MemDC, 0, 0, SRCCOPY);
替换MemBitmap?
上面的追问貌似有点低级,但请帮助啊