Taking Pictures using your Webcam in Delphi

Soon Sam Santos
8 min readJan 3, 2019
Webcam Form in Delphi

In this lesson I am going to teach you how to capture photos from your webcam in Delphi. It took me a while to figure it out how to do it when I was doing my Delphi App, that’s why I want to make this a detailed tutorial.

We are going to build a simple application where you have two buttons, when you click in the first one you are redirected to the WebCam Form (This is the form from photo above) where you can take the picture. In the second button, you’ll be able to save your photo automatically to a specific folder in your application.

We are going to follow many steps, but it’ll be worth in the end. I am using Delphi 10.3 Community Edition.

Step 1. Create your project

Create a new project in delphi.

Step 2. Add your components

Name your first form and unit of frmMain/uMain.

Create a second Unit (File → New → VCL Form —Delphi) and name it frmWebCam/uWebCam.

In your frmMain add the following components.

NOTE: Use the same names as mine to make it easier to follow the tutorial.

  1. TImage (name: imgProfile)
  2. TButton (name: btnTakePhoto)
  3. TButton (name: btnSave)

Select your TImage and in the Object Inspector set its width to 150, height to 98 and set Proportional to True.

It is important to have Proportional set to True, otherwise, the image will not adjust its size in the TImage size.

I set this specific width and height because this is the number that fits my webcam, if it is not good in your case, you can take some pictures using your webcam latter and then adjust the size manually.

Your first form will be like the one in the picture bellow.

Can’t see TImage in the top, because it has no image yet. It’s ugly but it’ll work haha!

In your frmWebCam add the following components.

  1. TPanel (name: pnlLeft)
  2. TPanel (name: pnlRight)
  3. TPaintBox (name: pbCamera)
  4. TButton (name: btnTake)
  5. TImage (name: imgSnapshot)
  6. TButton (name: btnSave)

Now, I’ll just teach you how I adjusted the size and position of these components but you can do it in the way you prefer. If you don’t care about the layout right now, place your components wherever you want (make them understandable at least) and jump to Step 3.

In the Object Inspector set:

pnlRight Align property → alRight

pnlLeft Align property → alClient

Adjust the size of pnlRight manually to fit half size of the form.

pnlLeft → Place btnTake and pbCamera inside it.

pnlRight → Place btnSave and imgSnapshot inside it.

btnTake and btnSave Align property → alBottom

pbCamera and imgSnapshot → alClient

Form → Width: 512 Height: 220

This will make your form to be like the one in the picture bellow.

WebCam Form

Step 3. Download and paste external files

To turn on your webcam and take some beautiful pictures of you, it will be necessary to download an external library to help shrinking your work. Download DirectX Delphi Webcam files. In the bottom of this website you will see the rar file: DirectXDelphiWebcamCapture.rar, and you also see a Demo file, this has some demonstrations on how to use these files.

If you are not sure about the authenticty of these library you can do a bit of so to make your self more confident about DirectX, I found out these answers on SO: How to get a snapshot from a webcam with Delphi7, Taking a picture from a webcam using WinAPI in Delphi 7, Delphi Webcam Simple Program.

Pick the downloaded files and paste them inside your application debug folder.

Win32/Webcamfiles/{downloaded_files}
Your DirectX files inside YourApp/Win32/Webcamfiles

SIMPLE NOTE: If there is no Win32 folder inside your app, this is because you didn’t run it yet. Run it once, or twice and it will appear. If it still doesn’t appear you need to close your project (Save it) and re-open.

Step 4. Import external files and organize forms creation

Now you need to import these downloaded files inside your application. Go to Project → View Source to open your project code and paste these code inside it. Also delete frmWebcam from being automatically created, because we want to create it only when we click in the button in frmMain.

uses
Vcl.Forms,
uMain in 'uMain.pas' {frmMain},
uWebCam in 'uWebCam.pas' {frmWebCam},
VFrames in 'Win32\WebcamFiles\VFrames.pas',
VSample in 'Win32\WebcamFiles\VSample.pas',
Direct3D9 in 'Win32\WebcamFiles\DirectX\Direct3D9.pas',
DirectDraw in 'Win32\WebcamFiles\DirectX\DirectDraw.pas',
DirectShow9 in 'Win32\WebcamFiles\DirectX\DirectShow9.pas',
DirectSound in 'Win32\WebcamFiles\DirectX\DirectSound.pas',
DXTypes in 'Win32\WebcamFiles\DirectX\DXTypes.pas';
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.

Delete the line that was after CreateForm(TfrmMain, frmMain)

Application.CreateForm(TfrmWebCam, frmWebCam); // Delete this line

Step 5. Setup uWebCam

It is time to set up your uWebCam code to really take the pictures.

Import VSample and VFrames to your uses clauses (at the top of your file).

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, VSample, VFrames;

Create some private variables and methods

private
{ Private declarations }
FVideoImage: TVideoImage;
FVideoBitmap: TBitmap;
procedure OnNewVideoFrame(Sender: TObject; Width, Height: integer;
DataPtr: pointer);

Paste this code to your FormCreate and OnNewVideoFrame methods.

procedure TfrmWebCam.FormCreate(Sender: TObject);
var
DevicesList: TStringList;
begin
FVideoBitmap := TBitmap.Create;
DevicesList := TStringList.Create;
FVideoImage := TVideoImage.Create;
FVideoImage.OnNewVideoFrame := OnNewVideoFrame; Screen.Cursor := crHourGlass;
Application.ProcessMessages;
FVideoImage.GetListOfDevices(DevicesList);
FVideoImage.VideoStart(DevicesList.Strings[0]);
Screen.Cursor := crDefault;
end;
procedure TfrmWebCam.OnNewVideoFrame(Sender: TObject; Width, Height: integer;
DataPtr: pointer);
var
I, R : integer;
begin
// Retreive latest video image
FVideoImage.GetBitmap(FVideoBitmap);
// Paint image onto screen, either normally or flipped.
pbCamera.Canvas.Draw(0, 0, FVideoBitmap);
end;

In this code we first initialize three variables.

FVideoBitmap: This will be the bitmap of the image we will take.

DevicesList: This is going to be a list of available webcam devices your computer has. If you have only one webcam type this will store one value, if you have three webcam types it will store three.

FVideoImage: This is going to take care of the video when you are seeing yourself in your camera to prepare to take the picture, this will start and stop this video.

FVideoImage will retrieve the list of available devices and will play the video using the first device (index of 0). I did that because I have only one webcam in my notebook and I am using this first webcam to take the picture. You could make a ComboBox with the available devices and let the user choose it (You can check an example in the DirectX Demos).

Now, when your WebCam form is created it starts a video with your webcam in the left (pbCamera: TPaintBox) where you can see yourself on the camera. When you click in Take Picture button the current image will be displayed in the right where you can check your picture and save it.

Click twice in each of your buttons and add the following code:

procedure TfrmWebCam.btnSaveClick(Sender: TObject);
begin
Self.ModalResult := mrOk;
end;
procedure TfrmWebCam.btnTakeClick(Sender: TObject);
begin
imgSnapshot.Picture.Assign(FVideoBitmap);
end;

btnTakeClick method will assign the current image to the right (TImage) and the btnSaveClick method will close the form with a Ok ModalResult.

Finally, when we close frmWebCam we want to stop the webcam, otherwise it would keep turned on. Add this code to stop the camera when the form is closed.

procedure TfrmWebCam.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FVideoImage.VideoStop;
end;

Step 6. Setup uMain

Import uWebCam and jpeg file to your uMain uses clauses.

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, uWebCam, Vcl.Imaging.jpeg;

Click twice in your btnTakePhoto button (We added it in Step 2) and add the following code:

procedure TfrmMain.btnTakePhotoClick(Sender: TObject);
begin
frmWebCam := TfrmWebCam.Create(Application);
with frmWebCam do
begin
ShowModal;
if ModalResult = mrOk then
imgProfile.Picture.Assign(imgSnapshot.Picture);
end;
end;

This is going to open the WebCam form and when it returns mrOk code we assign the image inside imgSnapshot to imgProfile.

To recap the flow, when we click in frmMain/btnTakePhoto it will open frmWebCam, where you will take a picture. When you take the picture it will be displayed in frmWebCam/imgSnapshot and then you click in frmWebCam/btnSave. It will return mrOk code and close the frmWebCam.

Then your frmMain will catch the mrOk code and will assign to frmMain/imgProfile the Picture that is inside frmWebCam/imgSnapshot.

If it is a little confusing, don’t worry, when we are done and you run your project you will understand much better.

Now you are done with starting the camera and taking pictures, however, if you don’t want to stop right here we are going to save our picture in a folder automatically in the following steps.

Step 7. Save your photo into a folder

Click twice in your frmMain/btnSave button and add the following code.

procedure TfrmMain.btnSaveClick(Sender: TObject);
var
JImgProfile: TJPEGImage;
ProfilePhotoPath: string;
begin
// ====== Photos ======
// == Profile
if imgProfile.Picture.Graphic <> nil then
begin
JImgProfile := TJPEGImage.Create;
JImgProfile.Assign(TJPEGImage(imgProfile.Picture.Graphic));
JImgProfile.PixelFormat := jf24Bit;
JImgProfile.CompressionQuality := 100;
JImgProfile.ProgressiveDisplay := False;
JImgProfile.ProgressiveEncoding := False;
// Profile photos will be saved at:
// ..\debug\user\profile-photos\photo1
SetCurrentDir(ExtractFileDir(Application.ExeName));
if DirectoryExists('user') then
begin
SetCurrentDir('user');
if DirectoryExists('profile-photos') then
begin
SetCurrentDir('profile-photos');
JImgProfile.SaveToFile('photo1' + '.jpeg');
end
else
begin
if CreateDir('profile-photos') then
begin
SetCurrentDir('profile-photos');
JImgProfile.SaveToFile('photo1' + '.jpeg');
end
else
MessageDlg('Failed to create directory: ' + IntToStr(GetLastError) + '.', mtError, [mbOK], 0);
end;
end
else
begin
if CreateDir('user') then
begin
SetCurrentDir('user');
if CreateDir('profile-photos') then
begin
SetCurrentDir('profile-photos');
JImgProfile.SaveToFile('photo1' + '.jpeg');
end
else
MessageDlg('Failed to create directory: ' + IntToStr(GetLastError) +
'.', mtError, [mbOK], 0);
end
else
MessageDlg('Failed to create directory: ' + IntToStr(GetLastError) +
'.', mtError, [mbOK], 0);
end;
// Save profile photo path to save in the database
ProfilePhotoPath := 'user\profile-photos\photo1';
SetCurrentDir(ExtractFileDir(Application.ExeName));
end;
end;

We are going to save our picture with the name photo1.jpeg to the following folder

YourApp\Win32\debug\user\profile-photos\photo1.jpeg

First, we check if there is a picture assigned to imgProfile, if there is we assign it to a new TJPEGImage variable (JImgProfile) and setup its property.

Then with the following line we set our current directory to our application directory (YourApp/Win32/debug).

We check if there is a user folder inside it, at the first time there will be no folder. Then our code will go to else where we create a new user and profile- photos folder and save the image into it.

In the second time there will be already a user folder so we check if there is a profile-photos folder, if there isn’t (supposing user deleted it manually), we create this folder and save the picture, else we just save the picture.

NOTES

In our case we are saving the picture with the name of photo1.jpeg, so when we try to save the second photo we will endup with an error indicating that we already have a photo with this name. Of course, in a real application you would put a dynamically name to your photo, for example, photo + your user unique id.

--

--

Soon Sam Santos

Flutter and Delphi Developer at Green. Teacher at SoonClass