镜像驱动截屏技术在数字语音教室中的应用
1.无需注册登录,支付后按照提示操作即可获取该资料.
2.资料以网页介绍的为准,下载后不会有水印.资料仅供学习参考之用.
密 惠 保
图像压缩算法
2.3.1 图像压缩步骤
图像压缩的目的在于以较少的数据来表示图像以节约存储费用,或者传输时间和费用。JPEG压缩算法可以用失真的压缩方式来处理图像[7],但失真的程度却是肉眼所无法辨认的。这也就是为什么JPEG会有如此满意的压缩比例的原因。
一.JPEG压缩分四个步骤实现:
1.颜色模式转换及采样;
2.DCT变换;
3.量化;
4.编码。
二.实现过程:
1.颜色模式转换及采样
RGB色彩系统是我们最常用的表示颜色的方式。JPEG采用的是YCbCr色彩系统。想要用JPEG基本压缩法处理全彩色图像,得先把RGB颜色模式图像数据,转换为YCbCr颜色模式的数据[8]。Y代表亮度,Cb和Cr则代表色度、饱和度。通过下列计算公式可完成数据转换。
Y=0.2990R+0.5870G+0.1140B
Cb=-0.1687R-0.3313G+0.5000B+128
Cr=0.5000R-0.4187G-0.0813B+128
人类的眼晴对低频的数据比对高频的数据具有更高的敏感度,事实上,人类的眼睛对亮度的改变也比对色彩的改变要敏感得多,也就是说Y成份的数据是比较重要的。既然Cb成份和Cr成份的数据比较相对不重要,就可以只取部分数据来处理。以增加压缩的比例。JPEG通常有两种采样方式:YUV411和YUV422,它们所代表的意义是Y、Cb和Cr三个成份的数据取样比例。
2. DCT变换
DCT变换的全称是离散余弦变换(Discrete Cosine Transform),是指将一组光强数据转换成频率数据,以便得知强度变化的情形。若对高频的数据做些修饰,再转回原来形式的数据时,显然与原始数据有些差异,但是人类的眼睛却是不容易辨认出来。
JPEG将整个亮度矩阵与色度Cb矩阵,饱和度Cr矩阵,视为一个基本单元称作MCU。每个MCU所包含的矩阵数量不得超过10个。例如,行和列采样的比例皆为4:2:2,则每个MCU将包含四个亮度矩阵,一个色度矩阵及一个饱和度矩阵。当图像数据分成一个8*8矩阵后,还必须将每个数值减去128,然后一一代入DCT变换公式中,即可达到DCT变换的目的。图像数据值必须减去128,是因为DCT转换公式所接受的数字范围是在-128到+127之间。
3. 量化
图像数据转换为频率系数后,还得接受一项量化程序,才能进入编码阶段。量化阶段需要两个8*8矩阵数据,一个是专门处理亮度的频率系数,另一个则是针对色度的频率系数,将频率系数除以量化矩阵的值,取得与商数最近的整数,即完成量化。当频率系数经过量化后,将频率系数由浮点数转变为整数,这才便于执行最后的编码。不过,经过量化阶段后,所有数据只保留整数近似值,也就再度损失了一些数据内容。
[资料来源:THINK58.com]
4. 编码
Huffman编码无专利权问题,成为JPEG最常用的编码方式,Huffman编码通常是以完整的MCU来进行的。编码时,每个矩阵数据的DC值与63个AC值,将分别使用不同的Huffman编码表,而亮度与色度也需要不同的Huffman编码表,所以一共需要四个编码表,才能顺利地完成JPEG编码工作。
屏幕捕获
3.2.1 全屏捕获
全屏捕获——最直接的实时捕获机制,就是在任何时候,不管需不需要,都把整个屏幕捕获下来[4]。在这种情形下,截屏系统将周期性的把显存中的反映当前屏幕的RGB数据拷贝出来生成一个位图。
具体实现代码如下:
think58好,好think58
[资料来源:http://think58.com]
void CatchFull::OnCatchFull( )
{
AfxGetMainWnd()->ShowWindow(SW_HIDE); think58好,好think58
HWND hWnd = ::GetDesktopWindow(); //获得屏幕的HWND.
HDC hScreenDC = ::GetDC(hWnd); //获得屏幕的HDC.
HDC MemDC = ::CreateCompatibleDC(hScreenDC);
RECT rect;
::GetWindowRect(hWnd, &rect);
SIZE screensize;
screensize.cx = rect.right - rect.left;
screensize.cy = rect.bottom - rect.top;
HBITMAP hBitmap = ::CreateCompatibleBitmap(hScreenDC, screensize.cx, screensize.cy);
HGDIOBJ hOldBMP = ::SelectObject(MemDC, hBitmap);
::BitBlt(MemDC, 0, 0 ,screensize.cx, screensize.cy, hScreenDC, rect.left, rect.top, SRCCOPY);
::SelectObject(MemDC, hOldBMP);
::DeleteObject(MemDC);
::ReleaseDC(hWnd, hScreenDC);
think58 [资料来源:http://think58.com]
[来源:http://think58.com]
if(this->m_bSaveToFile)
this->WriteBmpToFile(hBitmap);
AfxGetMainWnd()->ShowWindow(SW_NORMAL); //恢复窗口显示模式
} 内容来自think58 [来源:http://think58.com]
通过这一步将得到当前屏幕的位图句柄hBitmap,如果要将位图保存起来,还需要通过下一节的步骤。 内容来自think58
3.2.2 位图的保存
根据位图的句柄将位图写入文件,可以使用如下代码[14]: think58 [来源:http://www.think58.com]
void CatchFull::WriteBmpToFile(HBITMAP hBitmap)
{
HDC hDC =::CreateDC("DISPLAY", NULL, NULL, NULL);
//当前分辨率下每个像素所占字节数
int iBits = ::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES);
::DeleteDC(hDC); 内容来自think58 [资料来源:www.THINK58.com]
WORD wBitCount; //位图中每个像素所占字节数
if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits <= 24)
wBitCount = 24;
else
wBitCount = iBits;
DWORD dwPaletteSize = 0; //调色板大小,位图中像素字节大小
if (wBitCount <= 8)
dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);
BITMAP bm; //位图属性结构
::GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); 本文来自think58 [来源:http://www.think58.com]
BITMAPINFOHEADER bi; //位图信息头结构
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB; //BI_RGB表示位图没有压缩
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmBitsSize = ((bm.bmWidth * wBitCount+31)/32) * 4 * bm.bmHeight;
//为位图内容分配内存
HANDLE hDib = ::GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
HANDLE hPal = ::GetStockObject(DEFAULT_PALETTE); //处理调色板
HANDLE hOldPal = NULL;
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = SelectPalette(hDC,(HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
::GetDIBits(hDC, hBitmap, 0, (UINT) bm.bmHeight,(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,(BITMAPINFO*)lpbi, DIB_RGB_COLORS);
本文来自think58
[资料来源:http://think58.com]
if (hOldPal) //恢复调色板
{
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
think58好,好think58 [资料来源:www.THINK58.com]
[资料来源:www.THINK58.com]