==========大恒CG卡,我抓取图片时出了问题,总是出现白色的图片 ====================== ( 积分: 100 )

  • 主题发起人 happycyp
  • 开始时间
H

happycyp

Unregistered / Unconfirmed
GUEST, unregistred user!
下面是出问题的函数,用的是大恒CG卡:
function TVideoCtrl.CaptureFarShot(var AShotBmp: TBmpInfo): Boolean;
var
pBuf: Pchar;
BufLength: Dword;
//用户创建的一帧图像数据缓冲区大小,用来将图像卡采集到内存的数据读出到该缓冲区
ImgBufLength: LongWord;

BlockSize, MemHandle : Dword;
LineAddr: Pchar;
pBMIInfo: PBITMAPINFO;
//采集到内存中的图像数
Sum: DWORD;
Bmp: TBitmap;
begin
Result := False;
//使用静态内存保存图象,先访问其大小,如果访问失败则退出操作
if (CGGetStaticMem(BlockSize) <> CG_OK ) then
begin
//ShowMessage('Error in StaticMem Access!');
Exit;
end;
//已经固定用GRB565来采集数据了,每帧图像768*576,所以图像卡需要的帧缓冲区大小是
BufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 2;

//用户要不断将采集到静态内存的帧图像数据读出,需要读出后的帧图像数据是24位彩色
//所以用户自行创建的缓冲区大小是
ImgBufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3;

//分配帧缓存
pBuf := AllocMem(ImgBufLength);
pBMIInfo := AllocMem(sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
//锁定全部保留静态内存给图像卡使用
Bmp := TBitmap.Create;
CGStaticMemLock(0, BlockSize*4096, MemHandle, LineAddr);
//准备回显图像的DC
{VideoDc := GetDc(AVideo.Handle);
SetStretchBltMode(VideoDC, COLORONCOLOR);}
try
Bmp.Width:= OUTPUT_WINDOW_WIDTH;
Bmp.Height := OUTPUT_WINDOW_HEIGHT;
Bmp.PixelFormat := pf24bit;
//设定BMP的头信息
pBMIInfo^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
pBMIInfo^.bmiHeader.biWidth := OUTPUT_WINDOW_WIDTH;
pBMIInfo^.bmiHeader.biHeight := OUTPUT_WINDOW_HEIGHT;
pBMIInfo^.bmiHeader.biPlanes := 1;
pBMIInfo^.bmiHeader.biBitCount := 24;
pBMIInfo^.bmiHeader.biCompression := BI_RGB;
pBMIInfo^.bmiHeader.biSizeImage := 0;
pBMIInfo^.bmiHeader.biXPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biYPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biClrUsed := 0;
pBMIInfo^.bmiHeader.biClrImportant := 0;

//控制面版中分派的静态内存可以保存当前尺寸的采集图象的总数SUM
Sum := (BlockSize * 4096) div BufLength;
//采集到内存中
if (Sum > 0) and
(CGSnapShot(hCGCard[0], 0, 0, TRUE, 1) = CG_OK) then //取1帧
begin
//从内存中读取一图
CGDataTransform(pBuf , LineAddr,
OUTPUT_WINDOW_WIDTH, OUTPUT_WINDOW_HEIGHT, 16, True);
//调用win32的API函数将Buf中的数据以图象形式显示在VideoPanel上
SetStretchBltMode(Bmp.Canvas.Handle, COLORONCOLOR);
SetDIBitsToDevice(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height,
0, 0, 0, pBMIInfo^.bmiHeader.biHeight,
pBuf, pBMIInfo^, DIB_RGB_COLORS);
if Assigned(AShotBmp.biBmp) then
AShotBmp.biBmp.Free;
AShotBmp.biBmp := TBitmap.Create;
AShotBmp.biBmp.Assign(Bmp);
AShotBmp.biDateTime := GetDateTime;
end;
finally
if Assigned(Bmp) then
Bmp.Free;
FreeMem(pBMIInfo, sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
FreeMem(pBuf, ImgBufLength);
CGStaticMemUnlock(MemHandle);
end;
end;
//===================================================================================================
上面这个函数有时候保存的图片正常,有时候却得到白色的图片。请高手指教。
下面这个类似的方法是抓取另一帧图片,却从来没有出过问题一直是正常的。
function TVideoCtrl.CapturePic(hCard: HCG; iIndex: Byte =0): boolean;
var
pBuf: Pchar;
BufLength: Dword;
//用户创建的一帧图像数据缓冲区大小,用来将图像卡采集到内存的数据读出到该缓冲区
ImgBufLength: LongWord;

BlockSize, MemHandle : Dword;
LineAddr: Pchar;
pBMIInfo: PBITMAPINFO;
//采集到内存中的图像数
Sum: DWORD;
i: DWORD;
Bmp: TBitmap;
BmpArray: array[0..3] of TBitmap;
BmpInfo1, BmpInfo2: TBmpInfo;
begin
Result := False;
// if not bInit then exit;
//使用静态内存保存图象,先访问其大小,如果访问失败则退出操作
if iIndex <> 0 then
CaptureFarShot(FarShot1); //cyp 2007-8-30
if (CGGetStaticMem(BlockSize) <> CG_OK ) then
begin
//ShowMessage('Error in StaticMem Access!');
Exit;
end;
//已经固定用GRB565来采集数据了,每帧图像768*576,所以图像卡需要的帧缓冲区大小是
BufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 2;

//用户要不断将采集到静态内存的帧图像数据读出,需要读出后的帧图像数据是24位彩色
//所以用户自行创建的缓冲区大小是
ImgBufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3;

//分配帧缓存
pBuf := AllocMem(ImgBufLength);
pBMIInfo := AllocMem(sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
Bmp := TBitmap.Create;
//锁定全部保留静态内存给图像卡使用
CGStaticMemLock(0, BlockSize*4096, MemHandle, LineAddr);
//准备回显图像的DC
{VideoDc := GetDc(AVideo.Handle);
SetStretchBltMode(VideoDC, COLORONCOLOR);}
try
Bmp.Width:= OUTPUT_WINDOW_WIDTH;
Bmp.Height := OUTPUT_WINDOW_HEIGHT;
Bmp.PixelFormat := pf24bit;
//设定BMP的头信息
pBMIInfo^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
pBMIInfo^.bmiHeader.biWidth := OUTPUT_WINDOW_WIDTH;
pBMIInfo^.bmiHeader.biHeight := OUTPUT_WINDOW_HEIGHT;
pBMIInfo^.bmiHeader.biPlanes := 1;
pBMIInfo^.bmiHeader.biBitCount := 24;
pBMIInfo^.bmiHeader.biCompression := BI_RGB;
pBMIInfo^.bmiHeader.biSizeImage := 0;
pBMIInfo^.bmiHeader.biXPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biYPelsPerMeter := 0;
pBMIInfo^.bmiHeader.biClrUsed := 0;
pBMIInfo^.bmiHeader.biClrImportant := 0;

//控制面版中分派的静态内存可以保存当前尺寸的采集图象的总数SUM
Sum := (BlockSize * 4096) div BufLength;

//采集到内存中
if Sum > 4 then Sum := 4;
if (Sum > 0) and
(CGSnapShot(hCard, 0, FrameStep, TRUE, Sum) = CG_OK) then //取两帧
begin
for i := 0 to Sum - 1 do
begin
//从内存中读取一图
CGDataTransform(pBuf , LineAddr + i*BufLength,
OUTPUT_WINDOW_WIDTH, OUTPUT_WINDOW_HEIGHT, 16, True);
//调用win32的API函数将Buf中的数据以图象形式显示在VideoPanel上
SetStretchBltMode(Bmp.Canvas.Handle, COLORONCOLOR);
SetDIBitsToDevice(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height,
0, 0, 0, pBMIInfo^.bmiHeader.biHeight,
pBuf, pBMIInfo^, DIB_RGB_COLORS);
BmpArray := TBitmap.Create;
BmpArray.Assign(Bmp);
end;
// if iIndex <> 0 then CaptureFarShot(FarShot1);
if Sum > 2 then
begin
BmpInfo1.biBmp := TBitmap.Create;
BmpInfo1.biBmp.Assign(BmpArray[Sum - 2]);
BmpInfo1.biDateTime := GetDateTime;

BmpInfo2.biBmp := TBitmap.Create;
BmpInfo2.biBmp.Assign(BmpArray[0]);
BmpInfo2.biDateTime := GetDateTime;
Result := ScanFrame(BmpInfo1, BmpInfo2) //检测第一帧和第三帧
end else
begin
BmpInfo1.biBmp := TBitmap.Create;
BmpInfo1.biBmp.Assign(BmpArray[1]);
BmpInfo1.biDateTime := GetDateTime;

BmpInfo2.biBmp := TBitmap.Create;
BmpInfo2.biBmp.Assign(BmpArray[0]);
BmpInfo2.biDateTime := GetDateTime;
Result := ScanFrame(BmpInfo1, BmpInfo2) //检测第一帧和第三帧
end;
{设置事件信号,退出当前等待状态}
if Result then
SetEvent(hCarEvent);
{显示采集的图像中的最后一帧
StretchDIBits(VideoDC, 0, 0, AVideo.Width, AVideo.Height,
0, 0, pBMIInfo^.bmiHeader.biWidth, pBMIInfo^.bmiHeader.biHeight,
pBuf, pBMIInfo^, DIB_RGB_COLORS, SRCCOPY); }
end;
finally
//释放内存
for i := 0 to Sum -1 do
begin
if Assigned(BmpArray) then
BmpArray.Free;
BmpArray := nil;
end;
if Assigned(Bmp) then
Bmp.Free;
FreeMem(pBMIInfo, sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
FreeMem(pBuf, ImgBufLength);
CGStaticMemUnlock(MemHandle);
end;
end;
 
解决了
var
pBuf: Pchar;
BufLength: Dword;
ImgBufLength: LongWord;
BlockSize, MemHandle : Dword;
LineAddr: Pchar;
VideoDc: HDC;

begin
if not bInit then exit;
if (CGGetStaticMem(BlockSize) <> CG_OK ) then
begin
ShowMessage('Error in StaticMem Access!');
exit;
end;
BufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3;
ImgBufLength := OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3;
pBuf := AllocMem(ImgBufLength);
CG_VERIFY(CGStaticMemLock(0, BlockSize*4096, MemHandle, LineAddr));
try
if (CGSnapShot(hCGCard, 0, 0, TRUE, 1) = MB_OK) then
begin
CGDataTransform(pBuf , LineAddr, OUTPUT_WINDOW_WIDTH, OUTPUT_WINDOW_HEIGHT, 24, True);

FileStream.Position := pBFileHeader^.bfOffBits;
FileStream.Write(pBuf^, OUTPUT_WINDOW_WIDTH * OUTPUT_WINDOW_HEIGHT * 3);
FileStream.SaveToFile('test.bmp');
end;
finally

FreeMem(pBMIInfo, sizeof(TBITMAPINFO)+ (255 * sizeof(TRGBQuad)));
FreeMem(pBuf, ImgBufLength);
CG_VERIFY(CGStaticMemUnlock(MemHandle));
FileStream.Free();
freeMem(pBFileHeader);
end;

end;

Delphi的TBitMap对象的画布有问题。
直接用流先保存到文件即可。上面是方法。
 
顶部