📄 rcaclientlibrary.cpp
字号:
#include "stdafx.h"
BOOL
WINAPI
DecodeFromJPEGBuffer(
BYTE * lpJpgBuffer,
DWORD dwJpgBufferSize,
BYTE** lppRgbBuffer,
DWORD* lpdwWidth,
DWORD* lpdwHeight,
DWORD* lpdwNumberOfChannels
)
{
BOOL bres;
IJLERR jerr;
DWORD dwWholeImageSize;
BYTE* lpTemp = NULL;
// Allocate the IJL JPEG_CORE_PROPERTIES structure.
JPEG_CORE_PROPERTIES jcprops;
bres = TRUE;
__try
{
// Initialize the Intel(R) JPEG Library.
jerr = ijlInit(&jcprops);
if(IJL_OK != jerr)
{
bres = FALSE;
__leave;
}
// Get information on the JPEG image
// (i.e., width, height, and channels).
jcprops.JPGFile = NULL;
jcprops.JPGBytes = lpJpgBuffer;
jcprops.JPGSizeBytes = dwJpgBufferSize;
jerr = ijlRead(&jcprops, IJL_JBUFF_READPARAMS);
if(IJL_OK != jerr)
{
bres = FALSE;
__leave;
}
// Set the JPG color space ... this will always be
// somewhat of an educated guess at best because JPEG
// is "color blind" (i.e., nothing in the bit stream
// tells you what color space the data was encoded from).
// However, in this example we assume that we are
// reading JFIF files which means that 3 channel images
// are in the YCbCr color space and 1 channel images are
// in the Y color space.
switch(jcprops.JPGChannels)
{
case 1:
{
jcprops.JPGColor = IJL_G;
jcprops.DIBColor = IJL_RGB;
jcprops.DIBChannels = 3;
break;
}
case 3:
{
jcprops.JPGColor = IJL_YCBCR;
jcprops.DIBColor = IJL_RGB;
jcprops.DIBChannels = 3;
break;
}
default:
{
// This catches everything else, but no
// color twist will be performed by the IJL.
jcprops.JPGColor = IJL_OTHER;
jcprops.DIBColor = IJL_OTHER;
jcprops.DIBChannels = jcprops.JPGChannels;
break;
}
}
// Compute size of desired pixel buffer.
dwWholeImageSize = jcprops.JPGWidth * jcprops.JPGHeight *
jcprops.DIBChannels;
// Allocate memory to hold the decompressed image data.
lpTemp = new BYTE [dwWholeImageSize];
if(NULL == lpTemp)
{
bres = FALSE;
__leave;
}
// Set up the info on the desired DIB properties.
jcprops.DIBWidth = jcprops.JPGWidth;
jcprops.DIBHeight = jcprops.JPGHeight;
jcprops.DIBPadBytes = 0;
jcprops.DIBBytes = lpTemp;
// Now get the actual JPEG image data into the pixel buffer.
jerr = ijlRead(&jcprops, IJL_JBUFF_READWHOLEIMAGE);
if(IJL_OK != jerr)
{
bres = FALSE;
__leave;
}
} // __try
__finally
{
if(FALSE == bres)
{
if(NULL != lpTemp)
{
delete [] lpTemp;
lpTemp = NULL;
}
}
// Clean up the Intel(R) JPEG Library.
ijlFree(&jcprops);
*lpdwWidth = jcprops.DIBWidth;
*lpdwHeight = jcprops.DIBHeight;
*lpdwNumberOfChannels = jcprops.DIBChannels;
*lppRgbBuffer = lpTemp;
} // __finally
return bres;
} // DecodeFromJPEGBuffer()
//----------------------------------------------------------
// An example using the Intel(R) JPEG Library:
// -- Encode Windows DIB to JPEG buffer.
//----------------------------------------------------------
BOOL WINAPI EncodeToJPEGBuffer(
BYTE* lpRgbBuffer,
DWORD dwWidth,
DWORD dwHeight,
BYTE** lppJpgBuffer,
DWORD* lpdwJpgBufferSize,
int iQuality
)
{
BOOL bres;
IJLERR jerr;
DWORD dwRgbBufferSize;
BYTE* lpTemp;
// Allocate the IJL JPEG_CORE_PROPERTIES structure.
JPEG_CORE_PROPERTIES jcprops;
bres = TRUE;
__try
{
// Initialize the Intel(R) JPEG Library.
jerr = ijlInit(&jcprops);
if(IJL_OK != jerr)
{
bres = FALSE;
__leave;
}
dwRgbBufferSize = dwWidth * dwHeight * 3;
lpTemp = new BYTE [dwRgbBufferSize];
if(NULL == lpTemp)
{
bres = FALSE;
__leave;
}
// Set up information to write from the pixel buffer.
jcprops.DIBWidth = dwWidth;
jcprops.DIBHeight = dwHeight; // Implies a bottom-up DIB.
jcprops.DIBBytes = lpRgbBuffer;
jcprops.DIBPadBytes = 0;
jcprops.DIBChannels = 3;
jcprops.DIBColor = IJL_RGB;
jcprops.JPGWidth = dwWidth;
jcprops.JPGHeight = dwHeight;
jcprops.JPGFile = NULL;
jcprops.JPGBytes = lpTemp;
jcprops.JPGSizeBytes = dwRgbBufferSize;
jcprops.JPGChannels = 3;
jcprops.JPGColor = IJL_YCBCR;
jcprops.JPGSubsampling = IJL_411; // 4:1:1 subsampling.
jcprops.jquality = (iQuality>=0)&&(iQuality<=100) ? iQuality : 50; // Select "good" image quality
// Write the actual JPEG image from the pixel buffer.
jerr = ijlWrite(&jcprops,IJL_JBUFF_WRITEWHOLEIMAGE);
if(IJL_OK != jerr)
{
bres = FALSE;
__leave;
}
} // __try
__finally
{
if(FALSE == bres)
{
if(NULL != lpTemp)
{
delete[] lpTemp;
lpTemp = NULL;
}
}
*lppJpgBuffer = lpTemp;
*lpdwJpgBufferSize = jcprops.JPGSizeBytes;
// Clean up the Intel(R) JPEG Library.
ijlFree(&jcprops);
}
return bres;
} // EncodeToJPEGBuffer()
////////////////////////////////////////
//
// SOCKET 异步 IO 帮助函数, 异步模型为 "事件选择模型"
//
// 参数:
// SOCKET s:
// 套接字 s 是一个已成功连接的套接字, 并至少使用 FD_READ 标志作为
// 参数 lNetworkEvents 调用了 WSAEventSelect 成功地将套接字置为异步事件选择模型
//
// HANDLE hEvent:
// 一个用于网络 IO 事件通知的事件句柄.
//
// char * buf:
// 接收数据缓冲
//
// int len:
// 接收数据缓冲总长度
//
// BOOL * bExit:
// BOOL 变量的指针, 应用程序可以修改这个值. 这个函数调用 WaitForSingleObject 等待
// dwMilliseconds 毫秒后, 将检测 bExit 的值, 若为 bExit 为 TRUE, 函数将立即返回.
// 返回时是不管等待是否成功的,或说不论等待结果是 WAIT_TIMEOUT 或者 WAIT_OBJECT_0,
// 都会返回, 只要 bExit 为 TRUE
//
//
// DWORD dwMilliseconds:
// 函数将使用这个值作为第二个参数,调用 WaitForSingleObject. 以毫秒为单位
// INFINITE 为无限等待
//
// 返回值:
// 若第一次调用接收函数时, 连接出现问题, 则返回 0
//
// 若第一次调用接收函数成功后,以后无论发生任何错误都返回一个整型值,
// 描述已接收了多少数据
//
// 如果返回值与参数 len 相等, 说明成功发送出了所有数据, 若不等,可能是网络错误造成,
// 也可能是 bExit 被设为 TRUE 后接收操作被强制中断
INT
WINAPI RCARecv_EventSelectIO(
SOCKET s,
HANDLE hEventArray[2],
char* buf,
const int len
)
{
if( (buf == NULL) || (len==0) )
return FALSE;
int ret;
DWORD dwret;
int count = len;
int index = 0;
WSANETWORKEVENTS ns;
while( count > 0 )
{
ret = recv( s, &(buf[index]), count, 0 );
if( ret == SOCKET_ERROR )
{
// 如果发送错误,并且错误代码不是"被阻塞", 则返回 FALSE ( 发生了网络错误 )
if( WSAGetLastError() != WSAEWOULDBLOCK )
return len - count;
} else if( ret == 0 )
{
return len - count ;
} else
{
// 如果成功发送, 则更新缓冲偏移字节数和待发总字节数
index += ret;
count -= ret;
continue;
}
dwret = WaitForMultipleObjects(
2, hEventArray, FALSE, INFINITE );
switch ( dwret )
{
case WAIT_FAILED:
return len - count;
case WAIT_OBJECT_0:
break;
case WAIT_OBJECT_0 + 1:
return len - count;
case WAIT_TIMEOUT:
break;
}
ret = WSAEnumNetworkEvents( s, hEventArray[0], &ns );
if( ret == SOCKET_ERROR )
{
return len - count;
}
if( ns.lNetworkEvents & FD_READ )
{
if( ns.iErrorCode[ FD_READ_BIT] != 0 )
{
return len - count;
}
else
{
continue; // 回到循环开始处,再次接收数据(此时,绝对可以接收数据)
}
}
if( ns.lNetworkEvents & FD_CLOSE )
{
return len - count;
}
}
return len - count;
}
////////////////////////////////////////
//
// SOCKET 异步 IO 帮助函数, 异步模型 事件选择模型
//
// 参数:
// SOCKET s:
// 套接字 s 是一个已成功连接的套接字, 并至少使用 FD_WRITE 标志作为
// 参数 lNetworkEvents 调用了 WSAEventSelect 成功地将套接字置为异步事件选择模型
//
// HANDLE hEvent:
// 一个用于网络 IO 事件通知的事件句柄.
//
// char * buf:
// 待发数据缓冲
//
// int len:
// 待发数据缓冲总长度
//
// BOOL * bExit:
// BOOL 变量的指针, 应用程序可以修改这个值. 这个函数调用 WaitForSingleObject 等待
// dwMilliseconds 毫秒后, 将检测 bExit 的值, 若为 bExit 为 TRUE, 函数将立即返回.
// 返回时是不管等待是否成功的,或说不论等待结果是 WAIT_TIMEOUT 或者 WAIT_OBJECT_0,
// 都会返回, 只要 bExit 为 TRUE
//
//
// DWORD dwMilliseconds:
// 函数将使用这个值作为第二个参数,调用 WaitForSingleObject. 以毫秒为单位
// INFINITE 为无限等待
//
// 返回值:
// 若第一次调用发送函数时, 连接出现问题, 则返回 0
//
// 若第一次调用发送函数成功后,以后无论发生任何错误都返回一个整型值,
// 描述已发送了多少数据
//
// 如果返回值与参数 len 相等, 说明成功发送出了所有数据, 若不等,可能是网络错误造成,
// 也可能是 bExit 被设为 TRUE 后发送操作被强制中断
INT
WINAPI RCASend_EventSelectIO(
SOCKET s,
HANDLE hEventArray[2],
char* buf,
const int len
)
{
if( (buf == NULL) || (len==0) )
return FALSE;
int ret;
int count = (int)len;
int index =0;
DWORD dwret;
WSANETWORKEVENTS ns;
while( count > 0 )
{
ret = send( s, &(buf[index]), count, 0 );
if( ret == SOCKET_ERROR )
{
// 如果发送错误,并且错误代码不是"被阻塞", 则返回 FALSE ( 发生了网络错误 )
if( WSAGetLastError() != WSAEWOULDBLOCK )
return len - count;
}
else
{
// 如果成功发送, 则更新缓冲偏移字节数和待发总字节数
cout << ret << endl;
index += ret;
count -= ret;
continue;
}
// 到这里,说明没而待发缓冲区可供使用, 在 AsyncEvent IO 模型中, 可以等待事件通知的到来
// 现在根据 dwMilliseconds 来待待事件通知
dwret = WaitForMultipleObjects(
2, hEventArray, FALSE, INFINITE );
switch( dwret )
{
case WAIT_FAILED:
case WAIT_OBJECT_0 + 1:
return len - count;
case WAIT_OBJECT_0:
break;
case WAIT_TIMEOUT:
continue;
}
ret = WSAEnumNetworkEvents( s, hEventArray[0], &ns );
if( ns.lNetworkEvents & FD_WRITE )
{
if( ns.iErrorCode[ FD_WRITE_BIT] != 0 )
return (len - count);
else
continue; // 回到前边,再次发送数据(此时,绝对可以发送数据)
}
if( ret == SOCKET_ERROR )
return (len - count);
if( ns.lNetworkEvents & FD_CLOSE )
return (len - count);
}
return len - count;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -