multisnapz – command line image capture from multiple VFW cameras

EDIT (20-11-2011) : Since posting this, I have created a new DirectShow command line image grabber called CommandCam, which I recommend you use instead of multisnapz. Get CommandCam here (binary download and source code available).

I’ve just tried modifying the snapz program I published in a recent post to allow multiple cameras to be accessed (one at a time). At first it seemed straightforward – I just changed it so that the user can specify a video capture device number as a command line argument. However, it turned out to be more problematic than I expected. My program uses the ancient VFW (Video for Windows) API to perform video capture, but most modern cameras have a WDM (Window Driver model) driver. Windows allows legacy applications (that expect to interact with a VFW driver) to access WDM cameras via some sort of wrapper driver. So far so good, but unfortunately the wrapper driver only appears as a single VFW device, no matter how many WDM cameras it is wrapping.

I just got hold of two cameras to try out my multi-camera version and the first time I ran it with both cameras plugged in, a dialog box popped up to ask me which camera I wanted to use. After that, it didn’t ask me to choose again – it just kept automatically opening the camera I had selected the first time. It always appears as VFW device number 0. Using a higher device number does not work at all – the function capDriverConnect simply fails to connect to a device.

Anyway, for what it’s worth, just in case anyone has more than one camera with a VFW driver that they want to choose between, here’s the multiple camera version. I’ve changed the program name to multisnapz.exe. To capture an image from a particular video capture device, just specify the device number as a command line argument. For example, To capture an image from device 1, just run “multisnapz 1”.

Here’s the C code:

// multisnapz.exe - a command line cam image grabber
// Written by Ted Burke, Last updated 26-4-2011
// This works for multiple VFW cameras, but does not
// work for multiple WDM cameras because the standard
// wrapper driver wraps multiple WDM cameras as a
// single VFW device.
// For example, to snap an image from capture device 1,
// use the following command:
//      multisnapz 1
// To compile with MinGW:
//		gcc -o multisnapz.exe multisnapz.c -lvfw32

#include <windows.h>
#include <vfw.h>
#include <stdio.h>

// Window handles
HWND hWnd;
HWND hWndCap;

int capture_w = 640;
int capture_h = 480;
int time_delay = 0;		// delay in ms before snapshot
int preview_video = 0;	// Don't show on screen

// Message handling function
    HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    case WM_TIMER:
        // Save DIB snapshot, then exit from program
        capFileSaveDIB (hWndCap, "snapz.dib");
    case WM_CLOSE:
    case WM_DESTROY:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    return 0;

int WINAPI WinMain(
    HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
    // Register window class
    wc.cbSize        = sizeof(WNDCLASSEX);         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = "snapzWindowClass";
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
        fprintf(stderr, "Window Registration Failed!");

    // Create main window
    hWnd = CreateWindowEx(
        capture_w + 100, capture_h + 100,
        NULL, NULL, hInstance, NULL);
    if (hWnd == NULL)
        fprintf(stderr, "Couldn't create main window.");

    // Create capture window
    hWndCap = capCreateCaptureWindow(
        NULL, WS_CHILD,
        0, 0, capture_w, capture_h,
        hWnd, 0);
    if (hWndCap == NULL)
        fprintf(stderr, "Couldn't create capture window.\n");
        return 1;

    // Check to see if a specific camera was selected on the
    // on the command line. If a valid integer was not provided
    // atoi returns 0. Device 0 is the default camera.
    int capture_device;
    capture_device = atoi(lpCmdLine);

    // Connect to capture driver and set resolution
    if(!capDriverConnect(hWndCap, capture_device))
        fprintf(stderr, "Couldn't open capture device.\n");
        if (hWndCap) DestroyWindow(hWndCap);
        return 1;
    DWORD dwSize = capGetVideoFormatSize(hWndCap);
    LPBITMAPINFO lpbi = (LPBITMAPINFO)malloc(dwSize);
    capGetVideoFormat(hWndCap, lpbi, dwSize);
    lpbi->bmiHeader.biWidth = capture_w;
    lpbi->bmiHeader.biHeight = capture_h;
    capSetVideoFormat(hWndCap, lpbi, dwSize);

    // Initialise and start video preview
    if (preview_video > 0)
        // Set up video preview
        capPreviewRate(hWndCap, 1); // rate in ms
        capPreview(hWndCap, TRUE);
        ShowWindow(hWndCap, SW_SHOW);

        //Show main window
        ShowWindow(hWnd, nCmdShow);

    // Set timer to trigger snapshot
    SetTimer(hWnd, 1, time_delay, NULL);

    // Message loop
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0) > 0)

    // Tidy up video capture stuff
    KillTimer(hWnd, 1);
    capPreview(hWndCap, FALSE);
    if (hWndCap) DestroyWindow(hWndCap);

    return msg.wParam;

Please note that the devices in question must be VFW devices. It is very unlikely that this program will allow access to more than one WDM device unless there is a workaround I’m not aware of. I did see some mention of other VFW wrapper drivers during my little bit of research today, so if you’re really desperate to use this program to capture from multiple WDM devices, that might be something you could investigate.

Since a few people have contacted me about this program since I posted it, it seems like there is some demand for a simple command line image capture solution, so I might have a shot at rewriting it to use DirectShow which should allow multiple camera access.

This entry was posted in Uncategorized and tagged , , , , , , , , , . Bookmark the permalink.

5 Responses to multisnapz – command line image capture from multiple VFW cameras

  1. Timothy says:

    I’ve tried running both `snapz` and `multisnapz 0`, and both programs ask me every time to select which capture device to use. Using `multisnapz 1` gives the error “couldn’t open capture device”.

    I’m running win7 x64, and the two capture devices in the dropdown list are:
    Hauppauge WinTV 418 Video Capture
    Logitech Webcam 500

    I would like to be able to set the webcam as the default device and not have it ask me anymore, since the whole point of the batch file is to avoid user interaction.

    Thanks for any help, and let me know if you need more details.

    • Timothy says:

      Forgot to check the “notify me of replies” box on the first post, so reply to this one instead.


      • batchloaf says:

        Hi Timothy. Thanks for the feedback. The problem you’re having seems to be related to the fact that the current version of snapz (and multisnapz) uses the old VFW (Video for Windows) API to access the camera, rather than the newer DirectShow API. I’m currently rewriting it to use DirectShow because several people are having the same problem as you. Basically, what I think is happening is that when you run snapz, it looks for the default VFW camera. Since your camera probably only has a DirectShow driver, windows “wraps” it with a VFW “adapter” driver. It’s this “adapter” driver that’s actually displaying the camera selection dialog box, rather than snapz. Unfortunately, the adapter driver seems to make all available DirectShow devices appear as a single virtual VFW device and that dialog you’re seeing pops up to let the user specify which device will be “wrapped” by the adapter driver.

        Ok, anyway, to cut a long story short, keep an eye on this blog and hopefully I’ll have the DirectShow version available for download soon, which should solve your problem.

  2. dreamz says:

    Hi batchloaf, It works greatly! But there is a bit problem, when I snap two picture with the same condition, it has some chromatic aberration compare with another GUI snapz.
    Thanks for any help, and let me know if you need more details.

    • batchloaf says:

      Hi Dreamz,

      I have found this myself with some cameras – I take two snapshots the exact same way, but they come out different. Inserting a short delay between opening the camera device and taking the snapshot seems to mostly solve this by giving the camera more time to warm up. Multisnapz doesn’t include a command line argument option for setting a delay. However, if you’re willing to recompile it, it’s extremely easy to insert a delay. There is a global variable called “time_delay” which is currently initialised with a value of zero. If you change that number to whatever delay you want (in milliseconds) and recompile, it will insert that delay before taking the snapshot.

      A better alternative is probably to use CommandCam (the link should be in the navigation bar at the top of this page). CommandCam uses the DirectShow API (rather than the older Video For Windows API which multisnapz uses), which means that it will work with more cameras too. If CommandCam doesn’t work for you, you can also try RobotEyez (just do a search for the post using the search box on the right hand side of this page). RobotEyez is what will probably become the next version of CommandCam once I finally get around to incorporating all the new features I have on my list.


Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s