首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用Delphi从网络摄像头获取快照

使用Delphi从网络摄像头获取快照
EN

Stack Overflow用户
提问于 2010-08-11 01:29:33
回答 3查看 8.2K关注 0票数 6

我需要在Delphi中从网络摄像头中获取常规快照。速度不是问题(一秒钟就可以了)。我试过了http://delphi.pjh2.de的基于东西的演示代码,但我不能让它工作。它可以正常编译和运行,但回调函数从不触发。

我没有真正的摄像头,但我运行的是模拟器。模拟器可以工作(我可以使用Skype看到视频),但不能使用测试应用程序。我真的不知道该从哪里开始找...

有人愿意尝试一下这段代码吗?(对于这篇长篇大论的帖子-无法找到如何或是否可以附加文件-可以在here上找到压缩文件。)

或者,任何网络摄像头演示代码将受到赞赏,最好是与已知良好的EXE以及来源。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
program WebCamTest;

uses
  Forms,
  WebCamMainForm in 'WebCamMainForm.pas' {Form1},
  yuvconverts in 'yuvconverts.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


unit WebCamMainForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, YUVConverts, StdCtrls, JPeg {, TntStdCtrls} ;

const
  WM_CAP_START = WM_USER;
  WM_CAP_DRIVER_CONNECT       = WM_CAP_START+ 10;

  WM_CAP_SET_PREVIEW          = WM_CAP_START+ 50;
  WM_CAP_SET_OVERLAY          = WM_CAP_START+ 51;
  WM_CAP_SET_PREVIEWRATE      = WM_CAP_START+ 52;

  WM_CAP_GRAB_FRAME_NOSTOP    = WM_CAP_START+ 61;
  WM_CAP_SET_CALLBACK_FRAME   = WM_CAP_START+ 5;
  WM_CAP_GET_VIDEOFORMAT      = WM_CAP_START+ 44;

  WM_CAP_DLG_VIDEOFORMAT      = WM_CAP_START+ 41;

  PICWIDTH= 640;
  PICHEIGHT= 480;
  SUBLINEHEIGHT= 18;
  EXTRAHEIGHT= 400;

type
  TVIDEOHDR= record
    lpData: Pointer; // address of video buffer
    dwBufferLength: DWord; // size, in bytes, of the Data buffer
    dwBytesUsed: DWord; // see below
    dwTimeCaptured: DWord; // see below
    dwUser: DWord; // user-specific data
    dwFlags: DWord; // see below
    dwReserved1, dwReserved2, dwReserved3: DWord; // reserved; do not use
  end;
  TVIDEOHDRPtr= ^TVideoHDR;

  DWordDim= array[1..PICWIDTH] of DWord;

  TForm1 = class(TForm)
    Timer1: TTimer;
    Panel1: TPanel;
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    FCapHandle: THandle;
    FCodec: TVideoCodec;
    FBuf1, FBuf2: array[1..PICHEIGHT] of DWordDim;
    FBitmap: TBitmap;
    FJpeg: TJPegImage;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


function capCreateCaptureWindow(lpszWindowName: LPCSTR;
  dwStyle: DWORD;
  x, y,
  nWidth,
  nHeight: integer;
  hwndParent: HWND;
  nID: integer): HWND; stdcall;
  external 'AVICAP32.DLL' name 'capCreateCaptureWindowA';


function FrameCallbackFunction(AHandle: hWnd; VIDEOHDR: TVideoHDRPtr): bool; stdcall;
var
  I: integer;
begin
  result:= true;

  with form1 do begin
  try
    ConvertCodecToRGB(FCodec, VideoHDR^.lpData, @FBuf2, PICWIDTH, PICHEIGHT);

    for I:= 1 to PICHEIGHT do FBuf1[I]:= FBuf2[PICHEIGHT- (I- 1)];
    SetBitmapBits(FBitmap.Handle, PICWIDTH* PICHEIGHT* SizeOf(DWord), @FBuf1);

    FBitmap.Canvas.Brush.Color:= clWhite;
    FBitmap.Canvas.Font.Color:= clRed;

    FJpeg.Assign(FBitmap);

    FJpeg.CompressionQuality:= 85;
    FJpeg.ProgressiveEncoding:= true;
    FJpeg.SaveToFile('c:\webcam.jpg');

    SendMessage(FCapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, 0);
  except
  end;
  end;
end;

//------------------------------------------------------------------------------

procedure TForm1.FormCreate(Sender: TObject);
var  BitmapInfo: TBitmapInfo;
begin
  Timer1.Enabled := false;

  FBitmap:= TBitmap.Create;
  FBitmap.Width:= PICWIDTH;
  FBitmap.Height:= PICHEIGHT+ SUBLINEHEIGHT+ EXTRAHEIGHT;
  FBitmap.PixelFormat:= pf32Bit;
  FBitmap.Canvas.Font.Assign(Panel1.Font);
  FBitmap.Canvas.Brush.Style:= bssolid;
  FBitmap.Canvas.Rectangle(0, PICHEIGHT, PICWIDTH, PICHEIGHT+ SUBLINEHEIGHT);

  FJpeg:= TJpegImage.Create;

  FCapHandle:= capCreateCaptureWindow('Video', WS_CHILD or WS_VISIBLE, 0, 0, PICWIDTH, PICHEIGHT, Panel1.Handle, 1);
  SendMessage(FCapHandle, WM_CAP_DRIVER_CONNECT, 0, 0);
  SendMessage(FCapHandle, WM_CAP_SET_PREVIEWRATE, 15000, 0);
  sendMessage(FCapHandle, WM_CAP_SET_OVERLAY, 1, 0);
  SendMessage(FCapHandle, WM_CAP_SET_PREVIEW, 1, 0);

  // SendMessage(FCapHandle, WM_CAP_DLG_VIDEOFORMAT,1,0);     // -this was commented out

  FillChar(BitmapInfo, SizeOf(BitmapInfo), 0);
  SendMessage(FCapHandle, WM_CAP_GET_VIDEOFORMAT, SizeOf(BitmapInfo), Integer(@BitmapInfo));
  FCodec:= BICompressionToVideoCodec(bitmapinfo.bmiHeader.biCompression);
  if FCodec<> vcUnknown then begin
    Timer1.Enabled:= true;
  end;
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
  FBitmap.Free;
  FJpeg.Free;
end;


procedure TForm1.FormActivate(Sender: TObject);
begin
  if FCodec= vcUnknown then
    showMessage('unknown compression');
  FBitmap.Height:= PICHEIGHT+ SUBLINEHEIGHT;
end;

//------------------------------------------------------------------------------

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  SendMessage(FCapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, integer(@FrameCallbackFunction));
  SendMessage(FCapHandle, WM_CAP_GRAB_FRAME_NOSTOP, 1, 0); // ist hintergrundlauff盲hig
end;

end.

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 301
  ClientWidth = 562
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnActivate = FormActivate
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 48
    Top = 16
    Width = 185
    Height = 145
    Caption = 'Panel1'
    TabOrder = 0
  end
  object Timer1: TTimer
    OnTimer = Timer1Timer
    Left = 464
    Top = 24
  end
end

{**************************************************************************************************}
{                                                                                                  }
{  YUVConverts                                                                                     }
{                                                                                                  }
{  The contents of this file are subject to the Y Library Public License Version 1.0 (the          }
{  "License"); you may not use this file except in compliance with the License. You may obtain a   }
{  copy of the License at http://delphi.pjh2.de/                                                   }
{                                                                                                  }
{  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF  }
{  ANY KIND, either express or implied. See the License for the specific language governing        }
{  rights and limitations under the License.                                                       }
{                                                                                                  }
{  The Original Code is: YUVConverts.pas, part of CapDemoC.dpr.                                    }
{  The Initial Developer of the Original Code is Peter J. Haas (libs@pjh2.de). Portions created    }
{  by Peter J. Haas are Copyright (C) 2000-2005 Peter J. Haas. All Rights Reserved.                }
{                                                                                                  }
{  Contributor(s):                                                                                 }
{                                                                                                  }
{  You may retrieve the latest version of this file at the homepage of Peter J. Haas, located at   }
{  http://delphi.pjh2.de/                                                                          }
{                                                                                                  }
{**************************************************************************************************}

// For history see end of file

{$ALIGN ON, $BOOLEVAL OFF, $LONGSTRINGS ON, $IOCHECKS ON, $WRITEABLECONST OFF, $OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF, $TYPEDADDRESS ON, $MINENUMSIZE 1}

unit yuvconverts;

interface
uses
  Windows;

type
  TVideoCodec = (vcUnknown, vcRGB, vcYUY2, vcUYVY, vcBTYUV, vcYVU9, vcYUV12, vcY8, vcY211);

const
  BI_YUY2  = $32595559;  // 'YUY2'
  BI_UYVY  = $59565955;  // 'UYVY'
  BI_BTYUV = $50313459;  // 'Y41P'
  BI_YVU9  = $39555659;  // 'YVU9'  planar
  BI_YUV12 = $30323449;  // 'I420'  planar
  BI_Y8    = $20203859;  // 'Y8  '
  BI_Y211  = $31313259;  // 'Y211'

function BICompressionToVideoCodec(Value: DWord): TVideoCodec;

function ConvertCodecToRGB(Codec: TVideoCodec; Src, Dst: Pointer; AWidth, AHeight: Integer): Boolean;

implementation

function BICompressionToVideoCodec(Value: DWord): TVideoCodec;
begin
  case Value of
    BI_RGB, BI_BITFIELDS: Result := vcRGB;   // no RLE
    BI_YUY2:              Result := vcYUY2 ;
    BI_UYVY:              Result := vcUYVY ;
    BI_BTYUV:             Result := vcBTYUV;
    BI_YVU9:              Result := vcYVU9;
    BI_YUV12:             Result := vcYUV12;
    BI_Y8:                Result := vcY8;
    BI_Y211:              Result := vcY211;
  else
    Result := vcUnknown;
  end;
end;

const
  // RGB255 ColorFAQ
  fY  =  298.082 / 256;
  fRU =  0;
  fGU = -100.291 / 256;
  fBU =  516.411 / 256;
  fRV =  408.583 / 256;
  fGV = -208.120 / 256;
  fBV =  0;

{  // RGB219 ColorFAQ           too dark
  fY  =  256 / 256;
  fRU =  0;
  fGU =  -86.132 / 256;
  fBU =  443.506 / 256;
  fRV =  350.901 / 256;
  fGV = -178.738 / 256;
  fBV =  0; }

{  // Earl            same like RGB255
  fY  =  1.164;
  fRU =  0;
  fGU = -0.392;
  fBU =  2.017;
  fRV =  1.596;
  fGV = -0.813;
  fBV =  0;
}

// |R|   |fY fRU fRV|   |Y|   | 16|
// |G| = |fY fGU fGV| * |U| - |128|
// |B|   |fY fBU fBV|   |V|   |128|

type
  TYUV = packed record
    Y, U, V, F1: Byte;
  end;

  PBGR32 = ^TBGR32;
  TBGR32 = packed record
    B, G, R, A: Byte;
  end;

function YUVtoBGRAPixel(AYUV: DWord): DWord;
var
  ValueY, ValueU, ValueV: Integer;
  ValueB, ValueG, ValueR: Integer;
begin
  ValueY := TYUV(AYUV).Y - 16;
  ValueU := TYUV(AYUV).U - 128;
  ValueV := TYUV(AYUV).V - 128;

  ValueB := Trunc(fY * ValueY + fBU * ValueU);  // fBV = 0
  if ValueB > 255 then
    ValueB := 255;
  if ValueB <   0 then
    ValueB :=   0;

  ValueG := Trunc(fY * ValueY + fGU * ValueU + fGV * ValueV);
  if ValueG > 255 then
    ValueG := 255;
  if ValueG <   0 then
    ValueG :=   0;

  ValueR := Trunc(fY * ValueY + fRV * ValueV);  // fRU = 0
  if ValueR > 255 then
    ValueR := 255;
  if ValueR <   0 then
    ValueR :=   0;

  with TBGR32(Result) do begin
    B := ValueB;
    G := ValueG;
    R := ValueR;
    A := 0;
  end;
end;

type
  TDWordRec = packed record
  case Integer of
    0: (B0, B1, B2, B3: Byte);
    1: (W0, W1: Word);
  end;

// UYVY
// YUV 4:2:2 (Y sample at every pixel, U and V sampled at every second pixel
// horizontally on each line). A macropixel contains 2 pixels in 1 DWord.
// 16 Bits per Pixel, 4 Byte Macropixel
// U0 Y0 V0 Y1
procedure UYVYtoRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);
type
  PUYVY = ^TUYVY;
  TUYVY = packed record
    U, Y0, V, Y1: Byte;
  end;

var
  x, y: Integer;
  w: Integer;
  SrcPtr: PDWord;
  DstPtr: PDWord;
  SrcLineSize: Integer;
  DstLineSize: Integer;
  YUV: DWord;
  b: Byte;
begin
  SrcLineSize := AWidth * 2;
  DstLineSize := AWidth * 4;

  // Dst is Bottom Top Bitmap
  Inc(PByte(Dst), (AHeight - 1) * DstLineSize);

  w := (AWidth div 2) - 1;      { TODO : bei ungeraden Breiten fehlt letztes Pixel }
  for y := 0 to AHeight - 1 do begin
    SrcPtr := Src;
    DstPtr := Dst;
    for x := 0 to w do begin
      YUV := SrcPtr^;
      // First Pixel
      b := TDWordRec(YUV).B0;
      TDWordRec(YUV).B0 := TDWordRec(YUV).B1;
      TDWordRec(YUV).B1 := b;

      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      // Second Pixel
      TDWordRec(YUV).B0 := TDWordRec(YUV).B3;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Inc(SrcPtr);
    end;
    Dec(PByte(Dst), DstLineSize);
    Inc(PByte(Src), SrcLineSize);
  end;
end;

// YUY2, YUNV, V422
// YUV 4:2:2 as for UYVY but with different component ordering within the DWord
// macropixel.
// 16 Bits per Pixel, 4 Byte Macropixel
// Y0 U0 Y1 V0
procedure YUY2toRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);
var
  x, y: Integer;
  w: Integer;
  SrcPtr: PDWord;
  DstPtr: PDWord;
  SrcLineSize: Integer;
  DstLineSize: Integer;
  YUV: DWord;
  b: Byte;
begin
  SrcLineSize := AWidth * 2;
  DstLineSize := AWidth * 4;

  // Dst is Bottom Top Bitmap
  Inc(PByte(Dst), (AHeight - 1) * DstLineSize);

  w := (AWidth div 2) - 1;      { TODO : bei ungeraden Breiten fehlt letztes Pixel }
  for y := 0 to AHeight - 1 do begin
    SrcPtr := Src;
    DstPtr := Dst;
    for x := 0 to w do begin
      YUV := SrcPtr^;
      // First Pixel
      b := TDWordRec(YUV).B2;                  //  Y0 U Y1 V -> Y0 U V Y1
      TDWordRec(YUV).B2 := TDWordRec(YUV).B3;
      TDWordRec(YUV).B3 := b;

      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      // Second Pixel
      TDWordRec(YUV).B0 := TDWordRec(YUV).B3;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Inc(SrcPtr);
    end;
    Dec(PByte(Dst), DstLineSize);
    Inc(PByte(Src), SrcLineSize);
  end;
end;

// BTYUV, I42P
// YUV 4:1:1 (Y sample at every pixel, U and V sampled at every fourth pixel
// horizontally on each line). A macropixel contains 8 pixels in 3 DWords.
// 16 Bits per Pixel, 12 Byte Macropixel
// U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7
procedure BTYUVtoRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);
type
  PBTYUVPixel = ^TBTYUVPixel;
  TBTYUVPixel = packed record
    U0, Y0, V0, Y1, U4, Y2, V4, Y3, Y4, Y5, Y6, Y7: Byte;
  end;

var
  x, y: Integer;
  w: Integer;
  SrcPtr: PBTYUVPixel;
  DstPtr: PDWord;
  SrcLineSize: Integer;
  DstLineSize: Integer;
  YUV: DWord;
  SrcPixel: TBTYUVPixel;
begin
  SrcLineSize := ((AWidth + 7) div 8) * (3 * 4);
  DstLineSize := AWidth * 4;

  w := AWidth - 1;
  for y := 0 to AHeight - 1 do begin
    SrcPtr := Src;
    DstPtr := Dst;
    x := w;
    while x > 0 do begin
      // read macropixel
      SrcPixel := SrcPtr^;
      // First 4 Pixel
      TYUV(YUV).U := SrcPixel.U0;
      TYUV(YUV).V := SrcPixel.V0;

      TYUV(YUV).Y := SrcPixel.Y0;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      TYUV(YUV).Y := SrcPixel.Y1;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      TYUV(YUV).Y := SrcPixel.Y2;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      TYUV(YUV).Y := SrcPixel.Y3;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      // Second 4 Pixel
      TYUV(YUV).U := SrcPixel.U4;
      TYUV(YUV).V := SrcPixel.V4;

      TYUV(YUV).Y := SrcPixel.Y4;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      TYUV(YUV).Y := SrcPixel.Y5;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      TYUV(YUV).Y := SrcPixel.Y6;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);
      Dec(x);
      if x <= 0 then
        Break;

      TYUV(YUV).Y := SrcPixel.Y7;
      DstPtr^ := YUVtoBGRAPixel(YUV);
      Inc(DstPtr);

      Inc(SrcPtr);
    end;
    Inc(PByte(Dst), DstLineSize);
    Inc(PByte(Src), SrcLineSize);
  end;
end;

// YVU9
// 8 bit Y plane followed by 8 bit 4x4 subsampled V and U planes.
// 9 Bits per Pixel, planar format
procedure YVU9toRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);
var
  x, y, r, l: Integer;
  w: Integer;
  SrcYPtr: PByte;
  SrcUPtr: PByte;
  SrcVPtr: PByte;
  DstPtr: PDWord;
  SrcYLineSize: Integer;
  SrcUVLineSize: Integer;
  DstLineSize: Integer;
  YUV: DWord;
begin
  DstLineSize := AWidth * 4;

  SrcYLineSize := AWidth;
  SrcUVLineSize := (AWidth + 3) div 4;

  // Dst is Bottom Top Bitmap
  Inc(PByte(Dst), (AHeight - 1) * DstLineSize);

  SrcYPtr := Src;
  SrcVPtr := PByte(LongInt(SrcYPtr) + SrcYLineSize * AHeight);
  SrcUPtr := PByte(LongInt(SrcVPtr) + SrcUVLineSize * ((AHeight + 3) div 4));

  w := (AWidth div 4) - 1;      { TODO : bei ungeraden Breiten fehlt letztes Pixel }
  for y := 0 to (AHeight div 4) - 1 do begin  { TODO : bei ungeraden H枚hen fehlt letzte Reihe }
    for l := 0 to 3 do begin
      DstPtr := Dst;
      for x := 0 to w do begin
        // U and V
        YUV := (SrcUPtr^ shl 8) or (SrcVPtr^ shl 16);
        for r := 0 to 3 do begin
          YUV := (YUV and $00FFFF00) or SrcYPtr^;
          DstPtr^ := YUVtoBGRAPixel(YUV);
          Inc(DstPtr);
          Inc(SrcYPtr);
        end;
        Inc(SrcUPtr);
        Inc(SrcVPtr);
      end;
      Dec(PByte(Dst), DstLineSize);
      if l < 3 then begin
        Dec(SrcUPtr, SrcUVLineSize);
        Dec(SrcVPtr, SrcUVLineSize);
      end;
    end;
  end;
end;

// YUV12, I420, IYUV
// 8 bit Y plane followed by 8 bit 2x2 subsampled U and V planes.
// 12 Bits per Pixel, planar format
procedure YUV12toRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);  // I420, IYUV
var
  x, y, l: Integer;
  w: Integer;
  SrcYPtr: PByte;
  SrcUPtr: PByte;
  SrcVPtr: PByte;
  DstPtr: PDWord;
  SrcYLineSize: Integer;
  SrcUVLineSize: Integer;
  DstLineSize: Integer;
  YUV: DWord;
begin
  DstLineSize := AWidth * 4;

  SrcYLineSize := AWidth;
  SrcUVLineSize := (AWidth + 1) div 2;

  // Dst is Bottom Top Bitmap
  Inc(PByte(Dst), (AHeight - 1) * DstLineSize);

  SrcYPtr := Src;
  SrcUPtr := PByte(LongInt(SrcYPtr) + SrcYLineSize * AHeight);
  SrcVPtr := PByte(LongInt(SrcUPtr) + SrcUVLineSize * ((AHeight + 1) div 2));

  w := (AWidth div 2) - 1;      { TODO : bei ungeraden Breiten fehlt letztes Pixel }
  for y := 0 to (AHeight div 2) - 1 do begin  { TODO : bei ungeraden H枚hen fehlt letzte Reihe }
    for l := 0 to 1 do begin
      DstPtr := Dst;
      for x := 0 to w do begin
        // First Pixel
        YUV := SrcYPtr^ or (SrcUPtr^ shl 8) or (SrcVPtr^ shl 16);
        DstPtr^ := YUVtoBGRAPixel(YUV);
        Inc(DstPtr);
        Inc(SrcYPtr);
        // Second Pixel
        YUV := (YUV and $00FFFF00) or SrcYPtr^;
        DstPtr^ := YUVtoBGRAPixel(YUV);
        Inc(DstPtr);
        Inc(SrcYPtr);
        Inc(SrcUPtr);
        Inc(SrcVPtr);
      end;
      Dec(PByte(Dst), DstLineSize);
      if l = 0 then begin
        Dec(SrcUPtr, SrcUVLineSize);
        Dec(SrcVPtr, SrcUVLineSize);
      end;
    end;
  end;
end;

// Y8, Y800
// Simple, single Y plane for monochrome images.
// 8 Bits per Pixel, planar format
procedure Y8toRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);
var
  x, y: Integer;
  w: Integer;
  SrcPtr: PByte;
  DstPtr: PDWord;
  SrcLineSize: Integer;
  DstLineSize: Integer;
  Pixel: DWord;
begin
  SrcLineSize := AWidth;
  DstLineSize := AWidth * 4;

  // Dst is Bottom Top Bitmap
  Inc(PByte(Dst), (AHeight - 1) * DstLineSize);

  w := (AWidth) - 1;
  for y := 0 to AHeight - 1 do begin
    SrcPtr := Src;
    DstPtr := Dst;
    for x := 0 to w do begin
      Pixel := SrcPtr^;
      TDWordRec(Pixel).B1 := TDWordRec(Pixel).B0;
      TDWordRec(Pixel).B2 := TDWordRec(Pixel).B0;
      TDWordRec(Pixel).B3 := 0;
      DstPtr^ := Pixel;
      Inc(DstPtr);
      Inc(SrcPtr);
    end;
    Dec(PByte(Dst), DstLineSize);
    Inc(PByte(Src), SrcLineSize);
  end;
end;

// Y211
// Packed YUV format with Y sampled at every second pixel across each line
// and U and V sampled at every fourth pixel.
// 8 Bits per Pixel, 4 Byte Macropixel
// Y0, U0, Y2, V0
procedure Y211toRGB(Src, Dst: Pointer; AWidth, AHeight: Integer);
type
  PYUYV = ^TYUYV;
  TYUYV = packed record
    Y0, U, Y2, V: Byte;
  end;

var
  x, y: Integer;
  w : Integer;
  SrcPtr : PDWord;
  DstPtr : PDWord;
  SrcLineSize : Integer;
  DstLineSize : Integer;
  YUV: DWord;
  BGR: DWord;
  b: Byte;
begin
  SrcLineSize := ((AWidth + 3) div 4) * 4;
  DstLineSize := AWidth * 4;

  // Dst is Bottom Top Bitmap
  Inc(PByte(Dst), (AHeight - 1) * DstLineSize);

  w := (AWidth div 4) - 1;      { TODO : bei ungeraden Breiten fehlt letztes Pixel }
  for y := 0 to AHeight - 1 do begin
    SrcPtr := Src;
    DstPtr := Dst;
    for x := 0 to w do begin
      // Y0 U Y2 V
      YUV := SrcPtr^;
      // First and second Pixel
      b := TDWordRec(YUV).B2;                   // Y0 U Y2 V -> Y0 U V Y2
      TDWordRec(YUV).B2 := TDWordRec(YUV).B3;
      TDWordRec(YUV).B3 := b;
      BGR := YUVtoBGRAPixel(YUV);
      DstPtr^ := BGR;
      Inc(DstPtr);
      DstPtr^ := BGR;
      Inc(DstPtr);

      // third and fourth
      TDWordRec(YUV).B0 := TDWordRec(YUV).B3;   // Y0 U V Y2 -> Y2 U V Y2
      BGR := YUVtoBGRAPixel(YUV);
      DstPtr^ := BGR;
      Inc(DstPtr);
      DstPtr^ := BGR;
      Inc(DstPtr);

      Inc(SrcPtr);
    end;
    Dec(PByte(Dst), DstLineSize);
    Inc(PByte(Src), SrcLineSize);
  end;
end;

function ConvertCodecToRGB(Codec: TVideoCodec; Src, Dst: Pointer; AWidth, AHeight: Integer): Boolean;
begin
  Result := True;
  case Codec of
    vcYUY2:  YUY2toRGB (Src, Dst, AWidth, AHeight);
    vcUYVY:  UYVYtoRGB (Src, Dst, AWidth, AHeight);
    vcBTYUV: BTYUVtoRGB(Src, Dst, AWidth, AHeight);
    vcYVU9:  YVU9toRGB (Src, Dst, AWidth, AHeight);
    vcYUV12: YUV12toRGB(Src, Dst, AWidth, AHeight);
    vcY8:    Y8toRGB   (Src, Dst, AWidth, AHeight);
    vcY211:  Y211toRGB (Src, Dst, AWidth, AHeight);
  else
    Result := False;
  end;
end;

//  History:
//  2005-02-12, Peter J. Haas
//
//  2002-02-22, Peter J. Haas
//   - add YVU9, YUV12 (I420)
//   - add Y211 (untested)
//
//  2001-06-14, Peter J. Haas
//   - First public version
//   - YUY2, UYVY, BTYUV (Y41P), Y8

end.

一些消息结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var
    MsgResult : Integer ;

procedure TForm1.FormCreate(Sender: TObject);
var  BitmapInfo: TBitmapInfo;

begin
  Timer1.Enabled := false;

  FBitmap:= TBitmap.Create;
  FBitmap.Width:= PICWIDTH;
  FBitmap.Height:= PICHEIGHT+ SUBLINEHEIGHT+ EXTRAHEIGHT;
  FBitmap.PixelFormat:= pf32Bit;
  FBitmap.Canvas.Font.Assign(Panel1.Font);
  FBitmap.Canvas.Brush.Style:= bssolid;
  FBitmap.Canvas.Rectangle(0, PICHEIGHT, PICWIDTH, PICHEIGHT+ SUBLINEHEIGHT);

  FJpeg:= TJpegImage.Create;

  FCapHandle:= capCreateCaptureWindow('Video', WS_CHILD or WS_VISIBLE, 0, 0, PICWIDTH, PICHEIGHT, Panel1.Handle, 1);   // returns 2558326
  MsgResult := SendMessage(FCapHandle, WM_CAP_DRIVER_CONNECT, 0, 0);                                                   // returns 0
  MsgResult := SendMessage(FCapHandle, WM_CAP_SET_PREVIEWRATE, 15000, 0);                                              // returns 1
  MsgResult := sendMessage(FCapHandle, WM_CAP_SET_OVERLAY, 1, 0);                                                      // returns 0
  MsgResult := SendMessage(FCapHandle, WM_CAP_SET_PREVIEW, 1, 0);                                                      // returns 0

  // SendMessage(FCapHandle, WM_CAP_DLG_VIDEOFORMAT,1,0);     // -this was commented out

  FillChar(BitmapInfo, SizeOf(BitmapInfo), 0);
  MsgResult := SendMessage(FCapHandle, WM_CAP_GET_VIDEOFORMAT, SizeOf(BitmapInfo), Integer(@BitmapInfo));              // returns 0
  FCodec:= BICompressionToVideoCodec(bitmapinfo.bmiHeader.biCompression);                                              // returns vcRGB
  if FCodec<> vcUnknown then begin
    Timer1.Enabled:= true;
  end;
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
  FBitmap.Free;
  FJpeg.Free;
end;


procedure TForm1.FormActivate(Sender: TObject);
begin
  if FCodec= vcUnknown then
    showMessage('unknown compression');
  FBitmap.Height:= PICHEIGHT+ SUBLINEHEIGHT;
end;

//------------------------------------------------------------------------------

procedure TForm1.Timer1Timer(Sender: TObject);
begin
MsgResult := SendMessage(FCapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, integer(@FrameCallbackFunction));         // returns 0
MsgResult := SendMessage(FCapHandle, WM_CAP_GRAB_FRAME_NOSTOP, 1, 0); // ist hintergrundlauff盲hig            // returns 0
end;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-08-11 06:01:34

你的程序可以在Win7 32位D2010上运行。

不过,它所做的是引发一个异常:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
---------------------------
Project WebCamTest.exe raised exception class EFCreateError with message 
'Cannot create file "c:\webcam.jpg". Access is denied'.
---------------------------

它可以通过更改

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
FJpeg.SaveToFile('c:\webcam.jpg');

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
FJpeg.SaveToFile(TPath.GetTempPath + '\webcam.jpg');

而且,它不会显示整个可用的图像,你必须放大你的面板,重新居中或缩小网络摄像头输出。

通过一些代码修改使其根据您的评论工作的更新...

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // introducing the RGB array and a buffer
  TVideoArray = array[1..PICHEIGHT] of array[1..PICWIDTH] of TRGBTriple;
  PVideoArray = ^TVideoArray;

  TForm1 = class(TForm)
[...]
  FBuf24_1: TVideoArray;
[...]

function FrameCallbackFunction(AHandle: hWnd; VIDEOHDR: TVideoHDRPtr): bool; stdcall;
var
  I: integer;
begin
  result:= true;

  with form1 do begin
  try
    if ConvertCodecToRGB(FCodec, VideoHDR^.lpData, @FBuf2, PICWIDTH, PICHEIGHT) then
    begin
      for I:= 1 to PICHEIGHT do FBuf1[I]:= FBuf2[PICHEIGHT- (I- 1)];
      SetBitmapBits(FBitmap.Handle, PICWIDTH* PICHEIGHT* SizeOf(DWord), @FBuf1);
    end
    else
    begin  // assume RGB
      for I:= 1 to PICHEIGHT do
        FBuf24_1[I] := PVideoArray(VideoHDR^.lpData)^[PICHEIGHT-I+1];
      SetBitmapBits(FBitmap.Handle, PICWIDTH* PICHEIGHT* SizeOf(RGBTriple), @FBuf24_1);
    end;
[...]
票数 5
EN

Stack Overflow用户

发布于 2014-05-03 19:26:13

如果您希望使用VFW而不是过时的Video For Windows (VFW):http://www.delphibasics.info/home/delphibasicsprojects/directxdelphiwebcamcaptureexample

以下是一个更大项目的链接,该项目实现了下面详细介绍的代码:http://www.delphibasics.info/home/delphibasicssnippets/delphiwebcamcaptureexample

根据您的需要交换注释符号所指示的行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
program WebcamTest;
//www.delphibasics.info
//cswi

uses
  Windows;

const
  WM_CAP_DRIVER_CONNECT = 1034;
  WM_CAP_GRAB_FRAME = 1084;
  //WM_CAP_SAVEDIB = 1049;
  WM_CAP_EDIT_COPY = 1054;//
  WM_CAP_DRIVER_DISCONNECT = 1035;

function SendMessageA(hWnd: Integer;
                      Msg: Integer;
                      wParam: Integer;
                      lParam: Integer): Integer;
                      stdcall;
                      external 'user32.dll' name 'SendMessageA';

function capGetDriverDescriptionA(DrvIndex: Cardinal;
                                  Name: PAnsiChar;
                                  NameLen: Integer;
                                  Description: PAnsiChar;
                                  DescLen: Integer) : Boolean;
                                  stdcall;
                                external 'avicap32.dll' name 'capGetDriverDescriptionA';

function capCreateCaptureWindowA(lpszWindowName: PAnsiChar;
                                 dwStyle: Integer;
                                 x : Integer;
                                 y : Integer;
                                 nWidth : Integer;
                                 nHeight : Integer;
                                 ParentWin: Integer;
                                 nId: Integer): Integer;
                                 stdcall;
                                 external 'avicap32.dll' name 'capCreateCaptureWindowA';

function IntToStr(i: Integer): String;
begin
  Str(i, Result);
end;

var
  WebCamId : Integer;
  CaptureWindow : Integer;
  x : Integer;
  FileName : PAnsiChar;
  hData:  DWORD;
  pData:  Pointer;
  dwSize: DWORD;
  szText : AnsiString;
  FileHandle, BytesWritten : LongWord;
begin
  WebcamId := 0;
  CaptureWindow := capCreateCaptureWindowA('CaptureWindow', 0, 0, 0, 0, 0, 0, 0);
  if CaptureWindow <> 0 then
  begin
    if SendMessageA(CaptureWindow, WM_CAP_DRIVER_CONNECT, WebCamId, 0) <> 1 then
    begin
      SendMessageA(CaptureWindow, WM_CAP_DRIVER_DISCONNECT, 0, 0);
    end
    else
    begin
      for x := 1 to 20 do // Take 20 photos.
      begin
        SendMessageA(CaptureWindow, WM_CAP_GRAB_FRAME, 0, 0);
        FileName := PAnsiChar('C:\Test' + IntToStr(x) + '.bmp');
        //SendMessageA(CaptureWindow, WM_CAP_SAVEDIB, 0, LongInt(FileName));
        SendMessageA(CaptureWindow, WM_CAP_EDIT_COPY, 0, LongInt(FileName));//
        if OpenClipBoard(0) then
        begin
          hData := GetClipBoardData(CF_DIB);
          if hData <> 0 then
          begin
            pData := GlobalLock(hData);
            if pData <> nil then
            begin
              dwSize := GlobalSize(hData);
              if dwSize <> 0 then
              begin
                FileHandle := CreateFileA(FileName, GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, 0);
                WriteFile(FileHandle, pData, dwSize, BytesWritten, nil);
                CloseHandle(FileHandle);
              end;
              GlobalUnlock(DWORD(pData));
            end;
          end;
          CloseClipBoard;
        end;
      end;
    end;
    SendMessageA(CaptureWindow, WM_CAP_DRIVER_DISCONNECT, 0, 0);
  end;
end.
票数 1
EN

Stack Overflow用户

发布于 2010-08-11 03:48:13

我使用一个名为TVideoCap的组件。它是针对3、4和5的,但它包含了源代码,因此很容易更新。它会做你想做的事。只需搜索“TVideoCap”即可。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3454688

复制
相关文章
在Excel中获得汉字的首字母
Function hztopy(hzpy As String) As String
钱塘小甲子
2019/06/22
1.4K0
【Excel】用公式提取Excel单元格中的汉字
昨天一个前端的朋友找我帮忙用excel提取代码中的汉字(字符串),可算费了劲儿了,他要提取的内容均在单引号中,但问题是没有统一的规律,同一个单元格可能存在多个要提取的内容,而且汉字中间也夹杂其他字符。
数据科学社区
2018/06/11
8.5K0
oracle 汉字显示问号
3. 修改变量 现在需要将AMERICAN_AMERICA.ZHS16GBK 改为 SIMPLIFIED CHINESE_CHINA.ZH16GBK oracle用户编辑家目录的 .bash_profile 添加
范一刀
2021/08/10
2.1K0
Excel图表技巧16:在图表中突出显示最大值
要突出显示Excel图表中的值,只需添加一个带有要突出显示的值的额外系列。假设想要突出显示销量最大的产品,添加一个额外的列来计算值,如下图3所示。
fanjy
2021/09/22
3.6K0
excel 汉字转拼音「建议收藏」
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/151859.html原文链接:https://javaforall.cn
全栈程序员站长
2022/06/24
7.8K0
芒果tv在miniblink无法显示的bug分析
http://www.mgtv.com/pcclient/tv/里用了window.external,
龙泉寺扫地僧
2019/02/20
9150
如何在AI Studio数据可视化图像中显示汉字
AI Studio是一个非常好用的数据科学在线实验平台,不论是教学、学习还是开发,都可以使用。但是,下面的缺憾未免成为了珍珠上的一点瑕疵。
老齐
2020/05/15
3.4K0
如何在AI Studio数据可视化图像中显示汉字
在DataGrid中显示图片
    DadaGrid 是 ASP.NET 编程中一个很重要的控件,其优良的可定制功能为提高它的表现力提供了极大的方便。除了与数据源直接绑定以外,我们还可以通过列绑定模板对 DataGrid 的列进行自定义,来按照我们设定的格式显示数据。
Java架构师必看
2021/03/22
3.4K0
c#:winform读取excel,并显示在griddataview
立羽
2023/08/24
1.4K0
c#:winform读取excel,并显示在griddataview
如何实现在Excel表格中删除汉字而不破坏其他内容?
方法一: 先将数据复制到WORD中, 在WORD中,编辑/替换 “查找内容”输入:[一-龤]      (带中括号) “替换为”输入:/ 勾选“使用通配符” 点“全部替换” 然后再将数据复制回EXCEL。 附: 龤:ALT+64922 WORD中是:ALT+40868 方法二: =REPLACE(A1,MATCH(” “,MIDB(A1,ROW($1:$100),1),),LENB(A1)-LEN(A1),”/”) 方法三: 若你汉字均在前面,在b1输入公式:=right(a1,l
用户1272546
2018/06/04
2.7K0
关于在eclipse中中文汉字乱码的解决方式[通俗易懂]
很多童鞋反应在吧项目导入到eclipse(myeclipse)时中文会有乱码,修改了编码格式后还是乱码,这里给大家介绍一下关于中文乱码时修改编码的注意事项:
全栈程序员站长
2022/09/01
5.2K0
关于在eclipse中中文汉字乱码的解决方式[通俗易懂]
如何实现在Excel表格中删除汉字而不破坏其他内容?
方法一: 先将数据复制到WORD中, 在WORD中,编辑/替换 “查找内容”输入:[一-龤]      (带中括号) “替换为”输入:/ 勾选“使用通配符” 点“全部替换”
用户1191760
2019/02/27
3.7K0
在Excel中创建悬浮图
步骤1:根据原始数据,整理用于创建图表的数据,如下图2所示。一个名为“隐藏”的列,计算出悬浮的高度,也就是前面显示的柱状的高度之后;一个名为“显示”的列,即绘制的可见柱状的高度。
fanjy
2023/10/05
6480
在Excel中创建悬浮图
使用WebSocket在Server类中无法使用Autowired注解进行自动注入
在SpringBoot项目中使用WebSocket的过程中有其他的业务操作需要注入其它接口来做相应的业务操作,但是在WebSocket的Server类中使用Autowired注解无效,这样注入的对象就是空,在使用过程中会报空指针异常。
余生大大
2022/11/02
5.6K0
在Excel中创建瀑布图
在Excel中很容易创建瀑布图,因为自Excel 2016就推出了瀑布图。然而,改变瀑布颜色稍微有点困难。
fanjy
2023/08/30
6580
在Excel中创建瀑布图
【VBA】在excel中检索文本
虽然在excel文件中检索的vba代码不知道写了多少遍了,每次需要的时候,都是从网上找,然后写。实在是低效的做法。从网上找了一段代码,放在此处,以后需要的时候可以随手拿来。
东风压倒西风
2022/09/06
2.8K0
cmder 无法显示中文
cmder 默认是不支持中文字符的,可以在 Setting > Startup > Environment 下增加一行语言设置:
zucchiniy
2020/05/22
2.6K0
WPF 弹出 popup 里面的 TextBox 无法输入汉字
这是一个 wpf 的bug,在弹出Popup之后,如果 Popup 里面有 TextBox ,这时无法在里面输入文字。
林德熙
2018/09/18
1.7K0
WPF 弹出 popup 里面的 TextBox 无法输入汉字
这是一个 wpf 的bug,在弹出Popup之后,如果 Popup 里面有 TextBox ,这时无法在里面输入文字。
林德熙
2022/08/04
1.8K0
点击加载更多

相似问题

在AJAX和excel中显示汉字

14

在WPF中突出显示/characters行

16

无法在Qt-Embedded 4.7.3中显示汉字

24

在php中如何显示汉字?

30

在HTML文件中显示汉字

13
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文