在屏幕上快速绘制自定义格式的图像
Quickly draw custom format image on screen
我正在为我的游戏和其他应用程序开发自己的图像格式,我想让这些图像成为图像查看器。问题是,当我总是试图渲染更大的图像(1920x1080)时,它至少需要10秒,然后应用程序停止响应几秒钟,一切都消失了。
class Renderer{
//...
inline void GetRGB(unsigned int color,unsigned char &r,unsigned char &g,unsigned char &b){
r=((color>>16)&0xff); g=((color>>8)&0xff); b=((color)&0xff);
}
inline bool IsValidPos(unsigned int x,unsigned int y){
if((x>=0&&x<width)&&(y>=0&&y<height))return true;
else return false;
}
inline void GetPoint(unsigned int x,unsigned int y,unsigned int &color){
if(IsValidPos(x,y))
color=photostream[y*height+x];
}
void DrawPoint(unsigned int& x,unsigned int& y){
unsigned char r,g,b;
unsigned int col;
GetPoint(x,y,col);
//GetRGB(col,r,g,b);
SetPixel(hDC,x,y,col);
}
};
void RenderSHMP(ImageSHMP<unsigned int>& img,Renderer *renderer){
ImageSHMP<unsigned int> tmpImg(img.GetX(),img.GetY()); //create new image, this one will be shown
for(unsigned int x=0;x<tmpImg.GetX();x++)
for(unsigned int y=0;y<tmpImg.GetY();y++)
tmpImg.SetPoint(x,y,img.GetPoint(x,y)); //copy all data
if(img.GetX()>WIDTH||img.GetY()>HEIGHT){ //resize image if it is bigger than window resolution
double scale=1.0;
scale=static_cast<double>(WIDTH)/static_cast<double>(img.GetX());
tmpImg.Scale(scale);
}
//code above takes max. 0,2 seconds to execute
unsigned int col=0;
for(unsigned int x=0;x<tmpImg.GetX();x++)
for(unsigned int y=0;y<tmpImg.GetY();y++){
col=tmpImg.GetPoint(x,y);
renderer->SetPoint(x,y,col); //sets color in memory for later use
renderer->DrawPoint(x,y);
}
}
ImageSHMP包含类型为T的简单缓冲区,该缓冲区等于宽度*高度。所有数据都保存在这个缓冲区中,例如点[20,30]位于[30*height+20]。如何使它绘制得更快,这样窗口就不会处于"无响应"状态?我的意思是像简单的Windows图像查看器一样快
最终代码:
void RenderSHMP(ImageSHMP<unsigned int>& img,Renderer *renderer){
ImageSHMP<unsigned int> tmpImg(img.GetX(),img.GetY());
for(unsigned int x=0;x<tmpImg.GetX();x++)
for(unsigned int y=0;y<tmpImg.GetY();y++)
tmpImg.SetPoint(x,y,img.GetPoint(x,y));
if(img.GetX()>WIDTH||img.GetY()>HEIGHT){
double scale=1.0;
scale=static_cast<double>(WIDTH)/static_cast<double>(img.GetX());
tmpImg.Scale(scale);
}
int w=tmpImg.GetX(),h=tmpImg.GetY();
unsigned char r=0,g=0,b=0;
BITMAPINFO bmi;
HBITMAP hbm;
unsigned char *bytes=new unsigned char[w*h*3];
HDC hdc;
renderer->GetHDC(hdc);
unsigned int ctr=0;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = w;
bmi.bmiHeader.biHeight = h;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS,(void **)&bytes, NULL, 0);
HDC compatibleDC=CreateCompatibleDC(hdc);
HBITMAP hbmp = CreateCompatibleBitmap (hdc, w, h);
for(int y=int(h)-1;y>=0;--y){
for(int x=0;x<int(w);++x){
renderer->GetRGB(tmpImg.GetPoint(x,y),r,g,b);
bytes[ctr++]=b;
bytes[ctr++]=g;
bytes[ctr++]=r;
}
}
SetDIBits (hdc, hbmp, 0, h, bytes,&bmi, DIB_RGB_COLORS);
hbmp=(HBITMAP)SelectObject (compatibleDC, hbmp);
BitBlt(hdc, 0, 0, w, h, compatibleDC, 0, 0, SRCCOPY);
DeleteObject(SelectObject(compatibleDC, hbmp));
DeleteDC(compatibleDC);
delete [] bytes;
}
调用SetPixel 2M次需要一些时间。我认为你最好将图像大小调整为位图,然后将其绘制到屏幕上。例如使用CreateDIBSection
,然后通过ppvBits
填充,并使用BitBlit()绘制到屏幕本身。
简单的Windows图像查看器就能做到。
图像查看器不会逐像素绘制图像。您需要在一个系统调用中绘制整个图像。为此,您需要将图像解压缩到操作系统可以绘制的一些表示中,然后将解压缩后的图像绘制到屏幕上。在一个电话里。
在windows平台上,您可以使用SetDIBitsToDevice和StretchDIBits功能。只要正确填写BITMAPINFO,这些函数就可以从内存阵列中在窗口上绘制像素。
相关文章:
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- C++:main() 未捕获的异常的自定义格式
- 用于自定义间距的 .clang 格式选项
- 用于 XML 的自定义 wxDataObject 格式,用于复制粘贴支持
- 如何添加自定义关键字以 clang 格式被视为"class"?
- 自定义 {fmt} 格式化函数,具有编译时格式字符串检查功能
- Qt解析自定义文件格式
- 如何在C++中读取自定义格式的文本文件
- 自定义图像格式的奇怪OpenCV问题
- 如何在C++中定义自定义浮点格式(类型)
- 在屏幕上快速绘制自定义格式的图像
- 在c++中自定义日期格式
- 使用stringstreams的c++自定义字符串格式
- 如何布局自定义二进制文件格式
- 自定义存档格式文件读取
- 如何自定义手表窗口格式
- 如何自定义cin来读取我们自己的格式
- 如何创建、读取和写入自定义二进制文件格式
- 如何为自定义文件格式构建筛选器处理程序,以便可以通过windows搜索来搜索其内容
- 下载自定义文件格式