CommandCam

Image link to download CommandCam.exe from GithubCommandCam is a simple and easy to use command line webcam image grabber for Windows. It captures a single image from a webcam and stores it in a bitmap file. CommandCam is ideal for use in batch files and other situations where you want a very simple way to automate image capture. CommandCam uses Microsoft’s DirectShow API to access webcams, so it should work with most USB cameras.

CommandCam (the source code and the executable version) are published under the GNU General Public License (version 3).

Support CommandCam Development

Nobody ever clicks this

CommandCam is completely free to download and use, but if you find it incredibly useful and you’re a multi-millionaire, feel free to make a donation using the PayPal “Donate” button on the right. If you use CommandCam, but you don’t want to pay for it, don’t feel bad – almost nobody else pays either! (Donations to CommandCam occur just once in a very blue moon.) You can always support CommandCam development just by saying thanks.

Download CommandCam

CommandCam can be downloaded from my page on Github:

https://github.com/tedburke/CommandCam

The executable file, CommandCam.exe, can be downloaded directly using the following link:

CommandCam.exe (63KB, date: 21-4-2012)

The full CommandCam source code, which is contained in a single C++ file, is also available:

CommandCam.cpp (17KB, date: 21-4-2012)

Running CommandCam

To run CommandCam:

  1. Firstly, open a console window. From the Windows start menu, select Start -> Accessories -> Command Prompt.
  2. Make sure your webcam is plugged in.
  3. Move to the directory where you downloaded CommandCam.exe. For example, cd "My Documents\Downloads".
  4. Type CommandCam and press return.
  5. The captured image will be saved to the file image.bmp.

Here’s how that appears in the console window.

A screenshot of CommandCam being run in a console window

The above example captured the following image of my cup of tea to a file called "image.bmp" (the image was converted to PNG format prior to uploading).

An example image captured by CommandCam showing a mug of tea.

CommandCam Options

Several useful options can be specified using command line arguments.

To specify a time delay between the camera being turned on and the image being grabbed, use the "/delay" option to specify a time delay in milliseconds. For example, to add a 5 second delay,

CommandCam /delay 5000

The default output filename for the grabbed image is "image.bmp". To specify a different filename, use the "/filename" option. If the filename contains any spaces, enclose it in inverted commas. For example, to save the image as "face.bmp":

CommandCam /filename face.bmp

By default, the first available video capture device will be used. To specify a particular device (if you have more than one), use the "/devnum" option. For example, to open the second video capture device:

CommandCam /devnum 2

Alternatively, to specify a capture device by name, use the "/devname" option. If the device name contains any spaces, it should be enclosed in inverted commas. For example, to select a device called “USB Video Device”:

CommandCam /devname "USB Video Device"

To specify a capture device by serial number (for example if you wish to select between two cameras of the same model), use the "/devserial" option. For example, to select a device with the serial number “314159265”:

CommandCam /devserial 314159265

By default, CommandCam does not display any video on the screen before capturing the image. However, you can enable a video preview window using the "/preview" option.

CommandCam /preview

To list the available capture devices, for example to check which device number corresponds to which device, use the "/devlist" option.

CommandCam /devlist

To list the available capture devices with extra detail (currently just the DevicePath for each camera), use the "/devlistdetail" option.

CommandCam /devlistdetail

More than one command line option can be specified at once. For example, to capture an image from the second video capture device to a file called "output.bmp" after a 10 second delay, the following command would be used:

CommandCam /filename output.bmp /delay 10000 /devnum 2

To suppress the text normally printed to the console by CommandCam (welcome message and other information), use the "/quiet" option.

CommandCam /quiet

CommandCam error codes

If CommandCam exits due to an error, it returns one of the following error code values:

  1. “Error: no filename specified”
  2. “Error: invalid delay specified”
  3. “Error: invalid device number”
  4. “Error: invalid device name”
  5. “Error: invalid device serial number”
  6. “Unrecognised command line argument”
  7. “Could not initialise COM”
  8. “Could not create filter graph”
  9. “Could not create capture graph builder”
  10. “Could not attach capture graph builder to graph”
  11. “Could not create system device enumerator”
  12. “No video devices found”
  13. “No devices found”
  14. “Video capture device not found”
  15. “Error getting device name and DevicePath”
  16. “Could not create capture filter”
  17. “Could not add capture filter to graph”
  18. “Could not create Sample Grabber filter”
  19. “Could not get ISampleGrabber interface to sample grabber filter”
  20. “Could not enable sample buffering in the sample grabber”
  21. “Could not set media type in sample grabber”
  22. “Could not add Sample Grabber to filter graph”
  23. “Could not create Null Renderer filter”
  24. “Could not add Null Renderer to filter graph”
  25. “Could not render capture video stream”
  26. “Could not render preview video stream”
  27. “Could not get media control interface”
  28. “Could not run filter graph”
  29. “Could not get buffer size”
  30. “Could not allocate data buffer for image”
  31. “Could not get buffer data from sample grabber”
  32. “Could not get media type”
  33. “Error opening output file”
  34. “Wrong media type”

Compiling CommandCam

To compile CommandCam, you will probably require the Microsoft C++ compiler, called "cl.exe", which is included with Visual C++.  Personally, I compile the program from the command line (rather than through the Visual C++ IDE) using the following command:

cl CommandCam.cpp ole32.lib strmiids.lib oleaut32.lib

It should also be straightforward to compile it through the Visual C++ GUI, but it will probably be necessary to specify the following libraries in your project’s linker options:

ole32.lib, strmiids.lib, oleaut32.lib

Source code

The complete source code for CommandCam resides in a single file. Here it is in its entirety:

//
// CommandCam - A command line image grabber
// Copyright (C) 2012-2013 Ted Burke
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program (see the file "COPYING").
// If not, see <http://www.gnu.org/licenses/>.
//
// Website: http://batchloaf.wordpress.com
//
// To compile using the MSVC++ compiler:
//
//		cl CommandCam.cpp ole32.lib strmiids.lib oleaut32.lib
//
// Last modified 24-1-2013
//

// DirectShow header file
#include <dshow.h>

// This is a workaround for the missing header
// file qedit.h which seems to be absent from the
// Windows SDK versions 7.0 and 7.1.
// To use the items defined in this dll, the
// DexterLib namespace must be specified.
// The items in question are:
//
//		DexterLib::_AMMediaType
//		DexterLib::ISampleGrabber
//		DexterLib::IID_ISampleGrabber
//
#import "qedit.dll" raw_interfaces_only named_guids

// For some reason, these are not included in the
// DirectShow headers. However, they are exported
// by strmiids.lib, so I'm just declaring them
// here as extern.
EXTERN_C const CLSID CLSID_NullRenderer;
EXTERN_C const CLSID CLSID_SampleGrabber;

// DirectShow objects
HRESULT hr;
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;
IPropertyBag *pPropBag = NULL;
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
IBaseFilter *pCap = NULL;
IBaseFilter *pSampleGrabberFilter = NULL;
DexterLib::ISampleGrabber *pSampleGrabber = NULL;
IBaseFilter *pNullRenderer = NULL;
IMediaControl *pMediaControl = NULL;
char *pBuffer = NULL;

void exit_message(const char* error_message, int error)
{
	// Print an error message
	fprintf(stderr, error_message);
	fprintf(stderr, "\n");

	// Clean up DirectShow / COM stuff
	if (pBuffer != NULL) delete[] pBuffer;
	if (pMediaControl != NULL) pMediaControl->Release();
	if (pNullRenderer != NULL) pNullRenderer->Release();
	if (pSampleGrabber != NULL) pSampleGrabber->Release();
	if (pSampleGrabberFilter != NULL)
			pSampleGrabberFilter->Release();
	if (pCap != NULL) pCap->Release();
	if (pBuilder != NULL) pBuilder->Release();
	if (pGraph != NULL) pGraph->Release();
	if (pPropBag != NULL) pPropBag->Release();
	if (pMoniker != NULL) pMoniker->Release();
	if (pEnum != NULL) pEnum->Release();
	if (pDevEnum != NULL) pDevEnum->Release();
	CoUninitialize();

	// Exit the program
	exit(error);
}

int main(int argc, char **argv)
{
	// Capture settings
	int quiet = 0;
	int snapshot_delay = 2000;
	int show_preview_window = 0;
	int list_devices = 0;
	int list_devices_with_detail = 0;
	int device_number = 1;
	char device_name[255];
	char device_serial[255];
	char filename[255];

	// Other variables
	char char_buffer[100];

	// Default device name and output filename
	strcpy(device_name, "");
	strcpy(filename, "image.bmp");
	
	// First check if output messages should be suppressed
	int n;
	for (n=1 ; n < argc ; n++)
	{
		// Check next command line argument
		if (strcmp(argv[n], "/quiet") == 0)
		{
			// Enable preview window
			quiet = 1;
		}
	}
	
	// Information message
	if (!quiet)
	{
		fprintf(stdout, "\n");
		fprintf(stdout, "CommandCam  Copyright (C) 2012-2013 Ted Burke\n");
		fprintf(stdout, "This program comes with ABSOLUTELY NO WARRANTY;\n");
		fprintf(stdout, "This is free software, and you are welcome to\n");
		fprintf(stdout, "redistribute it under certain conditions;\n");
		fprintf(stdout, "See the GNU General Public License v3,\n");
		fprintf(stdout, "<http://www.gnu.org/licenses/gpl.txt>\n");
		fprintf(stdout, "\n");
		fprintf(stdout, "http://batchloaf.wordpress.com/CommandCam\n");
		fprintf(stdout, "This version 24-1-2013\n");
		fprintf(stdout, "\n");
	}
	
	// Parse command line arguments. Available options:
	//
	//		/delay DELAY_IN_MILLISECONDS
	//		/filename OUTPUT_FILENAME
	//		/devnum DEVICE_NUMBER
	//		/devname DEVICE_NAME
	//		/devserial DEVICE_SERIAL_NUMBER
	//		/preview
	//		/devlist
	//
	n = 1;
	while (n < argc)
	{
		// Process next command line argument
		if (strcmp(argv[n], "/quiet") == 0)
		{
			// This command line argument has already been
			// processed above, so just ignore it now.
		}
		else if (strcmp(argv[n], "/preview") == 0)
		{
			// Enable preview window
			show_preview_window = 1;
		}
		else if (strcmp(argv[n], "/devlist") == 0)
		{
			// Set flag to list devices rather than capture image
			list_devices = 1;
		}
		else if (strcmp(argv[n], "/devlistdetail") == 0)
		{
			// Set flag to list devices rather than capture image
			list_devices = 1;
			list_devices_with_detail = 1;
		}
		else if (strcmp(argv[n], "/filename") == 0)
		{
			// Set output filename to specified string
			if (++n < argc)
			{
				// Copy provided string into char buffer
				strcpy(char_buffer, argv[n]);

				// Trim inverted commas if present and copy
				// provided string into filename char array
				if (char_buffer[0] == '"')
				{
					strncat(filename, char_buffer, strlen(char_buffer)-2);
				}
				else
				{
					strcpy(filename, char_buffer);
				}
			}
			else exit_message("Error: no filename specified", 1);
		}
		else if (strcmp(argv[n], "/delay") == 0)
		{
			// Set snapshot delay to specified value
			if (++n < argc) snapshot_delay = atoi(argv[n]);
			else exit_message("Error: invalid delay specified", 2);

			if (snapshot_delay <= 0)
				exit_message("Error: invalid delay specified", 2);
		}
		else if (strcmp(argv[n], "/devnum") == 0)
		{
			// Set device number to specified value
			if (++n < argc) device_number = atoi(argv[n]);
			else exit_message("Error: invalid device number", 3);

			if (device_number <= 0)
				exit_message("Error: invalid device number", 3);
		}
		else if (strcmp(argv[n], "/devname") == 0)
		{
			// Set device number to specified value
			if (++n < argc)
			{
				// Copy device name into char buffer
				strcpy(char_buffer, argv[n]);

				// Trim inverted commas if present and copy
				// provided string into device_name
				if (char_buffer[0] == '"')
				{
					strncat(device_name, char_buffer, strlen(char_buffer)-2);
				}
				else
				{
					strcpy(device_name, char_buffer);
				}

				// Remember to choose by name rather than number
				device_number = 0;
			}
			else exit_message("Error: invalid device name", 4);
		}
		else if (strcmp(argv[n], "/devserial") == 0)
		{
			// Set device serial number to specified string
			if (++n < argc)
			{
				// Copy device name into char buffer
				strcpy(char_buffer, argv[n]);

				// Trim inverted commas if present and copy
				// provided string into device_serial
				if (char_buffer[0] == '"')
				{
					strncat(device_serial, char_buffer, strlen(char_buffer)-2);
				}
				else
				{
					strcpy(device_serial, char_buffer);
				}

				// Remember to choose by serial number rather than number
				device_number = 0;
			}
			else exit_message("Error: invalid device serial number", 5);
		}
		else
		{
			// Unknown command line argument
			fprintf(stderr, "Unrecognised option: %s\n", argv[n]);
			exit_message("", 6);
		}

		// Increment command line argument counter
		n++;
	}

	// Intialise COM
	hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
	if (hr != S_OK)
		exit_message("Could not initialise COM", 7);

	// Create filter graph
	hr = CoCreateInstance(CLSID_FilterGraph, NULL,
			CLSCTX_INPROC_SERVER, IID_IGraphBuilder,
			(void**)&pGraph);
	if (hr != S_OK)
		exit_message("Could not create filter graph", 8);

	// Create capture graph builder.
	hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
			CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
			(void **)&pBuilder);
	if (hr != S_OK)
		exit_message("Could not create capture graph builder", 9);

	// Attach capture graph builder to graph
	hr = pBuilder->SetFiltergraph(pGraph);
	if (hr != S_OK)
		exit_message("Could not attach capture graph builder to graph", 10);

	// Create system device enumerator
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
			CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
	if (hr != S_OK)
		exit_message("Could not create system device enumerator", 11);

	// Video input device enumerator
	hr = pDevEnum->CreateClassEnumerator(
					CLSID_VideoInputDeviceCategory, &pEnum, 0);
	if (hr != S_OK)
		exit_message("No video devices found", 12);

	// If the user has included the "/list" command line
	// argument, just list available devices, then exit.
	if (list_devices != 0)
	{
		if (!quiet) fprintf(stdout, "Available capture devices:\n");
		n = 0;
		while(1)
		{
			// Find next device
			hr = pEnum->Next(1, &pMoniker, NULL);
			if (hr == S_OK)
			{
				// Increment device counter
				n++;

				// Get device name
				hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
				VARIANT var;
				// Retrieve and print device name
				if (list_devices_with_detail)
					if (!quiet) fprintf(stdout, "Capture device %d:\n", n);
				VariantInit(&var);
				hr = pPropBag->Read(L"FriendlyName", &var, 0);
				if (!quiet) fprintf(stdout, "  Device name: %ls\n", var.bstrVal);
				VariantClear(&var);
				// Retrieve and print device path
				if (list_devices_with_detail)
				{
					VariantInit(&var);
					hr = pPropBag->Read(L"DevicePath", &var, 0);
					if (!quiet) fprintf(stdout, "  Device path: %ls\n\n", var.bstrVal);
					VariantClear(&var);
				}
			}
			else
			{
				// Finished listing device, so exit program
				if (n == 0) exit_message("No devices found", 13);
				else exit_message("", 0);
			}
		}
	}

	// Get moniker for specified video input device,
	// or for the first device if no device number
	// was specified.
	VARIANT var;
	n = 0;
	while(1)
	{
		// Access next device
		hr = pEnum->Next(1, &pMoniker, NULL);
		if (hr == S_OK)
		{
			n++; // increment device count
		}
		else
		{
			if (device_number == 0)
			{
				fprintf(stderr,
					"Video capture device %s not found\n",
					device_name);
			}
			else
			{
				fprintf(stderr,
					"Video capture device %d not found\n",
					device_number);
			}
			exit_message("", 14);
		}

		// If device was specified by name or serial number...
		if (device_number == 0)
		{
			// Get video input device name
			hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
			if (hr == S_OK)
			{
				// Get current device name
				VariantInit(&var);
				hr = pPropBag->Read(L"FriendlyName", &var, 0);

				// Convert to a normal C string, i.e. char*
				sprintf(char_buffer, "%ls", var.bstrVal);
				VariantClear(&var);

				// Exit loop if current device name matched devname
				if (strcmp(device_name, char_buffer) == 0) break;

				// Get current device path
				VariantInit(&var);
				hr = pPropBag->Read(L"DevicePath", &var, 0);

				// Convert to a normal C string, i.e. char*
				sprintf(char_buffer, "%ls", var.bstrVal);
				VariantClear(&var);
				
				pPropBag->Release();
				pPropBag = NULL;

				// Exit loop if specified serial number appears in DevicePath
				if (strlen(device_serial) && strstr(char_buffer, device_serial)) break;
			}
			else
			{
				exit_message("Error getting device name and DevicePath", 15);
			}
		}
		else if (n >= device_number) break;
	}

	// Get video input device name
	hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
	VariantInit(&var);
	hr = pPropBag->Read(L"FriendlyName", &var, 0);
	if (!quiet) fprintf(stdout, "Capture device: %ls\n", var.bstrVal);
	VariantClear(&var);

	// Create capture filter and add to graph
	hr = pMoniker->BindToObject(0, 0,
					IID_IBaseFilter, (void**)&pCap);
	if (hr != S_OK) exit_message("Could not create capture filter", 16);

	// Add capture filter to graph
	hr = pGraph->AddFilter(pCap, L"Capture Filter");
	if (hr != S_OK) exit_message("Could not add capture filter to graph", 17);

	// Create sample grabber filter
	hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
		CLSCTX_INPROC_SERVER, IID_IBaseFilter,
		(void**)&pSampleGrabberFilter);
	if (hr != S_OK)
		exit_message("Could not create Sample Grabber filter", 18);

	// Query the ISampleGrabber interface of the sample grabber filter
	hr = pSampleGrabberFilter->QueryInterface(
			DexterLib::IID_ISampleGrabber, (void**)&pSampleGrabber);
	if (hr != S_OK)
		exit_message("Could not get ISampleGrabber interface to sample grabber filter", 19);

	// Enable sample buffering in the sample grabber filter
	hr = pSampleGrabber->SetBufferSamples(TRUE);
	if (hr != S_OK)
		exit_message("Could not enable sample buffering in the sample grabber", 20);

	// Set media type in sample grabber filter
	AM_MEDIA_TYPE mt;
	ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
	mt.majortype = MEDIATYPE_Video;
	mt.subtype = MEDIASUBTYPE_RGB24;
	hr = pSampleGrabber->SetMediaType((DexterLib::_AMMediaType *)&mt);
	if (hr != S_OK)
		exit_message("Could not set media type in sample grabber", 21);

	// Add sample grabber filter to filter graph
	hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
	if (hr != S_OK)
		exit_message("Could not add Sample Grabber to filter graph", 22);

	// Create Null Renderer filter
	hr = CoCreateInstance(CLSID_NullRenderer, NULL,
		CLSCTX_INPROC_SERVER, IID_IBaseFilter,
		(void**)&pNullRenderer);
	if (hr != S_OK)
		exit_message("Could not create Null Renderer filter", 23);

	// Add Null Renderer filter to filter graph
	hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
	if (hr != S_OK)
		exit_message("Could not add Null Renderer to filter graph", 24);

	// Connect up the filter graph's capture stream
	hr = pBuilder->RenderStream(
		&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
		pCap,  pSampleGrabberFilter, pNullRenderer);
	if (hr != S_OK)
		exit_message("Could not render capture video stream", 25);

	// Connect up the filter graph's preview stream
	if (show_preview_window > 0)
	{
		hr = pBuilder->RenderStream(
				&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
				pCap, NULL, NULL);
		if (hr != S_OK && hr != VFW_S_NOPREVIEWPIN)
			exit_message("Could not render preview video stream", 26);
	}

	// Get media control interfaces to graph builder object
	hr = pGraph->QueryInterface(IID_IMediaControl,
					(void**)&pMediaControl);
	if (hr != S_OK) exit_message("Could not get media control interface", 27);

	// Run graph
	while(1)
	{
		hr = pMediaControl->Run();

		// Hopefully, the return value was S_OK or S_FALSE
		if (hr == S_OK) break; // graph is now running
		if (hr == S_FALSE) continue; // graph still preparing to run

		// If the Run function returned something else,
		// there must be a problem
		fprintf(stderr, "Error: %u\n", hr);
		exit_message("Could not run filter graph", 28);
	}

	// Wait for specified time delay (if any)
	Sleep(snapshot_delay);

	// Grab a sample
	// First, find the required buffer size
	long buffer_size = 0;
	while(1)
	{
		// Passing in a NULL pointer signals that we're just checking
		// the required buffer size; not looking for actual data yet.
		hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, NULL);

		// Keep trying until buffer_size is set to non-zero value.
		if (hr == S_OK && buffer_size != 0) break;

		// If the return value isn't S_OK or VFW_E_WRONG_STATE
		// then something has gone wrong. VFW_E_WRONG_STATE just
		// means that the filter graph is still starting up and
		// no data has arrived yet in the sample grabber filter.
		if (hr != S_OK && hr != VFW_E_WRONG_STATE)
			exit_message("Could not get buffer size", 29);
	}

	// Stop the graph
	pMediaControl->Stop();

	// Allocate buffer for image
	pBuffer = new char[buffer_size];
	if (!pBuffer)
		exit_message("Could not allocate data buffer for image", 30);

	// Retrieve image data from sample grabber buffer
	hr = pSampleGrabber->GetCurrentBuffer(
			&buffer_size, (long*)pBuffer);
	if (hr != S_OK)
		exit_message("Could not get buffer data from sample grabber", 31);

	// Get the media type from the sample grabber filter
	hr = pSampleGrabber->GetConnectedMediaType(
			(DexterLib::_AMMediaType *)&mt);
	if (hr != S_OK) exit_message("Could not get media type", 32);

	// Retrieve format information
	VIDEOINFOHEADER *pVih = NULL;
	if ((mt.formattype == FORMAT_VideoInfo) &&
		(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
		(mt.pbFormat != NULL))
	{
		// Get video info header structure from media type
		pVih = (VIDEOINFOHEADER*)mt.pbFormat;

		// Print the resolution of the captured image
		if (!quiet) fprintf(stdout, "Capture resolution: %dx%d\n",
			pVih->bmiHeader.biWidth,
			pVih->bmiHeader.biHeight);

		// Create bitmap structure
		long cbBitmapInfoSize = mt.cbFormat - SIZE_PREHEADER;
		BITMAPFILEHEADER bfh;
		ZeroMemory(&bfh, sizeof(bfh));
		bfh.bfType = 'MB'; // Little-endian for "BM".
		bfh.bfSize = sizeof(bfh) + buffer_size + cbBitmapInfoSize;
		bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + cbBitmapInfoSize;

		// Open output file
		HANDLE hf = CreateFile(filename, GENERIC_WRITE,
					FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
		if (hf == INVALID_HANDLE_VALUE)
			exit_message("Error opening output file", 33);

		// Write the file header.
		DWORD dwWritten = 0;
		WriteFile(hf, &bfh, sizeof(bfh), &dwWritten, NULL);
		WriteFile(hf, HEADER(pVih),
					cbBitmapInfoSize, &dwWritten, NULL);

		// Write pixel data to file
		WriteFile(hf, pBuffer, buffer_size, &dwWritten, NULL);
		CloseHandle(hf);
	}
	else
	{
		exit_message("Wrong media type", 34);
	}

	// Free the format block
	if (mt.cbFormat != 0)
	{
		CoTaskMemFree((PVOID)mt.pbFormat);
		mt.cbFormat = 0;
		mt.pbFormat = NULL;
	}
	if (mt.pUnk != NULL)
	{
		// pUnk should not be used.
		mt.pUnk->Release();
		mt.pUnk = NULL;
	}

	// Clean up and exit
	if (!quiet) fprintf(stdout, "Captured image to %s", filename);
	exit_message("", 0);
}

242 Responses to CommandCam

  1. Stephen says:

    Ted,
    Thanks for the response to my original reply and your suggestions. Thanks also for the updated code. I didn’t realise that you had posted a reply as the notification of followup comments must have had a problem so I apologise for not replying till now.

    I don’t know if the delay would have been necessary before or not. Certainly with the latest code it is unnecessary for me as I can simply run commandcam with no parameters at all and it works perfectly!

    Thanks very much – this is much simpler than using vlc to do a still image capture as I was doing previously.

    Stephen

  2. batchloaf says:

    Hi Stephen,
    Thanks for getting back to me. I’m delighted to hear the updated code is working well for you. Actually, your original feedback prompted me to clean up several bits and pieces in the program, which has produced a much more satisfactory version, so thanks for that.
    Ted

  3. Bill says:

    Interesting product.

    May I ask: I would like to automate testing, is there a way to start and stop (and filesave) a video from the webcam? (not just an image)

    • batchloaf says:

      Hi Bill,
      Unfortunately, CommandCam does not record videos. However, I have been considering writing a little program to do just what you describe (it’s certainly possible to do it and I can probably reuse some of the CommandCam code). I might get a chance to start writing it over the weekend. If you can describe a little more about the way you would be using it (how many videos, recording how often, how many cameras, etc) I can try to keep that in mind when I look at it.
      Regards,
      Ted

  4. sheldon says:

    hello, thanks for your new version of snapz. it works now. the only thing i wish i could influence would be the size of the captured image. my cam can go up to 1920×1080. an additional switch to choose some image sizes would be perfect.
    happy xmas,
    sheldon.

    • batchloaf says:

      Hi Sheldon,
      I was originally hoping to include this feature (image resolution selection), but it turned out to be quite tricky to make CommandCam do it due to the way it interacts with DirectShow (the underlying video API provided by Microsoft). However, I have since written another little program called RobotEyez which has similar functionality to CommandCam, but interacts with DirectShow in a way that makes it slightly easier to specify the image resolution. Perhaps I could compile you a version of RobotEyez that selects the specific resolution you want to use? Would that help if I could provide a version that does one specific resolution of your choice, or are you just interested in being able to control the resolution in general (e.g. 1920×1080)?
      Ted

  5. Robert Barr says:

    Great little tool! The only thing that would make it better is incrementing file names. I have it running in a batch file triggered by a motion detector. The motion detector is rather quick, so the pic gets written over before I get to see it. I only get to see the last pic. Other than that GREAT TOOL!!!!!!

    • batchloaf says:

      Hi Robert,
      Thanks very much for the positive feedback – it’s much appreciated. I’ll keep your suggestion about incrementing filenames in mind and try to add that feature the next time I get to spend a bit of time on CommandCam. In the meantime, you should be able to create the same effect by “wrapping” CommandCam in a batchfile that checks what filenames are already present before running CommandCam with an available filename. I’ll have a bit of a think about it and try to post an example later.
      Regards,
      Ted

  6. Robert Barr says:

    Ted,
    Using the Set command I added a line that takes out the unwanted junk from the %date% and %time%. and added it to the batch file as %DNT% . then i use the /filename %DNT%. Now it works like a charm! Thanks!

  7. Rick says:

    This worked beautifully to silently capture an image of the kid that stole one of work computers. Instead of doing a remote screen takeover which would have alerted the user, capturing an image behind the scenes worked great. Excellent evidence and the computer was recovered by police!

  8. Paul says:

    Great program, would be awesome if you could add jpeg support in the future as well!

  9. Nils says:

    Good work!
    Would it be possible to wait in the preview mode until the user presses a button or clicks in the preview window.

    • batchloaf says:

      Hi Nils,
      Thanks for your comment. I’m not sure how straightforward it will be to add this feature, but I’ll add it to the list and see if it’s possible.
      Regards,
      Ted

  10. john leo says:

    Used this one in an hta + vbscript app. and it works great xcept I can’t get a preview before snapping up the picture. As for jpeg conversion, i used the irfanviewportable. it is kinda lighter-weight compared to imagemagick and can also be run thru commandline,

    • batchloaf says:

      Hi John,
      Thanks for your message. I’m glad to hear you found CommandCam useful. Regarding the preview window not working, you could try another of my programs called RobotEyez which has many similar features, but performs the preview and capture in a slightly different way behind the scenes. You might find that it works better for you. Here’s the link:

      http://batchloaf.wordpress.com/2011/11/27/ultra-simple-machine-vision-in-c-with-roboteyes/

      I’ll probably merge CommandCam and RobotEyez into one program in the near future, since I’m really just using RobotEyez to experiment with new features.

      Thanks,
      Ted

  11. stampzz says:

    there is web site sensr.net
    allows to post pictures from wifi web cameras
    but i have regular USB cam
    so using your CommandCam.exe i can emulate “wifi web cam”
    kind of “capture img, upload it to sensr.net”

    • batchloaf says:

      Great, I’m glad you found it useful! That website is funny – they seem to be all about keeping an eye on your pets over the internet. I never thought of that before.

  12. Jani says:

    Wow, this is exactly what I’ve been looking for. THANK YOU.

    I’m using Logitech Quickcam pro 9000 camera. I was wondering it’s it’s somehow possible to go beyond 640 x 480 resolution? It’s possible with their bundled software but I guess it can’t be done with command line?

    Does anyone know which web cam gives the highest resolution images natively with CommandCam?

    Thanks! :)

    • batchloaf says:

      Hi Jani,

      Thanks for your comment! You’re not the only one looking to use CommandCam at higher resolution and there’s no major technical problem to making the change to the code – I’ve just been flat out at work, so I haven’t had a chance to do it. Hopefully, I’ll add the feature very soon.

      By the way, is there a particular resolution you want to use it at?

      Regards,
      Ted

      • Jani says:

        Hi Ted

        Thanks for being so helpful! I just want as many pixels as possible. I’m working on a panorama project where I combine two webcam inputs into one panoramic one. Due to lens correction, cropping & other functions I perform on the images, I lose some pixels – and there’s nothing I can do about it. So, the more I have in the beginning the better. I was wondering if anyone knows what camera gives the highest resolution with CommandCam. If there’s no solution to go higher, that’s fine if I know what to buy to get more pixels. Many cameras claim 1920 x 1080 but I don’t want to spend the money if I get back 640 x 480 LOL! :)

        Thanks!

      • batchloaf says:

        Well, what I’m planning to do is add a command line option for requesting a specific width and height for the captured image and it will just depend on the camera (and its driver) whether that resolution is supported. Hopefully, that will solve your problem.

        By the way, one feature that another user requested is the ability to capture from multiple cameras simultaneously, so I’m going to have a go at supporting that. Perhaps that might be useful for your panorama idea too.

        Regards,
        Ted

  13. w3lshboy says:

    HI – great program. Just some input:

    I recently bought a logitech C270 web camera (<$20).

    Although it claims to be widescreen with 720p support I have done quite a few trials and the best/most detailed picture quality is when using it as 4:3 ratio at "3mp". This translates to 2048×1536.
    Interestingly:
    1) Choosing 640×480 results in a sharp picture but other supported resolutions between those two listed above are actually worse quality….
    2) Choosing widescreen modes results in a cropped image compared to a 4:3 pictures so the sensor is probably 4:3 nativley.

    So I would very much appreciate support for the above resolution (2048×1536) and I think it may be beneficial to owners of a lot of similar webcam models*

    * There appear to be a lot of similar logitech models with differing feature sets but the housing is very similar so there is a good chance the sensor is the same in all of them.

    I will be using command cam at home for a security system and also (potentially) at work from some remote monitoring of my experiments. I just made a little donation – thank you.

    • batchloaf says:

      Hi W3lshboy,

      Thanks so much for your comment. Sincere thanks also for donating – if only more people would ;-) I’ll do my best to add that feature to facilitate capture at the resolution you mentioned. Watch this space!

      Thanks again,
      Ted

      • w3lshboy says:

        I finally got around to trying to integrate the latest RobotEyez today with my C270 logitech web cam. The max resolution I seem to be able to get working for RobotEyez capture is 800×600. From the logitech app I can capture at 3MP and the windows properties for that JPEG is 2048×1536. I have also tried RobotEyez at 1024×768. Both (high) resolutions report “could not render video preview stream”. interestingly ffdshow pops up a dialog when i try to capture but both “use ffdshow” and “do not use ffdshow” result in failure. I also tried a 4000ms pause for the higher res grabs. (PC: Windows 7 64bit.)

      • w3lshboy says:

        Aside: Perhaps this API (“IAMStreamConfig::GetStreamCaps”) could be integrated into RobotEyez to assist with this issue and debug.
        It would be good to know what video resolutions are available on a per webcam basis:

        http://msdn.microsoft.com/en-us/library/ms787898(v=vs.85).aspx

    • batchloaf says:

      Hello again W3lshboy,

      Thanks for the update. Here’s my (so far unspectacular) update:

      I’ve been trying a different approach for capturing higher resolution still images from USB cameras such as yours, using the Windows Image Acquisition (WIA) API. I’ve made some progress, but I haven’t yet managed to actually grab an image to a file (or at all – I’m not quite sure yet). I’ll post my current code in a new blog post in a minute so that you can take a look if you’re interested. Hopefully, I’ll get this working soon and it will provide a better way to capture still images at the maximum resolution supported by each camera.

      Ted

  14. Hi batchloaf
    I was wondering where would i find the libraries for this project.

    • batchloaf says:

      Which libraries do you need? I have Microsoft Visual C++ 2010 Express installed. Assuming it’s still available, it’s a free download. If you’re getting an error when you try to run it, perhaps you could post the exact error here?

      • I was talking about these .lib files:
        ole32.lib, strmiids.lib, oleaut32.lib

        Below are the linker errors that i am getting:
        1>—— Build started: Project: camera, Configuration: Debug Win32 ——
        1>Build started 2/23/2012 2:44:32 PM.
        1>InitializeBuildStatus:
        1> Touching “Debug\camera.unsuccessfulbuild”.
        1>ClCompile:
        1> All outputs are up-to-date.
        1> All outputs are up-to-date.
        1>ManifestResourceCompile:
        1> All outputs are up-to-date.
        1>camera.obj : error LNK2001: unresolved external symbol _FORMAT_VideoInfo
        1>camera.obj : error LNK2001: unresolved external symbol _IID_IMediaControl
        1>camera.obj : error LNK2001: unresolved external symbol _PIN_CATEGORY_PREVIEW
        1>camera.obj : error LNK2001: unresolved external symbol _PIN_CATEGORY_CAPTURE
        1>camera.obj : error LNK2001: unresolved external symbol _MEDIASUBTYPE_RGB24
        1>camera.obj : error LNK2001: unresolved external symbol _MEDIATYPE_Video
        1>camera.obj : error LNK2001: unresolved external symbol _CLSID_VideoInputDeviceCategory
        1>camera.obj : error LNK2001: unresolved external symbol _CLSID_SystemDeviceEnum
        1>camera.obj : error LNK2001: unresolved external symbol _CLSID_CaptureGraphBuilder2
        1>camera.obj : error LNK2001: unresolved external symbol _IID_ICaptureGraphBuilder2
        1>camera.obj : error LNK2001: unresolved external symbol _CLSID_FilterGraph
        1>C:\Users\drmaq\Dropbox\CAMERA\camera\Debug\camera.exe : fatal error LNK1120: 11 unresolved externals
        1>
        1>Build FAILED.
        1>
        1>Time Elapsed 00:00:03.68
        ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

      • batchloaf says:

        On my PC, strmiids.lib, ole32.lib and oleaut32.lib are all in the following location:

        C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib

        So, they’re part of the Windows SDK. As far as I recall, the Windows SDK is installed automatically with Visual C++ 2010 Express, but if not it can be downloaded from MSDN.

    • OK i have developed another problem
      it seem to build fine but when it executes it only displays this error:
      “Error opening output file”

      This is the output form the visual C++ debugger:
      ‘camera.exe': Loaded ‘C:\Users\drmaq\Dropbox\CAMERA\camera\Release\camera.exe’, Symbols loaded.

      etc etc

      • batchloaf says:

        Is it possible that you have a previous output file of the same name open in another program? For example, if you run CommandCam once and it produces an output image file which you open in an image viewer program, CommandCam won’t be able to create an output file of the same name as long as you have the first output file open. Could that be why you’re getting this error? Do you have an image file open in another window perhaps?

      • Nope i deleted the image.bmp file and move the exe file to a new folder and the i still get the output file error

  15. thanks I will look in to that

  16. but the exe i got from your site works perfectly

    • batchloaf says:

      Hmmm, I’m not sure what’s causing the problem. If your libraries are in the SysWOW64 folder, then I’m guessing you’re running Windows 7. I’m still using XP, so perhaps your exe has compiled somewhat differently to how mine did. Sorry I can’t suggest anything more helpful, but since I don’t have Windows 7 here, it probably isn’t possible for me to reproduce your problem and find a solution.

      Anyone else have any ideas?? If the exe you downloaded is working ok, my guess is that it must be a compile settings issue.

  17. Hi Ted,

    I have been searching for webcam image capturing app for my little project (for home server). Finally I found your app. which is simple and cool at the same time.

    I have written a little application which can start your app., wait for the image, and finally convert it to a jpg file. (Convert is necessary because of my slow upload speed.)

    The result is: http://92.249.157.109:1080/take.html

    If I had time I would merge the two codes (yours and mine and add some switches e.g. jpeg, png).
    Or I can send you my little program c++ (with gdi+) source if you want to use it.

    Thak you for your app.

    Best Regards,
    Nandi

  18. bem says:

    very good program, but I have one problem or one question. If I run skype video conference or run any other program which is using a webcam in such time when I try to run CommandCam.exe, I get error (Error: 2147943850, Could not run filter graph). So my question: it is possible to make a webcam shot while a webcam is active with other program sush as skype and etc.. ? sorry for my poor english language, I hope you understand what I want to ask.

    • batchloaf says:

      Hi Bem,
      I’m afraid CommandCam cannot open a camera that is already being used by another program because Windows will not allow it. If the camera picture is displaying in the Skype window, perhaps you can do a screenshot instead? Did you try pressing Alt + Prt Sc to see if the image can be captured from the screen? If it can, then there’s probably some way to trigger the same screen capture process from a command rather than a physical key press.

  19. bem says:

    Ok. other question. It is possible to turn off a webcam led light while a webcam is active ?

    • batchloaf says:

      It’s not possible with CommandCam. Individual camera drivers may provide some way of doing it, but I would imagine that most force the light to be turned on while the camera is active.

  20. Ken says:

    Mr. Burke, the Logitech C920 boasts 15MP resolution via some sort of post processing of the data gathered. Questions: 1. Does commandcam.exe support the C920? 2. Is it possible to integrate the post processing of the data into a hi-res 15MP BMP file in a batch mode first calling commandcam then the post processor? 3. Is it possible to integrate the post processing into the commandcam.exe?

  21. Ken says:

    Oh… one more question. Using your software what resolution could I expect without any post processing of the data from the C920?

    • batchloaf says:

      Hi Ken,
      Ok, I’ll do my best to answer your questions:

      1. CommandCam accesses the camera via the DirectShow API, so any camera with a DirectShow driver should work (that includes most USB cameras). I’m not sure about the C920 specifically, but CommandCam is free so all you have to do is give it a try!

      2. I’m afraid I don’t know anything about the post-processing for the C920. How is it done normally? If they provide a command line tool for doing it, then yes, you should be able to create a batch file that calls CommandCam first followed by the post-processor. However, if the post-processing is encapsulated within the camera driver and simply used when the camera is opened for high resolution capture, then CommandCam won’t currently let you control whether or not it’s used. CommandCam currently just uses each camera’s default resolution, so unless the camera defaults to high res, you’re out of luck. I am working on a re-write which will allow you to specify the resolution. You can check out an early version of this (called RobotEyez) here.

      3. I won’t be integrating any features into CommandCam that are specific to a particular camera model. If it’s integrated into the camera’s DirectShow driver, then it might be used during high res capture, but only if it happens automatically – I won’t be programming it specifically into CommandCam.

      4. The capture resolution just depends on the camera and th driver. As far as I remember, nothing in the code of the current release of CommandCam specifies the capture resolution, so the default resolution is simply used. On my camera, that’s 640×480, but I don’t know about other cameras. As I mentioned before, just give it a try with your camera and see what resolution it used.

  22. Michael Lefsky says:

    I’ve been looking for a simple program to capture webcam images and commandcam seems to be the best thing out there. We want to use commandcam to capture images of growing plants for a science education video, but would need to be able to bump the image resolution to 1920 x 1080 (i.e. HD quality). Do you have definite plans to add that functionality?

    • batchloaf says:

      Hi Michael,

      What a fascinating application! Since it’s for an educational cause, I couldn’t resist leaping into action and trying to add this feature. I’ve been slowly working on a rewrite of CommandCam, which for some reason I’m calling RobotEyez until it’s ready to replace the original. Anyway, it’s basically working and I’ve just added command line flags to set width and height. Please take a look at my blog post about RobotEyez. You can download the current RobotEyes executable from the link on that page.

      Basically, to do what you want, you’ll probably just run it as follows:

      RobotEyez /width 1920 /height 1080 /bmp

      With some cameras, it seems to help to leave a short delay for warming up before snapping the photo. For example, this will add a 5 second delay:

      RobotEyez /delay 5000 /width 1920 /height 1080 /bmp

      RobotEyez has a bunch of other command line flags that are documented (very briefly) on the blog post I linked to above.

      Ok, I hope that helps. Please let me know if it works for you or not. I haven’t been able to test it up to 1920×1080 since my camera doesn’t support that resolution, so I’d love to know if it works. Also, if you do manage to get any videos of the plants growing, I’d be interested to see them!

      Regards,
      Ted

  23. Ken says:

    Mr. Burke, my Logitech C920 arrived today. It really does provide ~15mp resolution. Unfortunately, the post processing or interleave processing of multiple samples happens within one GUI application. You must have the GUI panel up, and you must push the button on the GUI panel. The finest in “graphical computing”. I have tried both your sets of tools and everything available on the web. Best can do without Logitech’s software is 680×480.

  24. Eric Jaakkola says:

    I’m looking at scripting HDR-type images as the dynamic range of the camera itself if rather weak. Is there any way to specify either manual exposure values, or better yet, an exposure offset? (read in the measured exposure and adjust from there) – bracketed exposures.

    • batchloaf says:

      Hi Eric. CommandCam does not provide any way to set the parameters you mention. To be honest, I don’t even know whether it’s possible to configure those parameters via DirectShow (the Microsoft API that CommandCam uses to communicate with the camera). However, I doubt it would be straightforward to introduce this functionality into CommandCam, so I currently have no plans to attempt it. Also, since CommandCam opens the camera device for video capture (even though it’s just snapping a single frame), it’s probably not ideally placed to control this kind of thing. Sorry, that’s probably not much use to you.

  25. bem says:

    How to check with c++, if the webcam is active now or not ?

    • batchloaf says:

      Hi Bem. I’m not sure what the best way to do this it, but it may not be all that easy to check. My suggestion is to try opening the device (look at the CommandCam source code to see how) and see what happens. It’s possible that DirectShow provides some other way to check, but I’m afraid I don’t know for sure.

  26. Titus says:

    Hey, Batchloaf,
    Could I use your commandcam.exe in my software? Just the commandcam.exe would me named cc.exe. That would be realy great!!! Sorry for my bad language…

    • batchloaf says:

      Hi Titus. Thanks for your message. Can you give me some more details please? What is the software you’re writing and are you going to be selling it? Would I be credited in some way?

      • Titus says:

        Hellow, batchloaf. The software I am creating will be some kind of monitoring program. A legal keylogger maby… But I am realy looking forward to make some money from it… I can tell you nothing about krediting for now… Becouse I just started to create my program… I am not sure for the future and I can’t tell you about crediting for now… But if you give me your email I will keep you up to date with my program… Thankyou… What about the permission?

      • batchloaf says:

        Hi Titus. So, you’re writing some sort of keylogger that you hope to make money from, but you’re not planning to pay me or give me any credit. Hmmm. I hope you’ll understand why I might not be all that keen on giving you open-ended permission to use my software however you want under these circumstances ;-)

        I have been intending to explore the possibility of making CommandCam available under a GPL license (or similar), but I just haven’t had time to investigate it properly. If I do decide to do that, I suppose you’ll be able to bundle CommandCam with your software subject to the terms and conditions of that license.

  27. tulipseason says:

    Tool is useful. But you can mode when capture by webcame, don’t use flash .
    Capture do not flash in webcam.

    • batchloaf says:

      Do you mean that you want to take a picture from a camera that has a flash bulb attached? If so, it probably won’t be possible to control this from CommandCam because it opens the camera as a video capture device rather than for still capture.

  28. Tall_Paul says:

    A fantastic little utility. I intend to use it at our school when the new intake of students start in September.

    I needed something where I could take a photo and rename the file and your app makes it both quick and easy so thank you very much.

    • batchloaf says:

      Thanks Paul! I hope it works out for you. I actually originally wrote this to help with a project that one of my own students was working on. Since then I’ve used it quite a bit myself for simple machine vision exercises in a Robotics class that I teach. Let me know how you get on with it next term.

  29. Bill Warner says:

    I’m using your software with Alpha Five (database), and it works great! Thanks.

    OK, here’s a challenge – have you done anything like this for a signature pad? I’d be willing to pay for a solution for this problem. Please contact me at Compunique@charter.net.

    Bill

    • batchloaf says:

      Hi Bill. Do you mean the electronic tablets for capturing signatures in point of sale systems and the like? If so, I haven’t worked with these before, but I would assume that most hardware vendors already provide some sort of software to do this. I’m sure it can be done, but I’m not sure how transferable the solution would be from one brand of tablet to another.

  30. Dan Koch says:

    Nice tool! So much lighter than VLC for taking webcam snapshots. I have a couple of small feature requests:

    1. I found that I can control how long the preview window is present through the /delay option. Not sure if this was intended, but it’s useful for letting the user adjust focus, lighting, etc. Could the code be changed or an option added to leave the preview window up until the user closes it? While the window can stay up longer, the video stops beforehand, leaving an empty frame.

    2. After a successful image capture, the following text is returned:

    CommandCam Copyright (C) 2012 Ted Burke
    This program comes with ABSOLUTELY NO WARRANTY;
    This is free software, and you are welcome to
    redistribute it under certain conditions;
    See the GNU General Public License v3,

    http://batchloaf.wordpress.com

    This version 21-4-2012

    Capture device: HP Webcam
    Capture resolution: 640×480
    Captured image to snapshot.bmp

    Since I’ll be calling your program from within a Python script using the subprocess module, a nicer result would be nothing or 0 for successful completion and a 1 or error message if something goes wrong. So perhaps some additional options like /help, /version, /license, /verbose, etc. would accomplish the same thing?

    Thanks again for sharing this with the community!

    • batchloaf says:

      Hi Dan. Thanks for the suggestions. They seem like good ideas, so I’ll try to incorporate them when I next sit down to do a bit more work on CommandCam. Once the summer holidays finally arrive, I’ll hopefully get a chance to spend a day or two giving CommandCam a complete overhaul and incorporate these and other features.

      • Dan Koch says:

        Hi Ted,

        Just wondered if you had considered these suggestions from last June.

        Thanks!
        Dan

      • batchloaf says:

        Hi Dan,

        I’ve added a “/quiet” option which allows normal text output from CommandCam to be silenced. Error messages will still appear however.

        I’m not too sure what to do about leaving the preview window open. That’s a more significant change and I would need to be think the repercussions through carefully. Since I’m hoping to redo CommandCam when I can find the time (probably using the RobotEyez code rather than the current CommandCam code), I don’t think I’ll change this aspect of it right now.

        Ted

      • Dan Koch says:

        Sounds good!
        Dan

  31. Alejandro says:

    Is posible to save in jpg rather han bmp?

  32. batchloaf says:

    It is not currently possible to save directly to jpg in CommandCam. However, you can easily use ImageMagick‘s “convert” command to automatically change the bmp file into a jpg as soon as it’s saved. ImageMagick is free to download and provides an amazing set of command line tools for image conversion and modification (scaling, colour converting, adding text, etc). Once you’ve installed ImageMagick, all you need to do to convert CommandCam’s saved bmp file into jpg is something like this:

        CommandCam /filename photo.bmp
        convert photo.bmp photo.jpg
    
  33. Dan Koch says:

    I’m trying to capture the device list to a file using redirection:

    c:\apps\CommandCam.exe /devlist > c:\tmp\devices.txt

    The device list is printed to the console window but the file is empty. Any hints?

    • batchloaf says:

      Hi Dan,
      Yes, Ian (below) has hit the nail on the head. Because CommandCam prints the device list to stderr rather than stdout, you need to redirect the output slightly differently – using “2>” instead of “>”. Upon reflection, the device list should probably just print to stdout, so I may change that in the future. For the time being however, Ian’s suggestion should work fine. i.e. something like the following…

          CommandCam.exe /devlist 2> devlist.txt
      
      • Dan Koch says:

        Thank you both for the quick reply. With this bit of information, I was able to capture the list within my Python app for building a drop-down menu. For me, it would be cleaner to have normal outputs come to stdout and error messages to stderr along with exit codes like 0 and 1, but I can certainly live with the current behavior.

      • Dan Koch says:

        Hi Ted,

        Did this ever get cleaned up? Exit codes would be nice too.

        Thanks!
        Dan

      • batchloaf says:

        Hi Dan, I’ve just updated CommandCam so that all output text other than error messages goes to stdout, which can be redirected in the normal way if desired. Also, it now returns a unique error code for 34 separate errors that can cause it to exit (although I’m still testing this bit).

      • Dan Koch says:

        Thanks! I’ll watch for the next release.

        Dan

  34. Ian says:

    Dan, try c:\apps\CommandCam.exe /devlist 2> c:\tmp\devices.txt

  35. Sawyer says:

    Useful utility. Thanks for your efforts.
    I was able to switch on the preview window but is it possible that the image is not captured until the user accepts it.
    I tried this app. and is working fine with the integrated webcam on the system, will it work fine with plug and play devices i.e. usb cams?
    Is it possible to capture images from multiple devices on a single click?

    Looking forward to your reply.

    • batchloaf says:

      Hi Sawyer,

      Thanks for the feedback. To answer your questions:

      “is it possible that the image is not captured until the user accepts it?” It would be possible to do this, but I haven’t previously regarded it as a big priority since most people use CommandCam within some kind of automated system or script where there won’t be interaction with a user while it runs. There are already many other cam snapshot programs that let you take a snapshot with a mouse click on a GUI. The reason I wrote CommandCam was to facilitate taking a snapshot from a script for an automated system. I’d be interested to hear what you’re using it for – maybe you’re using it in a scenario i hadn’t thought of, in which case I might consider including it.

      “will it work fine with plug and play devices i.e. usb cams?” It should work with most plug-in USB webcams. That’s what I’m using myself. CommandCam uses the DirectShow API to access the cam, which is currently the standard way on Windows and the method supported by the vast majority of USB cams.

      “Is it possible to capture images from multiple devices on a single click?” You’re not the first user to ask about simultaneous capture from multiple devices. I conducted a preliminary investigation into doing this and I’m pretty sure it’s possible, but I haven’t found the time to do it yet. Once term ends (I’m a lecturer), I’m hoping to spend a couple of days rewriting CommandCam to incorporate many of the features that users have suggested. Hopefully, that will include simultaneous capture from multiple devices.

      I should point out that of course it is currently possible to capture from multiple cameras one at a time. Just add several CommandCam commands to a batch file and then run the batch file. There will be a short delay (one or two seconds?) between the images captured though, so they won’t be simultaneous. Here’s what the batch file might look like:

          CommandCam /devnum 1 /filename "cam1.bmp"
          CommandCam /devnum 2 /filename "cam2.bmp"
          CommandCam /devnum 3 /filename "cam3.bmp"
          CommandCam /devnum 4 /filename "cam4.bmp"
      

      Paste those lines into a plain text file (e.g. in Notepad), save it as something like “multicam.bat”. You’ll then be able to capture from multiple cameras (one at a time) by running “multicam.bat”.

      • Sawyer says:

        Hi Batchloaf
        Thanks for taking out time to reply.
        According to the initial requirement, which was exactly the same which this tool does now.
        Now the requirement is changed, user should be able to see the preview image from all the cams attached to the system on a single window split into number of cams attached and after that on a single click individual images from each cam should get stored at a particular location. The requirement for the preview of the image is because the camera might be adjusted before clicking the pic.
        If you know some other tool which can be used for this please let me know.

      • batchloaf says:

        Hi Sawyer,

        I haven’t ever used a program that does exactly what you describe, although I would imagine that such programs must exist. Perhaps you could look for a CCTV / security camera monitoring application?

        Anyway, I’ll keep your application in mind when I do the next phase of development on CommandCam. I can’t make any promises, since I’m just not sure how awkward it would be to preview multiple cameras that way. As a matter of interest, how many cameras are you planning on using?

        Regards,
        Ted

  36. Sawyer says:

    Hi Ted
    The cams will be placed at a security check post. One of the cam will focus on the registration number plate of the vehicle, one on the driver of the vehicle, so at least 2 cams will be used. The registration number plate of the vehicle might be positioned differently on different vehicles that is why the user should be able to adjust the cam before capturing the image.

  37. Dylan says:

    I’ve been looking for a program to take a webcam shot for ages, and I’ve finally stumbled across this little gem! This is fantastic. I know you’re probably overwhelmed with feature requests at this point, but I was wondering if you would be able to add a /silent switch? As it is, when the program is called, it gives an output in a command prompt window. What I’d like to use this program for is theft recovery for the school district that I’m working for and to have the program activated remotely via other programs we have on the computer. However, when the programs activate CommandCam as it is, it gives a prompt. If you could provide any feedback on the possibility of making a /silent switch, or how I might go about doing this, it would be very much appreciated! Thank you so much.

    • Josef says:

      Has there been any update to this? Something like that would be pretty useful for how I’d be using it.

      • batchloaf says:

        Hi Josef & Dylan.
        Sorry, no update on this yet. The teaching holidays have just started here in DIT, so I’m finally back on research mode for a couple of months. I’m therefore optimistic that I’ll be able to squeeze in a couple of days of concentrated CommandCam development some time over the next few weeks, at which point I’ll hopefully incorporate this and other requested new features.
        Ted

  38. 0x3ff3ct3d says:

    It works great in windows 7 64-Bit but i didn’t understand how it identified the web-cam ?? as there are many types of Web Cam ,
    I have Sony VAIO Laptop and when i run your CommandCam it successfully capture the image, i couldn’t understand how it identified what kind of webcam i am using ?

    I’d be glad if you can add few guidelines explaining the idea behind your program and how you start coding it ? anything that would help me understand the algorithm would be appericiated

    Thank you

    • batchloaf says:

      Hi 0x3ff3ct3d,

      Sorry, I forgot to reply to this when you first posted it. The basic structure of the part of the program that opens the webcam is based on the code provided by Microsoft in the DirectShow documentation on MSDN. To be honest, the way you open cameras in DirectShow seems very over-complicated to me (actually, I find that with all COM programming), but that’s just the way it is. I’m not even going to attempt to explain any of that stuff about device enumerators, monikers, property bags, etc. I just kind of felt my way through it by following the MSDN documentation.

      Here’s a link to the section of the MSDN documentation that I followed:

      http://msdn.microsoft.com/en-us/library/dd407331%28v=vs.85%29

      Best of luck making sense of it! (Not an easy task.)

      Ted

  39. 0x3ff3ct3d says:

    and does it possible to code it in VBScript ?

  40. Rejjy says:

    Hi

    I tried your program, on a Dell Inspiron N5050 with Integrated Webcam. Sadly it does not work, rather it is stuck and the line says
    Capture Device : Integrated Webcam.
    Nothing happens at this point and no image is saved.
    Please tell me what I’m doing wrong.

    Thanks.

    • Rejjy says:

      Sorry for the false information.
      The program now works, I believe it was a Dell Software Problem.
      It’s amazing really.
      I have now used it in AutohotKey (another language) to take a picture from the WebCam whenever somebody runs the laptop.
      Also, I use AHK to lock the system and then CommandCam is used to take a photo of anyone who types the wrong password.

      I thank you for your work.

  41. m says:

    I don’t suppose you have had the time to force the console window to not appear?

  42. Absolutely Fantastic! Nice work!!!

  43. Josh says:

    Ive been searching for something like this for days! Thank you so so so much

    • batchloaf says:

      Thanks Josh! I originally wrote it because one of my students needed a program like this for his final-year project (he was taking snapshots of pigs in pens to track their weight – long story). I was absolutely amazed that we couldn’t find an existing program that did this in Windows. Anyway, I’m delighted to hear that you’re finding it useful – best of luck with whatever you’re creating.

  44. John says:

    Thank you so much. I have been looking for a simple lightweight webcam capture program for a long time. Most programs just won’t work with my webcam and the few that work are resource hogs.

  45. Guido says:

    Thank you batchloaf, great program !
    Is it possible to include another option maybe a “snapshot button” to snap during preview instead of a delay ? maybe as an option ?

    442 // Wait for specified time delay (if any)
    443 Sleep(snapshot_delay);

    Guido

  46. Alessandro says:

    Hi, very useful program!
    Can you please add a function int getColor(int x, int y) that returns the RGB for the selected pixel?

    Thanks :)

    • batchloaf says:

      Hi Alessandro,

      Do you mean add the C function to the program? If so, how does the function get called? Where does the pixel value go? Or do you mean that someone could run CommandCam at the command line and instead of getting an image file, three numbers (R, G and B for the specified pixel) just get printed?

      • Alessandro says:

        Yes I mean add the C function to the program, i will compile your program as a library, i.e. under windows i’ll compile it as a DLL to be used with another program i’m developing :)

      • Alessandro says:

        I think that this is not gonna be considered, am i wrong?

      • batchloaf says:

        Hi Alessandro,
        I still don’t completely understand what you want to do. If you just want to check the colour of one pixel, I’m not sure that adapting the CommandCam code is going to be the ideal way to do it – it would probably be quite a slow way to get the colour of a single pixel. However, if you’re really determined to try it, the first place I would look is around line 520 of the code listed above, just after the line “CloseHandle(hf)”. At that point in the program, the captured image has just been written to a file and the raw pixel data is still stored in the array pBuffer. To print the RGB colour of pixel (x,y) at that point in the program would be quite straightforward – you could just add something like the following lines of code (I’m using the centre pixel of a 640×480 image as an example):

        // Declare variables and specify pixel coordinates
        int w = pVih->bmiHeader.biWidth;
        int h = pVih->bmiHeader.biHeight;
        int x = 320, y = 240;
        int r, g, b;
        
        // Get RGB components of pixel (x,y)
        b = pBuffer[y*w*3 + x*3];
        g = pBuffer[y*w*3 + x*3 + 1];
        r = pBuffer[y*w*3 + x*3 + 1];
        
        // Print pixel colour value to console
        printf("RGB value of pixel(%d,%d) is (%d,%d,%d)\n", r, g, b);
        

        If you’re compiling the CommandCam code as a DLL instead of an application, I suppose the function you’re talking about will just be the main function (renamed of course). The code above just prints the pixel value in the console, but if you want to return it from your function, you’ll have to work out some way of doing that.

      • Alessandro says:

        Ok thank you, just another question, is there a way to get directly the HSB values instead of RGB, without converting?

      • batchloaf says:

        On lines 383-384, I specify the colour format as 24-bit RGB (one byte per colour component) when setting the media sub type for the SampleGrabber:

        mt.subtype = MEDIASUBTYPE_RGB24;
        

        You could look up MSDN to see whether a HSB sub type could be specified here instead. It’s possible that there is also a sub type for HSB. If there is and if it’s a 24-bit format, you might be in luck. DirectShow tries to deliver the colour format you request (inserting converter filters if required and available), but if you’re looking for an unusual format, I’m not sure how reliable it would be using different cameras – you might find that it worked with some but not with others. RGB24 has the advantage of being pretty standard, so that even if it’s not the format that the camera driver outputs, it should always be possible to convert to that.

        Since you’re only getting one pixel, surely it’s not that big a deal to just do the conversion manually though? It might be easier than messing around with the DirectShow colour format.

      • batchloaf says:

        Actually, I’ve just had a quick dig around on MSDN myself and I don’t see any HSB or HSV colour format there. There are plenty of RGB (and similar formats) and a selection of YUV formats – would they be of any use to you? The Y component of YUV is probably very similar (or identical) to the B component of HSB, but the colour components are different to hue and saturation.

        You can see the list of supported formats here:

        http://msdn.microsoft.com/en-us/library/windows/desktop/dd407353%28v=vs.85%29.aspx

        The two most relevant sections are “Uncompressed RGB Video Subtypes” and “YUV Video Subtypes”.

  47. percy Kumah says:

    Hi, I’m using the commnad.exe file to capture images off my HP webcap for my access app. When I run the commnad.exe on its own it captures and stores the image in the same folder as the commnad.exe file. But when I shell it from access, it doesnt. I can see the webcam light flicker but it does not seem to capture. Any help?

  48. batchloaf says:

    Hmmm, I’m not sure. When you say that you’re shelling it from access, do you mean that you’re running it from some kind of Visual Basic macro in MS Access, the database application? I don’t have Access installed on my PC, but I can try launching CommandCam from Excel to see if that works. The only thing that springs to mind that might prevent it from working correctly is that maybe the working directory is set to a location that CommandCam isn’t allowed to write to. Could that be the problem?

  49. percy Kumah says:

    Thanks for the quick reply. I’m shelling in VBA. Below is my code:

    Dim img
    img = Shell(Application.CurrentProject.Path & “\CommandCam.exe”, vbMaximizedFocus)

    When I run it on its own, the image is saved in the same location as the CommandCam.exe. My app is also located in the same folder so I expected the same behavior when I shell CommandCam. I saw other documentation on how to set certain parameters such as delay, folder location etc but I have not figured out how to do that. Maybe if I can change the save location or even preview the image then I might have the chance to save it where I want.

    Thanks again for your help.

  50. batchloaf says:

    Hi Percy.

    Where do you want to save the image? Do you want to save it in the same directory as your VBA application? If so, I think it’s ok to just put CommandCam.exe in the same folder and make sure the working directory is set to that location before you use shell to run it.

    The way you’ve written your shell command, it looks as though you’re trying to store the captured image into the img object, but if that’s what you’re trying to do, it won’t work that way. CommandCam just saves the image as a file – it doesn’t “return” an object that you can assign to a variable/object this way. Instead, you should just run the shell command, then use another line or two of VB to load the image from the file and store it in your img object. I’m sure there’s a function called LoadImage or something like that in VB which will do this for you – I’m just guessing though, because it’s been a while since I wrote any VB.

    Ted

  51. percy Kumah says:

    “make sure the working directory is set to that location before you use shell to run it.” How do I do this?

  52. percy Kumah says:

    Hi Ted,
    I’m either extremly stupid or there is something wrong with my computer. Below is the code I have, I slight modification to what you gave me:

    Private Sub Command0_Click()
    On Error Resume Next

    Dim RetVal
    Dim img, CommandCam As String

    img = Application.CurrentProject.Path & “\image.bmp”
    CommandCam = Application.CurrentProject.Path & “\CommandCam.exe”

    ‘If the image file already exits, delete it
    Kill (img)

    ‘check to be sure it really is deleted
    While Dir(img) > “”
    Wend

    ‘take a new picture
    RetVal = Shell(CommandCam, vbNormalFocus)

    End Sub

    At this point, I just want to go past taking the image, then I can load it into my application which is the easy part. But nothing appears. The camera light flickers as usual but there is no image. When go back to the app folder and double click CommandCam it runs and takes the picture and saves it as image.bmp. So I really dont get why it does not work when shelled, which is basically the same as double clicking the executable from the app folder. Sorry to be a bother but this is the most frustrating 2 days I ever had becuase from all thr help you’ve given, it should work but it simply doesnt! Am still missing something?

    Percy.

    • batchloaf says:

      Hi Percy,

      I’m sorry to hear you’re having such a frustrating time with this. I doubt that your computer’s broken and I’m sure you’re not stupid! My instinct tells me that your problem is something to do with VBA accessing the wrong directory (or directories).

      Firstly, some suggestions:

      • Remove “On Error Resume Next” – if an error is occurring, it would be better to stop and debug so that you know what went wrong.
      • Most importantly, try inserting this line at the start of your subroutine to ensure that the current directory is definitely set as the one you’re trying to save the file in: “ChDir(Application.CurrentProject.Path)”.
      • Of course, that assumes that the string “Application.CurrentProject.Path” is what you think it is. To make sure, try inserting the following line somewhere in your subroutine “MsgBox(Application.CurrentProject.Path)”.

      If that doesn’t solve the problem, then I have a couple more questions:

      1. When your shell command runs CommandCam, does the console window appear and stay visible? When mine runs, the console appears and stays open for several seconds while the photo is being taken.
      2. Have you tried including lines like “MsgBox(img)” and “MsgBox(CommandCam)” to double check that the path and filename are what you think they are?
      3. Have you done a file search for “image.bmp” on your computer to see if a file with that name is appearing somewhere other than the in the directory where you’re expecting it to be?

      Ted

  53. percy Kumah says:

    Ted, you are a genius!! And thanks a million for the patience. After trying so many little tweaks and adding a number of references and removing some later, it works now! I couldnt belive it, the first time it worked cos I really dont know what I did but its working perfectly now.
    Thanks again.

  54. Fernando says:

    Hello!

    First I have to congratulate you for this application. It really works fine. :)

    Second: I have a problem and it would be awesome if you can help me solve it :P I don’t know why, but the image that comes from my webcam is a little bit darker. I guess if I can turn on the night mode before I take the snap I could solve the problem.
    So the problem now is to turn on the night mode. I was researching on msdn website and I found this topic (http://msdn.microsoft.com/en-us/library/windows/desktop/dd387908(v=vs.85).aspx) with some functions that can change the brightness, contrast and other settings, but I can’t find anyone that can turn on the night mode.

    Do you now how to do that or something else that can solve my problem? That would be a very big help.

    Tanks :)

    • batchloaf says:

      Hi Fernando,
      Thanks for your message. Have you tried adding in a short delay before CommandCam takes the photo. For example, to include a 5 second delay before taking the snapshot,

      CommandCam /delay 5000
      

      Sometimes, a delay like this can allow the camera to “warm up” and you get a clearer picture.

      Unfortunately, I don’t know what “night mode” is exactly (although I can imagine what it does of course) – there’s no setting like that on my webcam. Many camera drivers provide a custom control panel that lets you adjust settings specific to that camera – these camera-specific control panels can usually be accessed through the Cameras section of the Windows Control Panel; just find where your camera is listed and right-click on it. Some of these control panels allow you to configure default settings for the camera. If that’s the case for your camera, it could help since “night mode” is probably something specific to your model of camera, unlike for example “brightness” which is probably adjustable on most cameras.

      If changing the brightness setting would solve your problem, it looks like the IAMVideoProcAmp interface you found on MSDN might do the trick. To add it into the code to solve your problem mightn’t be too bad (i.e. setting the brightness to one specific value that works for your camera), but adding it to CommandCam as a general feature would involve more work than I have time for right now :-(

      Anyway, before doing anything more complicated, try adding the delay as I suggested above (if you haven’t tried that already) and let me know how you get on.

      • Fernando says:

        Hello. Tanks for your replay :)

        I have tried the delay and the result was the same.
        I also already implemented the brightness with IAMVideoProcAmp interface in you code but that was not what I want, because the brightness seems like a virtual increase of brightness made by software, but the “night mode” that I’m talking about seems like a physic thing, like if the lens of the webcam open to let more light enter or something. I know that because the software that comes with my pc to control webcam has that functionality and if I turn the night mode on in the software and take a snapshot with CommandCam the result comes perfect. So what I wanted to know was if there are a way to do that in the code, so I don’t have to open the webcam software every time before use CommandCam.

        Tank you anyway and sorry for my late replay :)

      • batchloaf says:

        Hi Fernando,

        What make and model of camera are you using? I’ll see if I can work out how night mode can be activated programmatically.

        I’ve just done a little digging around and I did find some information that could be useful. What I think are the most likely settings to be changed for “night mode” are the camera aperture and exposure time. Both of these are controlled using the IAMCameraControl interface:

        http://msdn.microsoft.com/en-us/library/windows/desktop/dd387908%28v=vs.85%29#camera_settings

        It might be possible to query the IAMCameraControl interface to see what aperture (aka “iris”, I think) and exposure settings are used with and without night mode enabled (using the camera’s own configuration application to turn it on and off).

        Regards,
        Ted

    • Fernando says:

      Hi Ted,

      That’s a good idea, but I already tried to use the IAMCameraControl and it don’t work with my webcam (or I’m doing something wrong, but I don’t think so, because I used the IAMVideoProcAmp just fine and the way both works should be essentially the same). What happens it that when I use the GetRange method it don’t succeed to return in any property. So, or I’m doing something wrong, or my webcam don’t support any property of IAMCameraControl interface.

      This is the adaptation that I made to the MSDN IAMVideoProcAmp example code to work with IAMCameraControl:

      IAMCameraControl *pProcAmp = 0;
      hr = pCap->QueryInterface(IID_IAMCameraControl, (void**)&pProcAmp);
      FILE *cam = stdout; // just some file I was using to store the printed messages
      if (FAILED(hr))
      {
      fprintf(cam, “QueryInterface Error\n”);
      }
      else
      {
      fprintf(cam, “QueryInterface OK\n”);
      long Min, Max, Step, Default, Flags, Val;

      hr = pProcAmp->GetRange(CameraControl_Pan, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Pan\n”);

      hr = pProcAmp->GetRange(CameraControl_Tilt, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Tilt\n”);

      hr = pProcAmp->GetRange(CameraControl_Roll, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Roll\n”);

      hr = pProcAmp->GetRange(CameraControl_Zoom, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Zoom\n”);

      hr = pProcAmp->GetRange(CameraControl_Exposure, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Exposure\n”);

      hr = pProcAmp->GetRange(CameraControl_Iris, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Iris\n”);

      hr = pProcAmp->GetRange(CameraControl_Focus, &Min, &Max, &Step, &Default, &Flags);
      if (SUCCEEDED(hr))
      fprintf(cam, “CameraControl_Focus\n”);
      }
      fclose(cam);

      This code should print the properties that return successfully but it only prints “QueryInterface OK”. So I think this means that none of the properties are supported.

      My webcam is a Chicony CNF7051.

      Tanks Ted, I’m really appreciating your help :)
      And sorry for my English :P

      • batchloaf says:

        Hi Fernando,

        Perhaps it would be worth printing out the hr values returned from each of those function calls just to be sure what’s stopping it from working? For example,

        if (SUCCEEDED(hr)) fprintf(cam, “CameraControl_Tilt\n”);
        else fprintf(stdout, "hr = %d\n", hr);
        

        Once you’ve printed them out, you can look up the hr values here:
        http://blogs.msdn.com/b/eldar/archive/2007/04/03/a-lot-of-hresult-codes.aspx

        Ted

      • Fernando says:

        Hi Ted,

        I done what you said. The error is:
        hr = -2147023728

        But I can’t find the meaning of the error anywhere.

      • batchloaf says:

        Hello again Fernando,

        Sorry, I think that was my fault – I should have said to print the error code as unsigned int or hex (“%u” or “%x” rather than “%d”). Anyway, I’ve converted the number you got into an unsigned int and then printed it as a hex value – 0x80070490. I then googled “DirectShow 0x80070490″ and I found the following page:

        http://msdn.microsoft.com/en-us/library/windows/desktop/dd375623%28v=vs.85%29.aspx

        I did a search on that page for the error code you received (in hex format) and I found this:

        E_PROP_ID_UNSUPPORTED
        0x80070490
        The specified property identifier is not supported.
        

        So, unfortunately that doesn’t sound good for controlling your camera this way! We’ll have to try to think of a different way.

        Ted

      • Fernando says:

        Hello Ted,

        Well, seems like that the problem is with my camera.
        I think I already gave you much work, so I will try to find a solution for may camera on my own and if I succeed I will let you know.

        Tank you for everything and once again congratulations for the excellent software you have made :)

      • batchloaf says:

        Hi Fernando,

        Ok, best of luck getting it working. One final tip, by the way: In case you haven’t seen this:

        http://forums.computers.toshiba-europe.com/forums/thread.jspa?threadID=39643

        It sounds from the last message in that discussion that the drivers for at least some Chicony cameras may have been updated to remember the night mode setting. If that’s the case for your camera, then updating your drivers might solve the problem.

        If not, best of luck finding another solution!

        Ted

  55. 4lfr3d0 says:

    oraleee: muy buen trabajo.
    probado en win7 y compilación exitosa en vs 2010.

  56. Kenneth Deitz says:

    Dr. Burke, if command cam could select a camera not by type but by serial number as seen in the USB device entry, it would be a big benefit to me. Please see email sent…

    • batchloaf says:

      Hi Ken,

      Indeed I think it might be possible to do more or less as you suggest. Each capture device has a unique string called its “DevicePath”. My understanding is that this string can be accessed in the same way as the device name is accessed on lines 274 and 326, e.g.

      pPropBag->Read(L”DevicePath”, &var, 0);

      I’m not on a Windows PC here, so I won’t be able to try this until I’m back in the office, but if I do find a few spare minutes over the next few days, I’ll see what I can do.

      Regards,
      Ted

  57. Kenneth Deitz says:

    Thank you. I think the camera supplier fed me a line about their software. As I wrote in my other communique, I have two of the same device id cameras on the same computer so the serial number is the means of accessing individuals.

  58. Kenneth Deitz says:

    I may be speaking stupidly to you, but the NIRSOFT USBDEVIEW software shows this Serial Number field…

  59. Kenneth Deitz says:

    Serial number is desirable since the device can be plugged in to the USB facility of the computer in different slots…

    • batchloaf says:

      According to this discussion on MSDN, it sounds like the DevicePath string will either be set to the serial number, or that it will contain it as a sub-string. In either case, once the DevicePath is obtained, it should be possible to match it easily (i.e. in a single line of code) to the serial number in a way that works when the device is plugged into any port.

  60. Kenneth Deitz says:

    Excellent!

    • batchloaf says:

      Hi Ken,

      I’ve added in a new feature for selecting the camera by serial number. To specify a camera with the serial number “314159265”, just type:

      commandcam.exe /devserial 314159265
      

      This feature works by searching the DevicePath for any occurence of the specified serial number as a substring. You can now view the full DevicePath string for each attached device by typing:

      commandcam.exe /devlist
      

      Let me know if this works for your two cameras.

      Regards,
      Ted

  61. Ken says:

    Thank you Ted. Unfortunately, the serial number seen by NIRSOFT USBDEVIEW is not present in the list of devices. Only the Device Name is present. Here is the result…

    I cannot get the new option to work. I wonder what overnight shipping for my camera is to Ireland?

    “CommandCam /devserial 30210152″

    “Video capture device not found”

    • batchloaf says:

      Hi Ken,

      Please plug in both cameras and run “CommandCam.exe /devlistdetail”, then reply here with the full output that appears in the console. I want to see if there are differences in the two DevicePath strings apart from the ones relating to the different USB sockets.

      Ted

  62. Ken says:

    If you can get your code to see the serial number of an Arduino Uno R3, I think you will have it made. The serial number seems to appear in the same field.

  63. Ken says:

    Available capture devices:
    Capture device 1:
    Device name: FJ Camera
    Device path: \\?\usb#vid_04f2&pid_b186&mi_00#7&e3c804d&1&0000#{65e8773d-8f56-1
    1d0-a3b9-00a0c9223196}\global

    Capture device 2:
    Device name: DFM 72BUC02-ML
    Device path: \\?\usb#vid_199e&pid_8207&mi_00#7&98e30b1&0&0000#{65e8773d-8f56-1
    1d0-a3b9-00a0c9223196}\global

    • Ken says:

      I only have one DFM… camera here now. Looking at the string, I don’t see the serial number seen by other software. The manufacturer of the camera makes stuff than can see this, but the software isn’t command line based. Useless to me!

      • batchloaf says:

        Ah right, sorry, I only saw your second message just now. I’ll tell you what: once you have the two identical cameras in the same place, let’s try the same thing again (“CommandCam.exe /devlistdetail”). Hopefully the two identical cameras will have DevicePath strings that will allow them to be distinguished.

        Ted

    • batchloaf says:

      Hi Ken,

      I’m a bit confused. These two cameras are clearly not the same model at all! They have different friendly names (“FJ Camera” and “DFM 72BUC02-ML”) and different vendor and product IDs. There should be no problem whatsoever selecting either one of these cameras consistently using its friendly name – there’s no need to resort to serial numbers!

      For example, for the first camera:

      CommandCam.exe /devname "FJ Camera"
      

      or for the second camera:

      CommandCam.exe /devname "DFM 72BUC02-ML"
      

      Am I missing the point here somehow?

      Ted

  64. Ken says:

    Yes sir, they are not the same. But I am looking at a configuration that I will see in the near future that will have two DFM… cameras.

    • Ken says:

      I do not have the second camera yet. I always try to prevent a disaster before it happens.

      • batchloaf says:

        Ok, well the next best thing you can try is the following:

        Plug the single camera into a USB socket
        Run “CommandCam.exe /devlistdetail”
        Now, unplug the camera and plug it into a different USB socket.
        Run “CommandCam.exe /devlistdetail” again
        Copy the output from both times into a reply here so that I can compare them.

        I should be able to see from the output whether this approach will work. In fact, it would be ideal to try the camera in more than two USB sockets just to be sure. If each physical camera is uniquely identifiable, then a certain part of the DevicePath will stay the same as the camera moves from socket to socket. However, if Windows cannot distinguish two cameras of the same make and model, it uses the USB hub and port to generate this part of the DevicePath which means that it changes when the same camera moves around.

  65. Ken says:

    Dr. Burke, I have tried that! Results! The one part that seems constant and seems as though it can be used as a serial is the “98e30b1″. Indeed, a few minutes ago, I tried this number and it will acquire an image with this number. But, the hex value of this number seems to be quite different than the number that other software sees.

    Position 1:
    Capture device 2:
    Device name: DFM 72BUC02-ML
    Device path: \\?\usb#vid_199e&pid_8207&mi_00#7&98e30b1&0&0000#{65e8773d-8f56-1
    1d0-a3b9-00a0c9223196}\global

    Position 2:
    Capture device 2:
    Device name: DFM 72BUC02-ML
    Device path: \\?\usb#vid_199e&pid_8207&mi_00#7&98e30b1&0&0000#{65e8773d-8f56-1
    1d0-a3b9-00a0c9223196}\global

    Position 3:
    Capture device 2:
    Device name: DFM 72BUC02-ML
    Device path: \\?\usb#vid_199e&pid_8207&mi_00#7&98e30b1&0&0000#{65e8773d-8f56-1
    1d0-a3b9-00a0c9223196}\global

    Position 4:
    Capture device 2:
    Device name: DFM 72BUC02-ML
    Device path: \\?\usb#vid_199e&pid_8207&mi_00#7&98e30b1&0&0000#{65e8773d-8f56-1
    1d0-a3b9-00a0c9223196}\global

    • Ken says:

      To be absolutely sure, I need to get my hands on another camera ASAP.

      • Ken says:

        This number according to Nirsoft is part of the “ParentId Prefix”. I need to look to make sure it will be unique. In the meantime, I am also having another camera sent here.

      • Ken says:

        Okay, I’ve ordered another camera. I also tried the /devlistdetail on a different windows computer. Same “98e30b1″…

  66. Ken says:

    Okay, I’ve ordered another camera. I also tried the /devlistdetail on a different windows computer. Same “98e30b1″…

    • batchloaf says:

      Ok great! Fingers crossed that the second camera will work the same (but with a different id number of course). Based on what you observed when plugging the camera into different sockets (and on different PCs), I’m very optimistic that it will work, but only time will tell for sure.

      Please let me know how you get on. I’ll be delighted if it works, but if not I’ll try to think of another workaround.

      Ted

      • Ken says:

        Dr. Burke. I have confirmed as of a few moments ago that two cameras of the same type are individually addressable via the “ParentId Prefix” scheme you implemented. Thank you very much!

      • batchloaf says:

        Bravo! That’s great news. Best of luck getting everything else working!

        Ted

  67. Ken says:

    Dr. Burke, I am delighted to be working with you.

  68. Pingback: Gitshots für Windows : Zustandsforschung

  69. Diego says:

    Hello.
    Excelent tool for automation, and thanks for making it opensource !
    I have 1question and 2 feature requests. hehe

    I have a few camera models with autofocus.
    Is there any way to set the focus to be constant and disable autofocus?
    The camera will be pointing always in the same direction, and autofocus adds a delay when capturing the image.

    Another question.
    Would it be possible, to read the parameters form an .ini file, and specify that file as the only command line parameter?

    Another question.
    Would it be possible, to capture múltiple devices while commandcam is launched only once ?
    I think that, the OS process spawn time is what takes most of the resources while waiting to have an image. Of course we are talking of half a second per launch.

    Kind regards,
    Diego

    • batchloaf says:

      Hi Diego,

      Thanks for your kind comments. I’ll do my best to answer your questions.

      Regarding the autofocus, I’m afraid I don’t know much about changing that setting programmatically. It may be possible to configure it using DirectShow or some other API, but I haven’t ever done it. Does the manufacturer of your camera provide a control panel that allows autofocus to be switched on and off? If not, then my guess is it may not be possible to disable it. If this setting is available though an existinng control panel for the camera, is it possible to disable it that way and then use CommandCam without the focusing delay?

      You could also have a look at RobotEyez, another image grabbing program where I’ve been trying out new features for the next version of CommandCam. It allows multiple images to be taken sequentially. Since the autofocus would only happen at the beginning, it should allow images to be captured more frequently.

      Regarding reading the parameters from an .ini file, what parameters do you have in mind? Is there a specific reason that this feature would be useful for you? Is it that you want to run CommandCam from a different program, but with different command line arguments each time? If so, there are ways to do this without using an .ini file. If you can explain why you want this feature, I’ll have a think about possible solutions.

      Regarding capture from multiple devices: This is a feature that someone suggested previously and I would certainly like to include it, but it requires quite a bit of modification of the existing code, so it will have to wait until I have more time available to concentrate on CommandCam. I develop this software as a hobby and I have a busy teaching load here in DIT, so it’s hard to find the time during term! Hopefully, I’ll get around to it soon though – I think it would be a really useful feature for a lot of people.

      Ted

  70. Kevin Michaeles says:

    Hi, I’m trying to use your program, and it’s saying it’s working and saving the file image.bmp, but it’s not showing in the directory afterwards.

    • batchloaf says:

      Hi Kevin,

      It sounds like it’s probably running but saving the file in a different directory than the one you expect. Are you running CommandCam by typing in the command in a command window, or are you running it from within a batch file, or are you running it by double clicking on it?

      However you’re running it, I suggest doing a file search in Windows for any files called “image.bmp” – it might just show up somewhere, which would clarify what’s happening.

      Let me know how you get on.

      Ted

  71. Rob Pedersen says:

    This is pretty great. I’ve been looking for something like this for a project for a while. Thanks.

  72. Robin says:

    This is great thanks! But is there a way to get rid of the delay time from executing the program and a file being saved. I have tried ‘CommandCam /delay 1′ but it’s still a few seconds before the image is saved. I need the capture to be instant in the application I am writing.I notice in the source code the default delay time is 2000, does this have something to do with my problem, or is it just my webcam (built in). Apart from this your application works great!

    • batchloaf says:

      Hi Robin,

      CommandCam accesses the camera as a video device and unfortunately it just seems to take some time to start it up. An additional delay can be specified since some cameras take a couple of seconds to automatically adjust the brightness level. However, even with the delay set to zero, it still seems to take a second or two to start up the camera.

      I’ve been thinking about this problem and considering other solutions like providing a two program solution: one that runs in the background and keeps the camera running, and a second program that lets you just grab a snapshot (from the already open camera) at any particular moment at the drop of a hat. It seems a bit messier than the appealing simplicity of CommandCam, but maybe it’s worth considering?

      Ted

  73. Ken says:

    This is an excellent idea Dr. Burke. I am sure it could potentially speed up operations in my application.

  74. satyajit says:

    I am really impressed..I am using windows 7 and when I try to run it as WINDOWS task scheduler, Its activating the camera as lights do blink,but I don’t see the picture getting saved…help me

    • batchloaf says:

      Hmmm, interesting problem. If you run it with the task scheduler, I’m not sure what directory the image file will be saved in by default. Have you tried using Windows file search to find the file?

      Alternatively, you could try using CommandCam’s “/filename” switch to specify the full path of the output file. For example:

      CommandCam /filename "c:\output.bmp"

      Hopefully that will save the file in the root directory of the C drive, but you could specify whatever directory you want.

  75. I was pretty excited to have found this at first, but seem to have found a glitch. When I try the code this way, first: commandcam /devnum 1 /filename c:\test.bmp
    it works. The second time i re-run the same line and it it returns an error of “Could not render capture video stream”. So then I tried commandcam /devnum 2 /filename c:\test.bmp, and it works using the front camera; and continues to work multiple times using the front camera. The rear camera; the one I really want to use, will only work once, until system reboot. I have to restart the computer for it to ever re-capture from the devnum 1; and only have it capture once, followed by the error message I’ve specified. Very annoying. Why is this?

    • batchloaf says:

      Hi Robert,

      I haven’t come across this problem before, but I don’t have a 64-bit Windows computer to try it on. Perhaps someone else can comment if they’ve run into a similar problem.

      As a matter of interest, did you try opening the cameras in the opposite order? If you open the front one first and then the back one, maybe you’ll be able to keep opening the back one?

      Finally, I have another program called RobotEyez, which will probably become the next version of CommandCam when I get around to finishing it. In the meantime, you can try it – it might just do what you want. Here’s the link:

      http://batchloaf.wordpress.com/2011/11/27/ultra-simple-machine-vision-in-c-with-roboteyes/

      Please let me know how you get on.

      Ted

  76. oh and; windows surface pro 64bit….2 cameras. I want the rear Camera to work many times over with yur app. only woks with the front though.

  77. Ken Deitz says:

    Dr. Burke. Your commandcam program is wonderful. I have told you that before. I asked you to add the feature for addressing singly among multiple cameras of the same type. You did that. I commend you. I have conquered every physical problem with lighting, camera settings, LCD segment analysis software, creep of plastic parts around fine adjust shims holding the camera…. Now, I have a problem with the manufacturers drivers on my customer’s WIN XP on the CORE 2 DUO system with 2G or storage and directx9c causing hangs one or more cameras, when I have 4 plugged in. WIN7, i5, 6G… Not a problem. It behaves strange with the suppliers GUI app as well when there are 4 under XP. I see strange hanging, slow responses with the supplier software as well as commandcam. Seems like a driver problem too me?

    • batchloaf says:

      Hi Ken,

      If the computer is hanging, then it probably is a driver issue, since a normal application shouldn’t have enough OS privileges to do that. Also, if you’re seeing the problem when using the supplier’s GUI, then it lends further weight to that theory.

      Is it an option to try different cameras instead? I could be wrong, but I’d imagine 4 simultaneous USB cameras in Windows XP is not something many people have done, so the manufacturer probably wouldn’t have done much testing under those circustances. What kind of cameras are they?

      Ted

      • Ken says:

        The Imaging Source. DFM 72BUC02-ML They are not being used intensively. One camera is queried 2 times per minute. Then, the next. and so on. We use the hashed Windows identifier that you added the feature into commandcam to address them. Works wonderfully most of the time. It isn’t the computer that hangs, it is the task and camera that hang. Control-Break and unplug/replug. Then it comes back to life. One in a group of 4 is always at a 50/50 chance for non operation. We went to a better hub and when they operate, they operate much faster. But still some hang. We went to “native” attach to the core 2 duo, XP, system and the behavior is actually slower with commandcam and CC capture. I called Germany from MX and spoke to a support person there. Of course, it is the other guy’s software. But this even happens at low frame rates with their GUI tool. They are sending me a different command line tool. I have to get this running by Saturday or they’ll send the Zeta cartel after me…

    • batchloaf says:

      Hi Ken,

      I did a bit of googling, but didn’t turn up anything very useful. I’m not sure I can offer much help with this since I won’t be able to reproduce the problem here. Did you make any progress yourself?

      Ted

  78. sanju says:

    hello sir. iam trying to use cmdcam with access form. i have a button on a form to call cmdcam.exe. everything works well except that there is no image file as output but when i double click the exe directly it works fine
    I am using Shell cmd in vba to achieve this

    My code in access 2010 :
    Dim x as variant
    x= CurrentProject.Path & “\CommandCam.exe”
    Call Shell (x,vbHide)

    • batchloaf says:

      Hi Sanju,

      Unless you specify a different folder for the file to be saved in, CommandCam will place the file in the current working directory. When you run it from Access using the shell command, I’m not sure what the working directory will be.

      Perhaps you could try specifying the full path in the filename that CommandCam should use. For example,

      CommandCam /filename c:\myfolder\whatever\image.bmp
      

      I’m not sure whether you will need to “escape” each of the backslahes if you’re putting that into a string for a shell command. Depending whether or not you need to do that, your line would probably end up looking like one of the following:

      x= CurrentProject.Path & "\CommandCam.exe /filename c:\myfolder\whatever\image.bmp"
      

      or

      x= CurrentProject.Path & "\CommandCam.exe /filename c:\\myfolder\\whatever\\image.bmp"
      

      Alernatively, you can try changing directory before calling the shell command, as I did in this Excel VBA example:

      http://batchloaf.wordpress.com/2013/01/07/running-commandcam-from-excel-using-vba/

      Hopefully that helps. Let me know how you get on.

      Ted

  79. Parker says:

    Hello, I happen to stumble upon your project and found it to be very helpful. I have so far managed to make the camera to capture a multiple images at a very fast speed, but then I came across a problem where I have more than one camera and couldn’t capture from all 3 of them. I’m trying to remake a program to capture from all 3 cameras is there a way?

    • batchloaf says:

      Hi Parker,

      A few other people have expressed interest in a multi-camera version of CommandCam, so I’m hoping to incorporate this into the next version. However, I’m not sure exactly when I’ll get around to it. I’m currently unable to do any Windows development because my Windows laptop has bitten the dust so I’m completely Linux based at the moment.

      Hopefully I’ll get around to it soon though! I’m pretty sure it should be possible. Can you please give me some details about what kind of capture you need to do – i.e. how many cameras, for how many frames, and at what frame rate?

      Ted

      • Parker says:

        Hi, Ted
        I will be using 3 cameras and ring loops will be used so infinite frames but it will be storing 2000 images per camera till it loops back and re-saves from the start, and frame rate will be around 140 fps (its a high speed cameras)

      • batchloaf says:

        Ok, wow, that’s a lot of video! I’ll try to keep this in mind when I get back to CommandCam development. It won’t be for a little while though because my Windows machine is out of action, so I’m Linux only at the moment.

        I’d really like to get CommandCam working with multiple cameras at once.

        Ted

  80. niravshah08 says:

    Hi,
    First of all, EXCELLENT WORK! this program is just awesome. Is there any way you could change the initial delay to 100ms because when i try to “/delay 500″ (or anything below 2000) it doesn’t take that into account and does 2000ms delay. Also is there any way you could disable the flash (or whatever you call that tiny white light next to webcam) from integrated webcam so that the user doesn’t know that webcam has turned on and taken a picture. Again thanks for this wonderful application

    • batchloaf says:

      Hi Niravshah,

      Thanks for your generous words. Sorry for the delay replying – I’ve been on holidays.

      Unfortunately, the 2 second delay you’re experiencing is not introduced by CommandCam – it just takes Windows a couple of seconds to open the camera and wait until it’s ready to deliver data to the program that opened it. Some cameras are faster than others, so you could try a different one to see if it produces a shorter delay.

      If you need a really fast response to snapshot some event, you probably need to use a different program that keeps the camera open and just records a frame instantaneously when something happens to trigger it.

      Regarding the light on the camera, it’s not normally possible for software to disable it, because it’s there to let the user know that some piece of software is accessing it, for example so that malware programs cannot spy on computer users without them realising it. I suppose it would be possible to disable the light by physically disconnecting the LED or whatever, but I wouldn’t recommend doing that! Also, there may be some cameras out there that don’t have a light, but all of my USB cameras have one.

      Ted

  81. Pingback: Computer Security: Snap a Picture of Whoever Logs on Your Laptop

  82. Terry says:

    Hi

    I tested against a “Microsoft« LifeCam VX-2000″.
    that got converted to; …commandcam.exe /devname “Microsoft½ LifeCam VX-2000″
    commandcam.exe replied; Video capture device Microsoft╜ LifeCam VX-2000 not found.

    I can see that the device name choice may not have been the best.

    • batchloaf says:

      Hi Terry,

      That’s an interesting problem. I haven’t come across camera names with those kind of exotic characters before. Could you try running “CommandCam /devlist” or “CommandCam /devlistdetail” to see what the camera shows up as there? You should still be able to select the device by device number or by serial number, although the device number may change depending on the order cameras are plugged in or which USB socket is used for each one.

      Ted

      • Terry says:

        Capture device 1:
        Device name: Microsoft« LifeCam VX-2000
        Device path: \\?\usb#vid_045e&pid_0761&mi_00#6&2dda4885&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global

        The character is a ®. (Registered trademark)
        I am using /devnum to access the webcam at the moment.

        Btw. It’s a great program. Thank you!

  83. Tom says:

    Hello, I have proposed you for Nobel prize, and I haven’t checked your code on Acer but I would like to make a small proposition, I’m very good in VBA but C++ and other C-s are total mistery for me. If you could help me to adjust CommandCam.exe code for taking pictures with preview and naming files with date of creation (and not deleting them) I would press that DONATE button so strong it would fall of screen :) . Please say yes :) . p.s. Sorry my english is not very good but I’m trying :) .

    • batchloaf says:

      Hi Tom,

      As it happens, I may have an hour or two free this afternoon to do a little programming. Can you explain a little bit more about how you want this to work? So far, what I think you’re looking for is:

      1. Run CommandCam from the command line. (Or do you want to run it from Excel VBA?)
      2. Display a preview window showing the moving image from the camera.
      3. Press a button or something to capture an image.
      4. Save the image to a file using the date and time as the filename.

      Is that correct? If so, please give me an example filename, so that I can format it the way you need it. I’ll have a look at this later, but no guarantees! By the way, if I do get it working, there’s no need to donate. Of course it’s nice when people do, but it’s almost as nice when people just say thanks. I’m not really in it for the money, which is just as well – donations are few and far between ;-)

      Ted

      • Tom says:

        If you get it to work it would be my honor to donate some money. File name is easy INS_REP_datetime.jpg. I would like to run it from Excel VBA and to have preview in workbook. And to be able to Press a button or something to capture an image. Thanks for your time. I appreciate it.

      • Tom says:

        If you get it to work it would be my honor to donate some money. File name is easy INS_REP_datetime.jpg. I would like to run it from Excel VBA and to have preview in workbook. And to be able to Press a button or something to capture an image. And one more thing. Not to delete pictures that were created before. Thanks for your time. I appreciate it.

  84. Tom says:

    I have managed to solve all problems I had with integration of commandcam.exe into VBA. If you want I can send you sample workbook. Thanks :)

  85. Thanks …this post helped me a lot…

  86. Arun K. Tripathi says:

    Hey, I want to trigger camera & save image in a particular location I have only VBS to trigger your programm. Can anyboday share a script for it to me.

    Thanks

  87. Pingback: Windows – Mac – Android – IOS – Graphic – Wallpaper – Webmaster | Topdl Computer Security: Snap a Picture of Whoever Logs on Your Laptop - Windows - Mac - Android - IOS - Graphic - Wallpaper - Webmaster | Topdl

  88. Pingback: Windows – Take Webcam Picture At Set Intervals | Project Failure

  89. Cole says:

    Where are the pictures saved to? Can we change the location?

    • batchloaf says:

      By default, the pictures are saved to the current working directory. However you should be able to specify whatever location you want using CommandCam’s “filename” command line option. For example,

      CommandCam /filename "c:\output.bmp"
      

      That should save the file in the root directory of the C drive, but you could specify whatever directory you want.

  90. Pichu Frisby says:

    Great job! Solved the issue on file name by using some lines in a batch file:
    set d=%date:~-4,4%%date:~-7,2%%date:~0,2%
    set d=%d: =_%
    set t=%time:~0,2%%time:~3,2%%time:~6,2%
    set t=%t: =0%
    RENAME “image.bmp” “image_%d%_%t%.bmp”

    Works awesome! The occassional “all-green” photo happens but I assume that’s a flaw of the camera.

    Thanks Ted!

  91. FromCol Php Devel says:

    Hi Ted.

    All I have to say is “What a wonderfull work” and thanks for answering all questions and comments, not everyone does it.

    I am going to trate to use it on Web Applications. I’ll talk you about results.

    Congratulations!!

  92. Pingback: Gitshots für Windows : Zustandsforschung

  93. adetuc says:

    Hi,
    Thanks for a great code.
    Did you introduce the resolution change to CommandCam yet ?
    Also when i execute the preview command the preview screen only comes up for 2 seconds then closes, can i keep it open for longer ?

  94. Extremely_Toxic says:

    Hello Ted! Great application. The best choice for our Citrix XenApp environment. The same question: is there an option to change resolution in commandcam?

    • batchloaf says:

      Hi Extremely Toxic,

      I haven’t changed anything in CommandCam for a while due to a lack of free time. However, you might find that RobotEyez (another program I wrote previously) does what you need:

      http://batchloaf.wordpress.com/2011/11/27/ultra-simple-machine-vision-in-c-with-roboteyes/

      It allows you to specify the resolution.

      Ted

      • Extremely_Toxic says:

        Ted, roboteyez is great too, but it can’t render the video stream in xenapp session. For me it’s critical. Is it real to make comcam with fixed resolution? For example 640*480. Tried to setup native logitech driver on the thinclient -no result. The main idea is to use the native win7 driver, cause it is redirected correctly with most of webcams. In any case, wait for donate after 15 july :)

      • batchloaf says:

        Hi Extremely Toxic,

        There’s no need at all to donate, but thanks for offering.

        Do you know the specific resolution that you want to capture at? It’s a while since I’ve done any work on CommandCam, so looking at it now I’m struggling to remember the exact process for configuring and initiating video capture. However, as far as I can tell it just captures at whatever the default resolution for the camera is, which may be different for each camera. Furthermore, it may be possible to modify the default resolution using a camera-specific application (a camera properties dialog box or something like that). You could try checking in the Windows Device Manager to see if such a configuration utility is available for your camera.

        Also, have you got any idea why RobotEyez won’t work in a xenapp session although CommandCam will?

        Ted

      • Extremely_Toxic says:

        Hi again. I have no idea about RobotEyez rendering. Perhaps this problem connected with the OS version. (Works on Win7x64/does not work on Win2k8r2). Tried to change the Citrix HDX policies – no result.
        Yep, i`ve tried to change the default resolution on local PC. No result.
        Probably i have 10000+ users who need to use over 10 different webcam models in XenApp session. CommandCam works with 90% of webcams, and is an universal solution for all users. The only trouble is height and width change availability.
        P.S. Replied here cause there is no “Reply” button after your last post.

      • batchloaf says:

        Hi again,

        Ok, I’ll have a look at this later this afternoon to see if I can spot a way to set the resolution in CommandCam. I know that when I looked at this before, it turned out to be surprisingly awkward, which was one of the reasons I began experimenting with a completely now program (RobotEyez). However, since RobotEyez isn’t working for you, I’ll have another go at setting the resolution in CommandCam. It’ll have to wait until later on though because I’m working at home on my Linux laptop as we speak.

        I may need to get you to test it though because I won’t be sure just by running it on my own machine.

        Ok, I’ll get back to you later.

        Ted

    • Extremely_Toxic says:

      P.P.S. Specific resolution is 640×480.

      • Extremely_Toxic says:

        Great thanks! Waiting %)

      • batchloaf says:

        Hi Extremely Toxic,

        Just a quick update. No success so far, I’m afraid. I spent a bit of time yesterday trying to work out how to set the resolution for the DirectShow sample grabber filter, but it’s surprisingly complicated. It’s becoming clearer to me why I started over with a slightly different approach with RobotEyez!

        I haven’t given up on getting this to work, but I can’t give any guarantees and I’ll be going away for the weekend tomorrow, so if I don’t get it working today it could be next week before I get to look at it again.

        Ted

  95. Extremely_Toxic says:

    Hi. Thanks for this application. It`s great for our Citrix XenApp environment. The same question about resolution change.

  96. Ian Boag says:

    Another happy user! I have a weather station at an airfield and run a simple website using cumulus. I need to take 4 pix every 30 minutes so folk can see what the sky looks like ….. I broke my head trying to connect 4 cams to one USB hub to one computer. Everything I tried gave up after one camera.

    This just eats the job! I even did a donation :-)

    Looks like http://www.easy2convert.com/bmp2jpg/ will handle the rest of the processing.

    Ian Boag in New Zealand ……

    • batchloaf says:

      Wow, thanks for letting me know that – what a fascinating application! I’m delighted to hear that CommandCam did what you needed. Thanks also for the generous donation – it’s much appreciated!

      Ted

  97. Mark Berry says:

    This program is awesome and exactly what I was looking for. I am wondering how hard it would be to change the output to PPM (pixel map) format. I also wish the resolution was selectable. For me it might be desirable to have a smaller resolution to keep the file sizes smaller (320×240). Again Thanks for this very useful program!

    • batchloaf says:

      Hi Mark,

      Would you consider installing another utility to convert the image after it’s captured? For example, I normally use ImageMagick, which is free to download and install, and contains numerous useful utilities for command line image processing and conversion. Imagemagick is incredibly useful and can be used to automate all kinds of image-related jobs.

      You can download the Windows version of ImageMagick here.

      Assuming you’re running CommandCam in a batch file, you would simply add an ImageMagick convert command straight after the CommandCam line, something like the following…

      CommandCam /filename output.bmp
      convert output.bmp output.ppm
      

      ImageMagick is actually a suite of (mostly command line) software utilities, of which “convert” is just one program. So it’s the second line in the example above that actually runs ImageMagick.

      You can also use ImageMagick to reduce the resolution of the image, so that if you’re archiving a lot of images they will use up less space. Something like…

      CommandCam /filename output.bmp
      convert output.bmp -resample 320x240 output.ppm
      

      The “-resample” operation is just one of a long list of image processing operations that ImageMagick can perform. For example, see the long list of options for the convert command.

      If you want each archived image to be saved with a filename that includes the current time, you could try something like…

      CommandCam /filename output.bmp
      convert output.bmp -resample 320x240 %TIME%.ppm
      

      If you’re trying to save storage space, you might also want to consider using a more compressed image format, such as jpeg…

      CommandCam /filename output.bmp
      convert output.bmp -resample 320x240 %TIME%.jpg
      

      WARNING: I wasn’t able to test any of these examples because I’m working on a linux laptop here, so apologies if some of them require modification to make them work correctly!

      Anyway, would something like the above ImageMagick examples do the trick in your application?

      Another option you could consider is to try RobotEyez, which is another program I wrote a couple of years ago for automated image capture. It provides some additional options not supported by CommandCam.

      Ted

  98. Chris says:

    Can’t get the object to be found, keep getting a 424 error. Any ideas?

    • batchloaf says:

      Hi Chris,

      Can you be a bit more specific? Are you seeing this error when you run CommandCam or when you try to compile it? If it’s the former, please explain a bit about your setup and include the exact command line you’re running. If it’s the latter, please explain which compiler you’re using and tell me if you’ve modified the original code in any way.

      Either way, it would also be useful to know what version of Windows you’re running.

      Ted

  99. Alexis says:

    Dear Ted,
    If i want to using CommandCam code to modify PIN_CATEGORY_STILL(real high resolution) form my camera.
    hr = pBuilder->RenderStream(
    &PIN_CATEGORY_STILL, &MEDIATYPE_Video,
    pCap, pSampleGrabberFilter, pNullRenderer);

    I want to high resolution still capture from my camera, not save a frame.
    How can i modify it.

    I reference MSDN , it say can use PIN_CATEGORY_STILL.
    But i add it in code, the hr error code return is fail.
    I have no idea how to do @@
    please give me a advising.
    Thanks.

    • batchloaf says:

      Hi Alexis,

      I’m afraid I can’t offer much help with this. I tried doing it myself previously, but did not succeed. As far as I could tell, most people capturing still images this way used a different API called WIA (Windows Image Acquisition) which is totally different from DirectShow.

      Anyway, best of luck trying to get it working!

      Ted

  100. Om3ga73 says:

    First time I have gotten something like this to work. Excellent program! I am running this through the Windows Task Scheduler, and I was wondering if you could tell me how to use date/time variables in the filename. Thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s