« MiGrep2その後(3)書庫ファイル内の検索 | トップページ | DelphiとLazarusでのドロップファイル処理の違い »

2017.04.18

Webカメラの映像を表示して、画像をJpegファイルに保存する(Lazarus/Delphiファイルサイズその2)

情報元
Webカメラ インターバル撮影ソフト
開発者:岩手県立総合教育センター奥田昌夫氏

オリジナルソースを元に、ボタンを押したらWebカメラの映像をJpegファイルに保存するだけの機能に絞り込みました。このプログラムは、廉価・簡易型の履歴写真保存システムとしての運用を想定しています(Webカメラで被写体を撮影して、USBフットスイッチ等の信号で随時写真に記録するなど)。
フォルダボタンでJpeg画像フィルの保存先フォルダを指定して、カメラ接続ボタンでWEBカメラに接続し、撮影ボタンで撮影・保存します。Jpeg画像は指定したフォルダに今日の日付のフォルダを作成して、その中に撮影時間をファイル名にして保存します。ファイル名は時分秒m秒で作成しますので、1秒以下の連続撮影でもファイルを上書きすることはありません。

今回は業務目的での使用を想定していますので、Delphi XE10.1 Starter版ではなくDelphi XE2 Pro版とLazarus1.7+FPC3.1で実行ファイルを作成しました。

実行状態
Webcam


で、お約束?の実行ファイルのサイズは以下の通りとなります。

Delphi XE10.1      2,322,432 バイト
Delphi XE2        1,721,344 バイト
Lazarus1.7+FPC3.1   1,724,416 バイト

Delphi XE2 x86_64   2,258,944 バイト
Lazarus1.7 x86_64   2,391,040 バイト

32bit版の実行ファイルサイズはXE2とLazarusでほぼ同等。試しに64bit版の実行ファイルを作成してみたところ、こちらはXE2の方が若干小さいようです。また、やはりXE10.1はちょっと大きいですね。

試しにDelphi7用にソースを一部修正してコンパイルした実行ファイルサイズは

Delphi7 492,544 バイト

Delphi7最強!と言いたいところですが、いかんせんWindowsXP以前の開発環境ですから単純に比較は出来ないんでしょうね。Delphi7で作成た実行ファイルもWIndows7上で問題なく動作しますが、ボタン等のWindowsコントロールデザインがWindows98時代のままだったりします。

今回はDelphi XE2用のプロジェクトソースと実行ファイル、Lazarus用のプロジェクトソースと実行ファイル、Delphi7用のソースファイルを公開します。

尚、LazarusではDelphi用ソースをそのままコンパイルすると撮影した画像が正常にBitBltされずに真っ黒になる問題を修正したため画像の処理が異なっています。また日本語表示で文字化けするため、ソースファイルをUTF8で保存して最初の行に{$CODEPAGE UTF8}を追加しています。

処理の一部

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';

// Webカメラ接続・解除処理
procedure TForm1.Button1Click(Sender: TObject);
begin
if not CaptureON 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 else begin
raise Exception.Create('Webカメラに接続できません.');
end;
Button1.Caption:= '接続解除(&D)';
CaptureON := True;
end else begin
SendMessage(CaptureWnd,WM_CAP_DRIVER_DISCONNECT, 0, 0);
DestroyWindow(CaptureWnd);
CaptureWnd := 0;
Button1.Caption:= 'カメラ接続(&W)';
CaptureON := False;
end;
Button2.Enabled := CaptureON;
end;

// 写真撮影・保存処理
procedure TForm1.Button2Click(Sender: TObject);
var
srcDC: HDC;
Bmp: TBitmap;
cBMP: HBITMAP; // LazarusのTBitmap不具合対策用
Jpg: TJpegImage;
fname, fldr: string;
i: integer;
begin
// Bitmapを準備
Bmp := TBitmap.Create;
try
srcDC := GetDC(Form1.Handle);
// サイズ設定
// LazarusではBitmapのサイズを直接指定するとうまく動かいないため、Bitmapの
// サイズを指定したハンドルを生成して、それをBitmapハンドルに代入する
cBMP := CreateCompatibleBitmap(srcDC, CaptureWidth, CaptureHeight);
//Bmp.Width := CaptureWidth;
//Bmp.Height := CaptureHeight;
Bmp.Handle := cBMP;
try
// Bitmapに画像をコピー
BitBlt(Bmp.Canvas.Handle, 0, 0,
CaptureWidth, CaptureHeight, srcDC, CaptureLeft, CaptureTop,
SRCCOPY);
// JpegImageを準備
Jpg := TJpegImage.Create;
try
// JpegにBitmap画像をコピー
Jpg.Assign(Bmp);
// 今日の日付でサブフォルダを準備する
DateTimeToString(fldr, 'yyyy-mm-dd', Now);
fldr := SaveFolder + '\' + fldr;
if not DirectoryExists(fldr) then
ForceDirectories(fldr);
// 現在時刻でファイル名を準備する
DateTimeToString(fname, 'hhnnss.zzz', Now);
// Jpeg画像を保存
Jpg.SaveToFile(fldr + '\' + fname + '.jpg');
finally
Jpg.Free;
end;
finally
ReleaseDC(Handle, srcDC);
end;
finally
DeleteObject(cBmp);
Bmp.Free;
end;
end;

「WebCAM.zip」をダウンロード


|

« MiGrep2その後(3)書庫ファイル内の検索 | トップページ | DelphiとLazarusでのドロップファイル処理の違い »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/22406/65167299

この記事へのトラックバック一覧です: Webカメラの映像を表示して、画像をJpegファイルに保存する(Lazarus/Delphiファイルサイズその2):

« MiGrep2その後(3)書庫ファイル内の検索 | トップページ | DelphiとLazarusでのドロップファイル処理の違い »