能力值:
( LV2,RANK:10 )
|
-
-
2 楼
过来支持了,,呵呵
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
头文件
#ifndef _VIDEOCAP_H
#define _VIDEOCAP_H
#include <Vfw.h>
#include <Windows.h>
#pragma comment(lib,"vfw32.lib")
class CVideoCap
{
public:
CVideoCap();
~CVideoCap();
public:
//初始化设备
BOOL Initialize();
BOOL IsWebCam();
//获取每帧图像DIB格式
LPBYTE GetDIB( LPCTSTR lpPath );
void YUV2_RGB( BYTE *YUV2buff, BYTE *RGBbuff, DWORD dwYUVSize );
BITMAPINFOHEADER *Getbmi();
static LRESULT CALLBACK capErrorCallback( HWND hWnd, int nID, LPCTSTR lpsz );
static LRESULT CALLBACK FrameCallbackProc( HWND hWnd, LPVIDEOHDR lpVHdr );
public:
BOOL m_bIsConnected;
BOOL m_bIsCapture;
BITMAPINFO *m_lpbmi;
LPBYTE m_lpDIB;
HWND m_hWnd;
HWND m_hWndCap;
LPCTSTR m_Path;
BOOL m_bInit;
};
#endif //end of VideoCap.h
源文件
#include "stdafx.h"
#include "VideoCap.h"
///*********************************** format char to int ***********************************/
// for ( int i = 0; i < 8; i ++ )
// {
// if ( yuv[in +i] >= '0' && yuv[in + i] <= '9' )
// {
// yuv[in + i] = yuv[in + i] - '0';
// }
// else
// {
// yuv[in + i] = (yuv[in + i] - 'a') + 10;
// }
// }
//
///*********************************** format int to char ***********************************/
// for ( int i = 0; i < 3; i++ )
// {
// if ( ((pixed_24[i] / 16) >= 0) && ((pixed_24[i] / 16) <= 9) )
// rgb[OUT++] = pixed_24[i] / 16 + '0';
// else
// rgb[OUT++] = pixed_24[i] / 16 - 10 + 'a';
//
// if ( ((pixed_24[i] % 16) >= 16) && pixed_24[i] % 16 <= 9 )
// rgb[OUT++] = pixed_24[i] % 16 + '0';
// else
// rgb[OUT++] = pixed_24[i] % 16 - 10 + 'a';
// }
//注意RGB的缓冲区得是YUV2的1.5倍,因为一个YUV2包含两个像素, 所以需要两个RGB像素表示
void CVideoCap::YUV2_RGB( BYTE *YUY2buff, BYTE *RGBbuff, DWORD dwYUVSize )
{
//整型算法
// 要用整型运算代替浮点运算,当然是要用移位的办法了,我们可以很容易得到下列算法:
//u = YUVdata[UPOS] - 128;
//v = YUVdata[VPOS] - 128;
//rdif = v + ((v * 103) >> 8);
//invgdif = ((u * 88) >> 8) +((v * 183) >> 8);
//bdif = u +( (u*198) >> 8);
//r = YUVdata[YPOS] + rdif;
//g = YUVdata[YPOS] - invgdif;
//b = YUVdata[YPOS] + bdif;
int R, G, B;
int Y, U, Y1, V;
int rdif, invgdif, bdif;
BYTE *poriYUV2buff = YUY2buff;
BYTE *poriRGBbuff = RGBbuff;
DWORD pos = 0;
for ( DWORD j = 0; j < dwYUVSize; j += 4 )
{
//1. 获取Y U V 数值,
//YUV2格式的排列是Y0,V0,Y1,U0, Y2,V2,Y3,U2
Y = *(YUY2buff++);
U = *(YUY2buff++);
Y1 = *(YUY2buff++);
V = *(YUY2buff++);
//2. 计算 R G B 值
U -= 128;
V -= 128;
rdif = V + ((V * 103) >> 8);
invgdif = ((U * 88) >> 8) + ((V * 183) >> 8);
bdif = U +( (U * 198) >> 8);
R = Y + rdif;
G = Y - invgdif;
B = Y + bdif;
//3. 溢出处理
if ( R > 255 ) R = 255; if ( R < 0 ) R = 0;
if ( G > 255 ) G = 255; if ( G < 0 ) G = 0;
if ( B > 255 ) B = 255; if ( B < 0 ) B = 0;
//4. 输出 R G B
*(RGBbuff++) = (byte)R;
*(RGBbuff++) = (byte)G;
*(RGBbuff++) = (byte)B;
*(RGBbuff++) = (byte)R;
*(RGBbuff++) = (byte)G;
*(RGBbuff++) = (byte)B;
}
YUY2buff = poriYUV2buff;
RGBbuff = poriRGBbuff;
}
CVideoCap::CVideoCap()
{
m_bInit = FALSE;
m_bIsConnected = FALSE;
m_bIsCapture = FALSE;
m_lpbmi = NULL;
m_lpDIB = NULL;
if ( ! IsWebCam() || m_bIsConnected )
return;
m_hWnd = CreateWindow( _T("#32770"), _T(""), WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL );
m_hWndCap = capCreateCaptureWindow(
_T("CVideoCap"),
WS_CHILD | WS_VISIBLE,
0,
0,
0,
0,
m_hWnd,
0);
}
CVideoCap::~CVideoCap()
{
if ( m_bIsConnected )
{
capCaptureAbort( m_hWndCap );
capSetCallbackOnError( m_hWndCap, NULL );
capSetCallbackOnFrame( m_hWndCap, NULL );
capDriverDisconnect( m_hWndCap );
if ( m_lpbmi )
delete [] m_lpbmi;
if ( m_lpDIB )
delete [] m_lpDIB;
m_bIsConnected = FALSE;
}
CloseWindow( m_hWnd );
CloseWindow( m_hWndCap );
}
LRESULT CALLBACK CVideoCap::capErrorCallback( HWND hWnd, int nID, LPCTSTR lpsz )
{
return -1;
}
LRESULT CALLBACK CVideoCap::FrameCallbackProc( HWND hWnd, LPVIDEOHDR lpVHdr )
{
try
{
CVideoCap *pThis = (CVideoCap *)capGetUserData( hWnd );
if ( pThis != NULL )
{
memcpy( pThis->m_lpDIB, lpVHdr->lpData, pThis->m_lpbmi->bmiHeader.biSizeImage );
InterlockedExchange( (LPLONG)&(pThis->m_bIsCapture), FALSE );
if ( pThis->m_Path != NULL )
capFileSaveDIB( hWnd, pThis->m_Path );
}
}
catch(...){}
return 0;
}
BOOL CVideoCap::IsWebCam()
{
if ( m_bIsConnected )
return FALSE;
BOOL bRet = FALSE;
char lpszName[100], lpszVer[50];
for ( int i = 0; i < 10 && !bRet; i++ )
{
bRet = capGetDriverDescription( i, lpszName, sizeof(lpszName), lpszVer, sizeof(lpszVer) );
}
return bRet;
}
LPBYTE CVideoCap::GetDIB( LPCTSTR lpPath )
{
if ( lpPath != NULL )
m_Path = lpPath;
if ( !m_bInit )
{
Initialize();
}
m_bIsCapture = TRUE;
capGrabFrameNoStop( m_hWndCap );
while( m_bIsCapture == TRUE )
Sleep( 100 );
return m_lpDIB;
}
BITMAPINFOHEADER *CVideoCap::Getbmi()
{
return &(m_lpbmi->bmiHeader);
}
BOOL CVideoCap::Initialize()
{
//CAPTUREPARMS gCapTureParms;
CAPDRIVERCAPS gCapDriverCaps;
DWORD dwSize;
if ( !IsWebCam() )
return FALSE;
int i;
for ( i = 0; i < 10; i++ )
{
if ( capDriverConnect( m_hWndCap, i ) )
break;
}
if ( i == 10 )
return FALSE;
dwSize = capGetVideoFormatSize( m_hWndCap );
capSetUserData( m_hWndCap, this );
capSetCallbackOnError( m_hWndCap, capErrorCallback );
if ( ! capSetCallbackOnFrame( m_hWndCap, FrameCallbackProc ) )
{
return FALSE;
}
m_lpbmi = (BITMAPINFO *)new BYTE[dwSize];
capGetVideoFormat( m_hWndCap, m_lpbmi, dwSize );
m_lpDIB = new BYTE[m_lpbmi->bmiHeader.biSizeImage];
capDriverGetCaps( m_hWndCap, &gCapDriverCaps, sizeof(CAPDRIVERCAPS) );
capOverlay( m_hWndCap, FALSE );
capPreview( m_hWndCap, TRUE );
capPreviewScale( m_hWndCap, FALSE );
m_bIsConnected = TRUE;
m_bInit = TRUE;
return TRUE;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
啊,原来出了ffmpeg,还有vfw库啊!
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
也可以试试OpenCV啊
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
大侠,我想用C语言,而不是C++,可否用C语言写一个呢
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
想过用OpenCV,可是不知道从何下手啊,今天还有一天,再做不出来就得换程序啦!!!
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
把类名去掉就是C的了,难道你没看出来吗?我把函数放在类里只是为了方便管理。代码都是C风格的,没有用到C++特性。
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
可是我看着好像有继承啊,C里面应该没继承吧,可否把修改好的C代码给出来呢
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
哪有继承?我就是把API封装了下。
|