linux应用Xlib来显示内存图像数据到窗口的方式
来源:互联网 发布:linux下rime配置 编辑:程序博客网 时间:2024/05/20 22:26
由于需要动态的将相机取得到图像数据动态的在窗口中显示,开始时试过好几个开源的显示库都没有达到想要到效果,SDL是最接近想要的效果的,可是目前到版本对于多窗口的显示支持还不完善,最终决定应用xlib来直接显示,归根结底这些库最终都是应用xlib来显示的。
在linux下 的xlib显示内存图像数据,几个需要的对象是:
unsigned long m_WinID;窗口句柄
Display * m_display;
GC m_gc;
XImage * m_pDSPImage;
pthread_mutex_t m_lock_Screen; //显示对象的互斥
// 绘图控制
int m_nDrawStartX; //起始坐标 x
int m_nDrawStartY; //起始坐标 y
int m_nDrawWidth; //绘图宽度
int m_nDrawHeight; //绘图高度
这些对象需要初始化:
根据传入的图像的宽高和位深来初始化相关对象资源
void DIBCreate(ULONG Width, ULONG Height, ULONG nColor) {if (0 == m_WinID)return;pthread_mutex_lock(&m_lock_Screen);m_display = XOpenDisplay(NULL);if (!m_display) {return;}unsigned long valuemask = 0;XGCValues values;m_gc = XCreateGC(m_display, (Window) m_WinID, valuemask, &values);if (!m_gc) {XCloseDisplay(m_display);m_display = NULL;return;}Visual *visual = DefaultVisual(m_display, DefaultScreen(m_display));int imagedepth = DefaultDepth(m_display,DefaultScreen(m_display));////////////////////////////////////////////创建屏幕大小的XImage的图像缓冲区,主要由于图像再大显示最大也超不出屏幕,提高显示效率 unsigned int display_width, display_height;//屏幕尺寸display_width = DisplayWidth(m_display, DefaultScreen(m_display));display_height = DisplayHeight(m_display, DefaultScreen(m_display));m_pDSPImage = XCreateImage(m_display, visual, imagedepth, ZPixmap, 0, NULL,display_width, display_height, 32, 0);if (m_pDSPImage) {m_pDSPImage->data = new char[display_width * display_height* m_pDSPImage->bits_per_pixel / 8];}pthread_mutex_unlock(&m_lock_Screen);}
释放显示的相关资源方法:
void DIBFree() {pthread_mutex_lock(&m_lock_Screen);if (m_gc) {XFreeGC(m_display, m_gc);m_gc = NULL;}if (m_display) {XCloseDisplay(m_display);m_display = NULL;}if (m_pDSPImage) {XDestroyImage(m_pDSPImage);//XDestroyImage方法会删除ximage对象的图像数据的内存
m_pDSPImage = NULL;}pthread_mutex_unlock(&m_lock_Screen);}
显示时的处理:
下面方法可以根据上面初始化的对象获得窗口的具体大小
XWindowAttributes win_attr;
XGetWindowAttributes(m_display, (Window) m_WinID, &win_attr); //主要获得显示窗口的大小
下面的显示部分充分考虑到窗口的大小在小于图像大小时的部分刷新跟缩放的操作,缩放时应用临近插值方法,提高显示效率。
pthread_mutex_lock(&m_lock_Screen);XWindowAttributes win_attr;XGetWindowAttributes(m_display, (Window) m_WinID, &win_attr); //主要获得显示窗口的大小int DrawWidth;int DrawHeight;if (m_nDrawStartX > 0) {DrawWidth= (win_attr.width - m_nDrawStartX) < m_nDrawWidth ? (win_attr.width- m_nDrawStartX): m_nDrawWidth;} else {DrawWidth= win_attr.width > m_nDrawWidth + m_nDrawStartX ? m_nDrawWidth+ m_nDrawStartX: win_attr.width;}if (m_nDrawStartY > 0) {DrawHeight= (win_attr.height - m_nDrawStartY) < m_nDrawHeight ? (win_attr.height- m_nDrawStartY): m_nDrawHeight;} else {DrawHeight= win_attr.height > m_nDrawHeight + m_nDrawStartY ? m_nDrawHeight+ m_nDrawStartY: win_attr.height;}ImageData2DisplayData(pData, nColor, uWidth, uHeight,DefaultVisual(m_display, DefaultScreen(m_display)),m_pDSPImage, OffX, OffY, uWidth, uHeight,//内存图像的偏移位置及图像数据的长宽 m_nDrawStartX, m_nDrawStartY, m_nDrawWidth, m_nDrawHeight,DrawWidth, DrawHeight);//需要将图像数据转换为ARGB格式的数据 XPutImage(m_display, (Drawable) m_WinID, m_gc, m_pDSPImage, 0, 0,m_nDrawStartX > 0 ? m_nDrawStartX : 0,m_nDrawStartY > 0 ? m_nDrawStartY : 0, //需要考虑窗口绘制的偏移为负值的情况DrawWidth, DrawHeight);pthread_mutex_unlock(&m_lock_Screen);
图像数据转换为显示数据方法:
//显示需要转换的函数,应用临近插值方式进行缩放int ImageData2DisplayData(PUCHAR pSrc, int SrcBpp, DWORD Width, DWORD Height,Visual *visual, XImage *DstImage,DWORD offX, DWORD offY, DWORD offWidth, DWORD offHeight,//源数据的区域int offX_dst, int offY_dst, DWORD dstWidth, DWORD dstHeight,//绘制到屏幕上的区域int windowWidth, int windowHeight);//窗口的大小{ unsigned long r, g, b, rmask, gmask, bmask, xcol; int rshift, gshift, bshift, bperpix, bperline, border; rmask = visual->red_mask; gmask = visual->green_mask; bmask = visual->blue_mask; rshift = 7 - CImageAlgorithm::highbit(rmask); gshift = 7 - CImageAlgorithm::highbit(gmask); bshift = 7 - CImageAlgorithm::highbit(bmask); bperline = DstImage->bytes_per_line; bperpix = DstImage->bits_per_pixel; border = DstImage->bitmap_bit_order; int nSrcBit = SrcBpp/8; int nSrcLineBit = Width*nSrcBit; int nImgBit = bperpix/8; int srcOffx = -(offX_dst>0?0:offX_dst)*offWidth/dstWidth + offX; int srcOffy = -(offY_dst>0?0:offY_dst)*offHeight/dstHeight + offY; if(24==SrcBpp) { if(32 == bperpix) { PUCHAR ip, pp; pp = pSrc; for(int i = 0; i < dstHeight; i++){ int srcH = i * offHeight/dstHeight + srcOffy; if(srcH>=Height || i>=(DstImage->height)||i>=windowHeight) break; pp = pSrc + (Height-1-srcH)*nSrcLineBit; //显示图像要上下对调 ip = (PUCHAR)DstImage->data + i*bperline; for(int j = 0; j < dstWidth; j++){ int srcW = j * offWidth/dstWidth + srcOffx; if(srcW>=Width || j>=(DstImage->width)||j>=windowWidth) break; memcpy(ip,pp+3*srcW,3); ip+=4; } } } else if(24 == bperpix){ PUCHAR ip, pp; pp = pSrc; for(int i = 0; i < dstHeight; i++){ int srcH = i * offHeight/dstHeight + srcOffy; if(srcH>=Height || i>=(DstImage->height)||i>=windowHeight)break; pp = pSrc + (Height-1-srcH)*nSrcLineBit; ip = (PUCHAR)DstImage->data + i*bperline; for(int j = 0; j < dstWidth; j++){ int srcW = j * offWidth/dstWidth + srcOffx; if(srcW>=Width || j>=(DstImage->width)||j>=windowWidth)break; memcpy(ip,pp+3*srcW,3); ip+=3; } } } } else if(8==SrcBpp){ if(32 == bperpix) { PUCHAR ip, pp; pp = pSrc; for(int i = 0; i < dstHeight; i++){ int srcH = i * offHeight/dstHeight + srcOffy; if(srcH>=Height || i>=(DstImage->height)||i>=windowHeight)break; pp = pSrc + (Height-1-srcH)*nSrcLineBit; ip = (PUCHAR)DstImage->data + i*bperline; for(int j = 0; j < dstWidth; j++){ int srcW = j * offWidth/dstWidth + srcOffx; if(srcW>=Width || j>=(DstImage->width)||j>=windowWidth)break; memset(ip,*(pp+srcW),3); ip+=4; } } } else if(24 == bperpix){ PUCHAR ip, pp; pp = pSrc; for(int i = 0; i < dstHeight; i++){ int srcH = i * offHeight/dstHeight + srcOffy; if(srcH>=Height || i>=(DstImage->height)||i>=windowHeight)break; pp = pSrc + srcH*nSrcLineBit; ip = (PUCHAR)DstImage->data + (dstHeight - 1 - i)*bperline; //显示图像要上下对调 for(int j = 0; j < dstWidth; j++){ int srcW = j * offWidth/dstWidth + srcOffx; if(srcW>=Width || j>=(DstImage->width)||j>=windowWidth)break; memset(ip,*(pp+srcW),3); ip+=3; } } } } return 0;}
- linux应用Xlib来显示内存图像数据到窗口的方式
- 图像的显示方式
- 应用窗口的从创建到显示的过程
- linux下 X11桌面 一个C语言调用Xlib创建窗口的小列子
- 如何用C#来实现以动画的方式显示图像
- 窗口和线程漫谈之工作线程如何将数据的处理结果显示到窗口
- 彻底解决显示Opencv中Mat图像到Mfc窗口问题
- Imshow直接显示图像到窗口控件 good!!
- 带实证明,imshow是能显示数据归一化到0到1的图像的!
- 使用JS来显示浏览器的窗口
- 图像数据的拉伸显示
- Xlib 窗口属性
- Xlib 窗口属性
- 在linux窗口上显示YUV图像源代码
- 数据窗口显示的报表的形式如何导出到EXCEL文件
- Delphi图像处理 -- 获取窗口或设备的图像数据
- X11下几种显示图像的方式
- X11下几种显示图像的方式
- android JNI 分析:
- 关闭占用某端口的进程
- 数据仓库生命周期的一些疑惑
- struts文件下载
- 浅谈字节序(Byte Order)及其相关操作(转自老赵)
- linux应用Xlib来显示内存图像数据到窗口的方式
- 设置eclipse console 显示条数
- Android游戏框架AndEngine使用入门
- struts 2.0 图片上传
- 十进制转二进制
- Android学习笔记--事件机制
- codec engine工程中使用ccs下编译的lib库
- js表单验证控制代码大全
- 新的起点