自己写远程控制软件之图像压缩

来源:互联网 发布:java struct2 编辑:程序博客网 时间:2024/05/05 14:28
由于要压缩成 JPG 文件,我用的是 Intel ilj 库,别说你没听过哦,可压缩 YUYV和 Bmp,以下是我的 JpegEncoder,
使用简单,接口清晰,谁用谁知道。至于在客户端显示 JPG,我就交给 OleLoadPicture 了,因为 ilj 在解压的时候,有时会内存泄露,但是 OleLoadPicture 在使用时会有个问题就是如果 JPG 文件本身有问题,会造成 OleLoadPicture 死锁,我查了一下,据说是 Microsoft 的 BUG,这么长时间了也不知道 Fix 没有。不过 OleLoadPicture 死锁在这个程序是不太可能出现的,我说的是我在公司的情况,细节我就不说了。

#ifndef JPEGEncoder_H#define JPEGEncoder_H//////////////////////////////////////////////////////////////////////////#include <Windows.h>//////////////////////////////////////////////////////////////////////////#include "ijl.h"//////////////////////////////////////////////////////////////////////////#pragma comment(lib, "ijl15l.lib")//////////////////////////////////////////////////////////////////////////template <DWORD dwUnique>class JPEGEncoderT{public:JPEGEncoderT(){ijlInit(&m_jpeg);}~JPEGEncoderT(){ijlFree(&m_jpeg);}//////////////////////////////////////////////////////////////////////////IJLERR Encode(DWORD dwWidth, DWORD dwHeight, LPVOID lpRGBSrc, DWORD dwSrcLength, LPVOID lpJPEGDst, DWORD dwDstLength, LPDWORD lpJPEGSize, DWORD dwBitCount){DWORD dwByteCount = dwBitCount / 8;if (lpRGBSrc == NULL || lpJPEGDst == NULL || dwSrcLength == 0 || dwDstLength == 0 || lpJPEGSize == NULL) {return IJL_MEMORY_ERROR;}if (dwDstLength < (dwWidth * dwHeight)) {return IJL_BUFFER_TOO_SMALL;}IJLERR ijlError= IJL_RESERVED;m_jpeg.upsampling_reqd= FALSE;m_jpeg.cconversion_reqd= FALSE;m_jpeg.DIBBytes= (LPBYTE) lpRGBSrc;m_jpeg.JPGBytes= (LPBYTE) lpJPEGDst;m_jpeg.DIBWidth= dwWidth;m_jpeg.DIBHeight= -dwHeight;m_jpeg.JPGWidth= dwWidth;m_jpeg.JPGHeight= dwHeight;m_jpeg.DIBSubsampling= IJL_NONE;m_jpeg.JPGFile= NULL;m_jpeg.JPGSizeBytes= dwDstLength;m_jpeg.jquality= 100;//////////////////////////////////////////////////////////////////////////m_jpeg.DIBChannels    = dwByteCount;m_jpeg.JPGChannels    = dwByteCount;m_jpeg.DIBPadBytes    = IJL_DIB_PAD_BYTES(m_jpeg.DIBWidth, dwByteCount);switch (dwBitCount) {case 24:m_jpeg.DIBColor       = IJL_BGR;m_jpeg.JPGColor       = IJL_YCBCR;m_jpeg.JPGSubsampling = IJL_411;break;case 32:m_jpeg.DIBColor       = IJL_RGBA_FPX;m_jpeg.JPGColor       = IJL_YCBCRA_FPX;m_jpeg.JPGSubsampling = IJL_4114;break;default:return IJL_UNSUPPORTED_BYTES_PER_PIXEL;break;}//////////////////////////////////////////////////////////////////////////ijlError = ijlWrite(&m_jpeg, IJL_JBUFF_WRITEWHOLEIMAGE);if (ijlError == IJL_OK) {*lpJPEGSize = m_jpeg.JPGSizeBytes;}return ijlError;}//////////////////////////////////////////////////////////////////////////IJLERR Encode(DWORD dwWidth, DWORD dwHeight, LPVOID lpYUYVSrc, DWORD dwSrcLength, LPVOID lpJPEGDst, DWORD dwDstLength, LPDWORD lpJPEGSize){if (lpYUYVSrc == NULL || lpJPEGDst == NULL || dwSrcLength == 0 || dwDstLength == 0 || lpJPEGSize == NULL) {return IJL_MEMORY_ERROR;}if (dwDstLength < (dwWidth * dwHeight >> 1)) {return IJL_BUFFER_TOO_SMALL;}IJLERR ijlError = IJL_RESERVED;m_jpeg.DIBBytes= (LPBYTE) lpYUYVSrc;m_jpeg.JPGBytes= (LPBYTE) lpJPEGDst;m_jpeg.DIBWidth= dwWidth;m_jpeg.DIBHeight= dwHeight;m_jpeg.JPGWidth= m_jpeg.DIBWidth;m_jpeg.JPGHeight= m_jpeg.DIBHeight;m_jpeg.JPGFile= NULL;m_jpeg.JPGSizeBytes= dwDstLength;m_jpeg.jquality= 100;//////////////////////////////////////////////////////////////////////////m_jpeg.DIBChannels= 3;m_jpeg.JPGChannels= m_jpeg.DIBChannels;m_jpeg.DIBColor= IJL_YCBCR;m_jpeg.JPGColor= IJL_YCBCR;m_jpeg.DIBSubsampling= IJL_422;m_jpeg.JPGSubsampling= IJL_422;//////////////////////////////////////////////////////////////////////////ijlError = ijlWrite(&m_jpeg, IJL_JBUFF_WRITEWHOLEIMAGE);if (ijlError == IJL_OK) {*lpJPEGSize = m_jpeg.JPGSizeBytes;}return ijlError;}private:JPEG_CORE_PROPERTIES m_jpeg;};//////////////////////////////////////////////////////////////////////////typedef JPEGEncoderT<0> CJPEGEncoder;//////////////////////////////////////////////////////////////////////////#endif

把显示的代码也贴上来,(只要来一般格式的图像,直接用 CopyImage 就可以显示了,方便,哈哈!)
OwnerPolicy,这可是我研究了<产生式编程>后突发的灵感,简单实用,便于组件化一些类。
DialogScreen 里包含了客户端鼠标和键盘的捕捉(不捕捉怎么发给服务器,让服务器执行啊)。代码简单,你懂的。
BEGIN_TEMPLATE_MESSAGE_MAP 在 VS2005 下才有,VC6 及 VS2003 不支持。

#ifndef DialogScreen_H#define DialogScreen_H//////////////////////////////////////////////////////////////////////////#include <AfxWin.h>#include "Resource.h"#include "OwnerPolicy.h"//////////////////////////////////////////////////////////////////////////#include <OCIDL.h>#include <OleCtl.h>//////////////////////////////////////////////////////////////////////////template <typename OwnerT>class DialogScreenT:public CDialog, public OwnerPolicy<OwnerT>{enum{HOT_KEY_ID = 0x1000, };public:void FullScreen(){DialogScreenT<OwnerT>::FullScreen(GetSafeHwnd());}void CopyImage(LPVOID lpBuffer, DWORD dwLength){if ((lpBuffer == NULL) || (dwLength == 0)) {return;}HGLOBAL hPicture = ::GlobalReAlloc(m_hPicture, dwLength, GMEM_MOVEABLE);if (hPicture == NULL) {return;}m_hPicture = hPicture;LPVOID pData = ::GlobalLock(m_hPicture);if (pData == NULL) {return;}CopyMemory(pData, lpBuffer, dwLength);GlobalUnlock(m_hPicture);ShowPicture(m_hPicture, GetSafeHwnd());}public:DialogScreenT(CWnd *pParent = NULL):CDialog(DialogScreenT::IDD, pParent){//{{AFX_DATA_INIT(DialogScreenT)//}}AFX_DATA_INITm_hPicture = ::GlobalAlloc(GMEM_MOVEABLE, 32);}~DialogScreenT(){if (m_hPicture != NULL) {GlobalFree(m_hPicture);m_hPicture = NULL;}}//{{AFX_DATA(CMainDialog)enum { IDD = IDD_DLG_SCREEN };//}}AFX_DATA//{{AFX_VIRTUAL(DialogScreenT)protected:virtual void DoDataExchange(CDataExchange *pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(DialogScreenT)//}}AFX_DATA_MAP}//}}AFX_VIRTUALprotected://{{AFX_MSG(DialogScreenT)virtual BOOL OnInitDialog(){CDialog::OnInitDialog();//////////////////////////////////////////////////////////////////////////RegisterHotKey(GetSafeHwnd(), HOT_KEY_ID, MOD_SHIFT|MOD_CONTROL, 'C');return TRUE;}LRESULT OnHotKey(WPARAM wParam, LPARAM lParam){if (wParam == HOT_KEY_ID) {DestroyWindow();}return 0;}afx_msg void OnPaint(){CPaintDC dc(this);ShowPicture(m_hPicture, GetSafeHwnd());}afx_msg void OnDestroy(){UnregisterHotKey(GetSafeHwnd(), HOT_KEY_ID);CDialog::OnDestroy();}afx_msg void OnLButtonDown(UINT nFlags, CPoint ptMouse){owner()->OnMouseEvent(this, MOUSEEVENTF_LEFTDOWN, ptMouse.x, ptMouse.y);}afx_msg void OnLButtonUp(UINT nFlags, CPoint ptMouse){owner()->OnMouseEvent(this, MOUSEEVENTF_LEFTUP, ptMouse.x, ptMouse.y);}afx_msg void OnLButtonDblClk(UINT nFlags, CPoint ptMouse){owner()->OnMouseEvent(this, MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP, ptMouse.x, ptMouse.y);owner()->OnMouseEvent(this, MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP, ptMouse.x, ptMouse.y);}afx_msg void OnRButtonDown(UINT nFlags, CPoint ptMouse){owner()->OnMouseEvent(this, MOUSEEVENTF_RIGHTDOWN, ptMouse.x, ptMouse.y);}afx_msg void OnRButtonUp(UINT nFlags, CPoint ptMouse){owner()->OnMouseEvent(this, MOUSEEVENTF_RIGHTUP, ptMouse.x, ptMouse.y);}afx_msg void OnRButtonDblClk(UINT nFlags, CPoint ptMouse){owner()->OnMouseEvent(this, MOUSEEVENTF_RIGHTDOWN|MOUSEEVENTF_RIGHTUP, ptMouse.x, ptMouse.y);owner()->OnMouseEvent(this, MOUSEEVENTF_RIGHTDOWN|MOUSEEVENTF_RIGHTUP, ptMouse.x, ptMouse.y);}//////////////////////////////////////////////////////////////////////////afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){owner()->OnKeybdEvent(this, nChar, 0);CDialog::OnSysKeyDown(nChar, nRepCnt, nFlags);}afx_msg void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags){owner()->OnKeybdEvent(this, nChar, KEYEVENTF_KEYUP);CDialog::OnSysKeyUp(nChar, nRepCnt, nFlags);}afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){owner()->OnKeybdEvent(this, nChar, 0);CDialog::OnKeyDown(nChar, nRepCnt, nFlags);}afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags){owner()->OnKeybdEvent(this, nChar, KEYEVENTF_KEYUP);CDialog::OnKeyUp(nChar, nRepCnt, nFlags);}//}}AFX_MSGDECLARE_MESSAGE_MAP()//////////////////////////////////////////////////////////////////////////protected:virtual void OnOK(){owner()->OnKeybdEvent(this, VK_RETURN, 0);owner()->OnKeybdEvent(this, VK_RETURN, KEYEVENTF_KEYUP);}virtual void OnCancel(){owner()->OnKeybdEvent(this, VK_ESCAPE, 0);owner()->OnKeybdEvent(this, VK_ESCAPE, KEYEVENTF_KEYUP);}private:static void FullScreen(HWND hWnd){INT nFrameWidth= GetSystemMetrics(SM_CXFRAME);INT nFrameHeight= GetSystemMetrics(SM_CYFRAME);INT nCaptionHeight= GetSystemMetrics(SM_CYCAPTION);INT nScreenWidth= GetSystemMetrics(SM_CXSCREEN);INT nScreenHeight= GetSystemMetrics(SM_CYSCREEN);CRect rect;::GetClientRect(hWnd, &rect);rect.left= rect.left - nFrameWidth;rect.top= rect.top - nFrameHeight - nCaptionHeight;rect.bottom= rect.top + nScreenHeight + 2 * nFrameHeight + nCaptionHeight;rect.right= rect.left + nScreenWidth + 2 * nFrameWidth;::SetWindowPos(hWnd, HWND_TOPMOST, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW);}static HRESULT ShowPicture(HGLOBAL hGlobal, HWND hWnd){HDC hDC = NULL;OLE_XSIZE_HIMETRIC xWidth = 0;OLE_YSIZE_HIMETRIC xHeight = 0;CComQIPtr<IStream> pStream;CComQIPtr<IPicture>pPicture;CRect rect;HRESULT hResult = E_FAIL;if (!::IsWindow(hWnd)) {goto Exit;}::GetClientRect(hWnd, &rect);hDC = ::GetDC(hWnd);if (hDC == NULL) {goto Exit;}if (FAILED(CreateStreamOnHGlobal(hGlobal, FALSE, &pStream)) || pStream == NULL) {goto Exit;}if (FAILED(OleLoadPicture(pStream, 0, TRUE, IID_IPicture, (LPVOID *) &pPicture)) || pPicture == NULL) {goto Exit;}if (FAILED(pPicture->get_Width(&xWidth))) {goto Exit;}if (FAILED(pPicture->get_Height(&xHeight))) {goto Exit;}if (FAILED(pPicture->Render(hDC, 0, 0, rect.Width(), rect.Height(), 0, xHeight, xWidth, -xHeight, NULL))) {goto Exit;}hResult = S_OK;Exit:if (hDC != NULL) {::ReleaseDC(hWnd, hDC);hDC = NULL;}return hResult;}private:HGLOBAL m_hPicture;};//////////////////////////////////////////////////////////////////////////BEGIN_TEMPLATE_MESSAGE_MAP(DialogScreenT, OwnerT, CDialog)//{{AFX_MSG_MAP(DialogScreenT)ON_WM_PAINT()ON_WM_DESTROY()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_LBUTTONDBLCLK()ON_WM_RBUTTONDOWN()ON_WM_RBUTTONUP()ON_WM_RBUTTONDBLCLK()ON_WM_KEYDOWN()ON_WM_KEYUP()ON_WM_SYSKEYDOWN()ON_WM_SYSKEYUP()ON_MESSAGE(WM_HOTKEY, OnHotKey)//}}AFX_MSG_MAPEND_MESSAGE_MAP()//////////////////////////////////////////////////////////////////////////#endif


原创粉丝点击