自己寫遠端控制軟體之影象壓縮
由於要壓縮成 JPG 檔案,我用的是
Intel ilj 庫,別說你沒聽過哦,可壓縮 YUYV和 Bmp,以下是我的 JpegEncoder,
使用簡單,介面清晰,誰用誰知道。至於在客戶端顯示 JPG,我就交給 OleLoadPicture 了,因為 ilj 在解壓的時候,有時會記憶體洩露,但是 OleLoadPicture 在使用時會有個問題就是如果 JPG 檔案本身有問題,會造成 OleLoadPicture 死鎖,我查了一下,據說是 Microsoft 的 BUG,這麼長時間了也不知道 Fix 沒有。不過 OleLoadPicture 死鎖在這個程式是不太可能出現的,我說的是我在公司的情況,細節我就不說了。
把顯示的程式碼也貼上來,(只要來一般格式的影象,直接用 CopyImage 就可以顯示了,方便,哈哈!)
OwnerPolicy,這可是我研究了<產生式程式設計>後突發的靈感,簡單實用,便於元件化一些類。
DialogScreen 裡包含了客戶端滑鼠和鍵盤的捕捉(不捕捉怎麼發給伺服器,讓伺服器執行啊)。程式碼簡單,你懂的。
BEGIN_TEMPLATE_MESSAGE_MAP 在 VS2005 下才有,VC6 及 VS2003 不支援。
使用簡單,介面清晰,誰用誰知道。至於在客戶端顯示 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_INIT
m_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_VIRTUAL
protected:
//{{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_MSG
DECLARE_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_MAP
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////////
#endif
相關文章
- 自己寫遠端控制軟體之捕捉螢幕
- 自己寫遠端控制軟體之隱藏介面
- 自己寫遠端控制軟體之網路傳輸
- 自己寫遠端控制軟體之鍵鼠響應
- 自己寫遠端控制軟體之偵測伺服器伺服器
- 遠端桌面控制軟體,遠端桌面控制軟體推薦,及其連線方法
- vnc遠端控制軟體,vnc遠端控制軟體有什麼用,操作教程VNC
- VNC遠端控制軟體XP版,VNC遠端控制軟體XP版下載VNC
- 遠端控制軟體 LogMeIn
- vnc遠端控制軟體怎麼用,vnc遠端控制軟體怎麼用,使用教程VNC
- vnc遠端控制軟體,vnc遠端控制軟體怎麼使用,vnc server如何安裝?VNCServer
- VNC遠端控制軟體:VNC Server for MacVNCServerMac
- VNC Server for Mac(VNC遠端控制軟體)VNCServerMac
- 遠端控制軟體哪個好用?精選安全遠控軟體ToDesk
- 圖鴨科技獲CVPR 2018影象壓縮挑戰賽單項冠軍,技術解讀端到端影象壓縮框架框架
- vnc遠端控制軟體x64,vnc遠端控制軟體x64安裝方法,及使用教程VNC
- vnc遠端控制軟體中文版,細數五款好用的vnc遠端控制軟體中文版VNC
- 2024遠端控制軟體排名1
- 國外遠端控制軟體排行榜
- JPEG影象的解壓縮操作
- TeamViewer遠端控制軟體,讓你享受遠端辦公的便利View
- vnc遠端控制軟體綠色,vnc遠端控制軟體綠色版下載,使用者登入使用教程VNC
- 最佳RDP/VPN替代方案:Splashtop遠端控制軟體
- 高流暢的遠端控制軟體推薦
- 如何把影片壓縮,影片壓縮軟體哪個最好
- BetterZip for Mac解壓縮軟體Mac
- Android平臺影象壓縮方案Android
- 八大遠端控制軟體,完美替代TeamviewerView
- 開源一款遠端控制軟體 —— pcshare
- 解壓縮軟體RAR Extractor MacMac
- RAR Extractor Mac - 解壓縮軟體Mac
- 【開源】canvas影象裁剪、壓縮、旋轉Canvas
- 極端影象壓縮的生成對抗網路,可生成低位元速率的高質量影象
- VNC遠端協助軟體,VNC遠端協助軟體下載!VNC
- 最快的遠端控制軟體radmin的配置和使用
- 遠端控制軟體 TeamViewer 的侷限性和替代方案View
- VNC Connect Enterprise Mac(遠端桌面控制軟體)VNCMac
- 專業商用遠端控制軟體,低至10元每月