2013年05月13日

WEBカメラのキャプチャ

最近ニコニコ生放送を見るようになった。大変な盛況ぶりである。けっこう多くの人が顔を出してしゃべっている。本名どころか住所や口座番号まで公表している人がいる。そのうち、自分でも放送やskypeがしたくなってきて、カメラを買ってきた。いわゆる「WEBカメラ」である。USBに接続して使うマイク内臓のものが3000円もしなかった。カメラを買うのは初めてではないが、前回はたしかwindows98、NT4.0の時代。Intelのカメラだったがもう捨ててしまって画素数がいくつだったのかも覚えていない。

配信はカメラで顔を写してしゃべるのが普通だがそれだけではなく、実行しているゲーム画面を映したり、車に載せたり、パソコンのデスクトップをそのまま放送することなどもできる。そしてそれをするためのソフトがいろいろあるのでそれを使えばいいのだが、単純にWEBカメラの画像を表示するだけであれば自分で作れるのではないかと思っていろいろ調べてみた。

方法はいろいろあるのだが、私の環境(Windows7 Home Premium 64bit, Delphi 2007 for Win32)で動作確認できたのは下記サイトで公開されているものくらいだった。
http://www1.iwate-ed.jp/tantou/joho/material/interval_shot/

こちらではexeファイルとunitのpascalソースのみが公開されていて、exeファイルを実行するとちゃんと動くのだが、ソースを自分でdelphiで開いてコンパイルするとうまく動かない。1,2日ほど苦闘して改造しながらなんとか動くものができた。

このプログラムは特に追加で何かをインストールする必要はない。
ソースを見ると、AVICAP32.DLLを使って、
capCreateCaptureWindowA
capGetDriverDescriptionA
というAPIを呼び出し、

さらに
SendMessageA
SetWindowPos
などのAPIを使ってカメラの映像を表示させていた。

そしてその静止画映像をJPGで保存しているのだが、私はそこはbmpでそのまま保存するようにした。

動かなかったのは、保存した映像がサイズゼロの画像になってしまうところである。
でもフォーム上に画像は表示されているので、その位置をbitbltでコピーして保存した。

以下はソースの一部である。

function capCreateCaptureWindowA(WindowName: PChar;
dwStyle: Cardinal; x,y, nWidth,nHeight: Integer;
ParentWin: HWnd; nID: Integer): HWnd; stdcall;
external 'AVICAP32.DLL';

function capGetDriverDescriptionA(wDriverIndex: Short;
lpszName: String; cbName : Integer;
lpszVer : String; cbVer : Integer): Boolean; stdcall;
external 'AVICAP32.DLL';

procedure TForm1.btnConnectClickClick(Sender: TObject);
const
str_Connect = 'Webカメラに接続';
str_Disconn = '接続解除';
begin
if (Sender as TButton).Caption = str_Connect then
begin
CaptureWnd := capCreateCaptureWindowA('0',
WS_CHILD or WS_VISIBLE, CaptureLeft, CaptureTop,
CaptureWidth, CaptureHeight,Handle,0);
if CaptureWnd<>0 then
begin
//デバイスへの接続
SendMessageA(CaptureWnd,WM_CAP_DRIVER_CONNECT,0,0);
//プレビュースケール
SendMessageA(CaptureWnd,WM_CAP_SET_SCALE,-1,0);
//プレビューのコマ数(ミリ秒)
SendMessageA(CaptureWnd,WM_CAP_SET_PREVIEWRATE,30,0);
// プレビュー開始
SendMessageA(CaptureWnd,WM_CAP_SET_PREVIEW,-1,0);
//
SetWindowPos(CaptureWnd,HWND_BOTTOM, 0, 0,
CaptureImage.Width,CaptureImage.Height,
SWP_NOMOVE or SWP_NOZORDER);

end;
(Sender as TButton).Caption:= str_Disconn

end
else
begin
//if CaptureWnd<>0 then
SendMessage(CaptureWnd,WM_CAP_DRIVER_DISCONNECT,0,0);
DestroyWindow(CaptureWnd);
CaptureWnd := 0;
(Sender as TButton).Caption:= str_Connect;

end
end;


いろいろと試行錯誤しながら思ったのは、カメラと同様にデスクトップの状況もキャプチャできないかということである。それができるソフトはいろいろあるので可能なのだろうが、WEBを探してかんたんに見つかるような情報はなかった。

上記の部分で、キャプチャ対象としてカメラのソースを指定しているところを、デスクトップにしてやればデスクトップがキャプチャできるのではないかと思った。

最初は capCreateCaptureWindowA で指定している Handleかなと思ったのだがこれは parentwindowつまりその上にカメラの映像が表示されるウィンドウのことだ。ためしにここを デスクトップにしてみるとデスクトップ上に表示された。

ただしこれは「ウィンドウ」なのでフォームの中のビットマップなどにアサインすることはできないようだ。

最初に指定している'0'はWindownameとなっているが、これを1に変えても動作に変わりはなかった。








posted by delsoli at 23:30| Comment(0) | delphi | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。