From: Jérôme on
Hello,

I'm trying to grab pictures from a webcam with Video For Windows (VFW).
The source code I use is the following:

HWND _capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
capDriverConnect(_capwnd,0);

capGrabFrame(_capwnd);
capEditCopy(_capwnd);
OpenClipboard(NULL);
HBITMAP hBmp = (HBITMAP)GetClipboardData(CF_BITMAP);
CloseClipboard();

BITMAP bmp;
GetObject(hBmp, sizeof(BITMAP), &bmp);
int size = bmp.bmWidth*bmp.bmHeight*bmp.bmWidthBytes;
unsigned char* data = new unsigned char[size];

GetBitmapBits(hBmp,size, data);

I get an array of pixels (data) but the image is not in the RGB format
(maybe YUV).

Does anybody know how to get the exact format used by the driver or a
faster way to obtain this array of pixels ? I found no information nor
on msdn or on google.

Thanks,

--
Jýrýme
From: Headache on


Jérôme wrote:
> Hello,
>
> I'm trying to grab pictures from a webcam with Video For Windows (VFW).
> The source code I use is the following:
>
> HWND _capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
> capDriverConnect(_capwnd,0);
>
> capGrabFrame(_capwnd);
> capEditCopy(_capwnd);
> OpenClipboard(NULL);
> HBITMAP hBmp = (HBITMAP)GetClipboardData(CF_BITMAP);
> CloseClipboard();
>
> BITMAP bmp;
> GetObject(hBmp, sizeof(BITMAP), &bmp);
> int size = bmp.bmWidth*bmp.bmHeight*bmp.bmWidthBytes;
> unsigned char* data = new unsigned char[size];
>
> GetBitmapBits(hBmp,size, data);
>
> I get an array of pixels (data) but the image is not in the RGB format
> (maybe YUV).
>
> Does anybody know how to get the exact format used by the driver or a
> faster way to obtain this array of pixels ? I found no information nor
> on msdn or on google.
>
> Thanks,
>
> --
> Jérôme

You should be using device independent bitmaps (DIBs) and using
capGetVideoFormat to explain how the colour section of your DIB held
(indexes into your system palette, true RGBQuad values etc.).

From: Jérôme on
Headache wrote:
> You should be using device independent bitmaps (DIBs) and using
> capGetVideoFormat to explain how the colour section of your DIB held
> (indexes into your system palette, true RGBQuad values etc.).
>

Thanks for your help Headache. But how do you get an array of pixels
from a DIB ? When I use something like this:

unsigned char* data = (unsigned char*)GlobalLock(hDIB);

I obtain a reversed picture with bad colors (blue becomes green) !

Any good tutorials,books or others documentations about the GDI API ?
I'm totally lost...

--
Jýrýme


From: Jérôme on
Jýrýme wrote:
> When I use something like this:
>
> unsigned char* data = (unsigned char*)GlobalLock(hDIB);
>
> I obtain a reversed picture with bad colors (blue becomes green) !

It works now ! :)
The picture was inversed because the rows of a DIB are stored upside
down and the colors were bad because of a bad adressing of the data
pointer (the pixels array is just after BITMAPINFOHEADER in DIB).

I join the source code of my small testing program which grabs a picture
from a webcam and store it in a PPM file.

#include <windef.h>
#include <wingdi.h>
#include <VFW.H>

#include <stdio.h>
#include <iostream>

int main(){
HWND _capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
capDriverConnect(_capwnd,0);

capGrabFrame(_capwnd);
capEditCopy(_capwnd);
OpenClipboard(NULL);
HANDLE hDIB = GetClipboardData(CF_DIB);
BITMAPINFOHEADER* pInfo;
pInfo = (BITMAPINFOHEADER*)GlobalLock(hDIB);

unsigned char* data = (unsigned char*)pInfo+sizeof(BITMAPINFOHEADER);

GlobalUnlock(hDIB);
CloseClipboard();

unsigned char* points = new unsigned char[320*240*3];

for(int i=0; i<240; i++)
for(int j=0; j<320; j++)
{
points[3*j+320*i*3] = data[3*320*(239-i)+3*j+2]; // R
points[3*j+320*i*3+1] = data[3*320*(239-i)+3*j+1]; // G
points[3*j+320*i*3+2] = data[3*320*(239-i)+3*j]; // B
}

FILE * pFile;
pFile = fopen ("test.ppm" , "w");
fprintf(pFile, "P6 %d %d 255 ", 320, 240);
fwrite ((unsigned char*)points, 1 , 320*240*3 , pFile);
fclose (pFile);

capDriverDisconnect(_capwnd);
}

--
Jýrýme