桌面共享中桌面图片对比取变化部分数据和还原显示
2010-07-12 15:11
387 查看
在做桌面共享时,最重要的就是桌面数据的对比压缩算法,怎么让数据在网络上传得最少而又不损耗桌面质量,有很多人直接用vnc的算法,但vnc虽然开源,又权威,但项目太大,看源码有点难看懂,前些天我实现了一个轻量级的算法,自己试了下,效果跟vnc不分上下,只是算法比较单一,不象vnc一个能适应不同的网络自动调整算法,下面来看下我的算法,分两部分
一、从一张图片中dif出变化部分数据,张桌面切成n个小正方形,比较每个正方形是否改变,如果改变则把整个正方形取出。
#define SETBIT(p, x) ((unsigned char)p[x/8] |= (1 << (x%8)))
static DWORD m_dwOutMaxSize;
static BYTE * m_lpOutBuffer;
static BYTE * m_lpPreData;
二、将变化部分拼成的图片(bmp),根据变化头还原数据到桌面图片数据中
一、从一张图片中dif出变化部分数据,张桌面切成n个小正方形,比较每个正方形是否改变,如果改变则把整个正方形取出。
#define SETBIT(p, x) ((unsigned char)p[x/8] |= (1 << (x%8)))
static DWORD m_dwOutMaxSize;
static BYTE * m_lpOutBuffer;
static BYTE * m_lpPreData;
从一张图片中dif出变化部分图片转成一张jgeg图片 BYTE *BMPtoFix(unsigned char * lpInData,int w,int h, unsigned long *lWidth ,unsigned long *lHeight, unsigned long *lHeadSize, unsigned long *lSize) { /* //bmp图片头 LPBITMAPINFOHEADER lpbi; lpbi = (LPBITMAPINFOHEADER)lpInData; //去头 lpInData += sizeof(BITMAPINFOHEADER); //图片必须是24bit,否则退出 if (lpbi->biBitCount != 24){ return NULL; } int w = lpbi->biWidth;///<宽 int h = lpbi->biHeight;///<高 */ if (w % 16){ return NULL; } int hCell = h/16;///<横向格数 /**如果不能整除则加一个格*/ if (hCell % 16) hCell++; int wCell = w / 16;///<竖向格数 /**这里用char的每一位来表示一个格的状态,0为不变,1为要更新, hSize用来表示头所占的字节数。 */ int hSize = (wCell*hCell)/8;///<屏幕所有的格数/8 = char 个数 if ((wCell*hCell)%8){ hSize++;///<不能整除加一个char } BOOL bPre = true; DWORD lBufSize = wCell*hCell*768 + hSize;///<构造这张图片在内存要用的大小,每一格16*16*3 = 768字节 /**分配全局内存,hSize + 图片数据*/ if (m_lpOutBuffer==NULL || m_dwOutMaxSize < lBufSize) { if (m_lpOutBuffer) GlobalFree (m_lpOutBuffer); m_lpOutBuffer = (BYTE *)GlobalAlloc (GMEM_FIXED, lBufSize); m_dwOutMaxSize = lBufSize;///<替换当前最大内存值 if (m_lpOutBuffer == NULL){ return NULL; } memset(m_lpOutBuffer, 0, lBufSize); } /**分配全局内存,old图片数据*/ if (m_lpPreData==NULL) { m_lpPreData = (BYTE *)GlobalAlloc (GMEM_FIXED, lBufSize-hSize); if (m_lpPreData == NULL){ return NULL; } memset(m_lpPreData,0, lBufSize-hSize); bPre = false; } BYTE *lpOutData = m_lpOutBuffer + hSize;///<用来存放输出的数据 DWORD lOutRowOffset = 0, lPreRowOffset = 0; /**全屏一格格操作,数据每一格offset 768*/ for (DWORD lPreRow = 0; lPreRow < wCell*hCell; lPreRow++, lPreRowOffset += 768) { DWORD iFound = 0;///与原数据对比,发现相同像素点个数 DWORD lPrePoint = lPreRowOffset; DWORD lInPoint = ((lPreRow%wCell) + (lPreRow/wCell)*w)*48; for (DWORD row = 0 ; row < 16 ; row ++) { /**如果超出当前屏幕则清0*/ if (lInPoint > w*h*3) { memset(m_lpPreData + lPrePoint, 0,48); } /**没超出就比较是否有不同的点*/ else { if (iFound == 0 && bPre) { for (int i = 0 ; i < 48; i++) { if (*(m_lpPreData + lPrePoint + i) != *(lpInData + lInPoint+i)) { iFound++; break; } }//end for }//end if memcpy(m_lpPreData + lPrePoint, lpInData + lInPoint, 48); //± } lPrePoint += 48; //16 * 3; lInPoint += w * 3; }//end for if (iFound == 0 && bPre) continue; SETBIT(m_lpOutBuffer, lPreRow); // memcpy(lpOutData + lOutRowOffset,m_lpPreData + lPreRowOffset, 768); //16*16*3 lOutRowOffset += 768; }//end for *lWidth = 16; *lHeight = lOutRowOffset/(16*3); *lHeadSize = hSize; *lSize = lOutRowOffset; return m_lpOutBuffer; }
二、将变化部分拼成的图片(bmp),根据变化头还原数据到桌面图片数据中
#define GETBIT(p, x) ((unsigned char)p[x/8] >> (x%8) & 1) BYTE * FixtoBMP(unsigned char * lpInData, unsigned long lWidth , unsigned long lHeight, unsigned char * lpHeadData, unsigned long lHeadSize, unsigned long w, unsigned long h) { if (w % 16) return NULL; int hCell = h / 16; if (hCell % 16){ hCell++; } int wCell = w / 16; int hSize = (wCell*hCell)/8; if ((wCell*hCell)%8){ hSize++; } if (hSize != lHeadSize) return NULL; DWORD lBufSize = (long)w * 3 * (long)h; //////////////////////////////////////////////////////////////////////////// if (m_lpPreData==NULL) { m_lpPreData = (BYTE *)GlobalAlloc (GMEM_FIXED, lBufSize); if (m_lpPreData == NULL) return NULL; memset(m_lpPreData,0, lBufSize); } DWORD lFullRow, row ; DWORD lFullRowOffset = 0, lFullPoint = 0; DWORD lPreRowOffset = 0, lPrePoint; for (lFullRow = 0; lFullRow < wCell*hCell; lFullRow++) { lPrePoint = ((lFullRow%wCell) + (lFullRow/wCell)*w)*48; if (GETBIT(lpHeadData, lFullRow))//²»Ïàͬ { for (row = 0 ; row < 16 ; row ++) { if (lPrePoint+1 < lBufSize) { memcpy(m_lpPreData + lPrePoint, lpInData + lFullPoint, 48); } lPrePoint += w * 3; lFullPoint += 48; //16 * 3 }//end for }//end if }//end for return m_lpPreData; }
相关文章推荐
- CSS 背景图片始终显示最中间的部分,不随窗口变化而收缩或变形。
- Android开发中调用系统相册上传图片到服务器OPPO等部分手机上出现短暂的显示桌面问题的解决方法
- ajax 页面部分先显示图片后出数据
- springMVC高级部分(数据校验,数据错误回显(自定义格式错误显示),拦截器,异常处理,文件上传,文件下载,springmvc运行流程以及springmvc和struts2对比)
- 调用系统相册上传图片到服务器--OPPO等部分手机上出现短暂的显示桌面问题
- [转]HTML图片部分显示--利用矩形区…
- DataGridView (四)将一个字段绑定到多列逐行显示后取值还原数据格式
- 利用COM组件IPicture读取jpg、gif、bmp图片文件数据和显示图片
- winform直接显示二进制数据中的图片
- IOS 截取部分图片并显示
- vb6.0 PictureBox图片框未显示部分的内容
- 解决listview显示全部数据和隐藏部分数据时候postion错乱
- 使用gridview时,会出现部分item数据显示不出来
- 使用XMLHttpRequest获取二进制数据显示图片
- 页面登陆框老是乱乱的?banner跨页图片缩小之后总是在侧面不能显示主要部分?哈哈~我来帮你忙~~
- angularjs 删除循环中的 promise 数据之后立马显示变化
- 请问 Wallpaper Calendar 是如何实现在桌面显示日历和输入数据的????
- 图片瀑布流的威力?最新数据显示Pinterest有望成为第二大社交网站,仅次于Facebook
- 如何在UIimageview里显示一张图片里的某一部分
- [ArcGIS Server] 如何在没有瓦片的地方显示“此级别无数据”这样的特定图片