2

I am using the Windows API to take a picture with the attached webcam.

All works fine except the picture captured is very dark. If I start the webcam in another application and then I capture with my application, all works fine. What am I doing wrong?

Here is the code I use:

procedure TWebCam.Execute; //different thread
var
  hand: THandle;
  fname: AnsiString;
const
  WM_CAP_START = $0400;
  WM_CAP_DRIVER_CONNECT = $0400 + 10;
  WM_CAP_DRIVER_DISCONNECT = $0400 + 11;
  WM_CAP_SAVEDIB = $0400 + 25;
  WM_CAP_GRAB_FRAME = $0400 + 60;
  WM_CAP_STOP = $0400 + 68;
  WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
  WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52;
  WM_CAP_SET_SCALE = WM_CAP_START + 53;
begin
  FreeOnTerminate := True;
  fname := AnsiString(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) +
    'capture.bmp');
  if FileExists(String(fname)) then DeleteFile(string(fname));
  hand := capCreateCaptureWindowA('CapWindow32', WS_CHILD and WS_VISIBLE, 0, 0,
    0, 0, frmMain.Handle, 0);
  if hand <> 0 then
  begin
    if SendMessage(hand, WM_CAP_DRIVER_CONNECT, 0, 0) <> 0 then
    begin
      SendMessage(hand,WM_CAP_SET_PREVIEWRATE,66,0); //tried some stuff that are not required but without any success
      SendMessage(hand, WM_CAP_SET_PREVIEW, 1, 0);
      Sleep(5000);
      SendMessage(hand, WM_CAP_GRAB_FRAME, 0, 0);
      SendMessage(hand, WM_CAP_SAVEDIB, 0, NativeInt(PAnsichar(fname)));
      SendMessage(hand, WM_CAP_DRIVER_DISCONNECT, 0, 0);
      SendMessage(hand, $0010, 0, 0);
      SendMessage(frmMain.Handle,WM_USER + 24,0,0); //notify main thread
    end
    else
    begin
      SendMessage(hand, $0010, 0, 0);
      Synchronize(NoWebcam);
    end;
  end
  else
    Synchronize(NoWebcam);
end;
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
opc0de
  • 11,557
  • 14
  • 94
  • 187
  • 2
    I think that after "WM_CAP_DRIVER_CONNECT" you need to send another message which will make the webcam's LED to shine (: –  Feb 15 '12 at 17:06
  • 1
    @DorinDuminica eventual sa dea drumu la bec :)) – opc0de Feb 15 '12 at 17:09
  • @AndreasRejbrand det var ett skämt ... du är alltid kränkande och sarkastiska ... har du vänner? – opc0de Feb 15 '12 at 17:30
  • @AndreasRejbrand thought you downvoted it just for a simple joke ... sorry didn't meant to be rude ... just i dislike that every time i post a question is down voted and i don't eaven know the reason... my apologies – opc0de Feb 15 '12 at 17:48
  • Maybe [this](http://stackoverflow.com/questions/3454688/getting-a-snapshot-from-a-webcam-with-delphi) could help. – kobik Feb 15 '12 at 18:29
  • There could also be a way to change ISO/Exposure/CCD-Preamp-level from the API. – Warren P Feb 15 '12 at 21:11

1 Answers1

2

I hate to give my own questions an answer but maybe someone will find it useful in the future.

The thing is that the webcam adjusts its luminosity progressively when it starts, so you must first capture some dummy frames to get a normal picture... Here is what I use now:

var
 i : Integer;
...
begin
...
   for i := 0 to 24 do
   begin
     SendMessage(hand, WM_CAP_GRAB_FRAME, 0, 0);
     Sleep(200)
   end;
...
end;

Works like a charm, kind of hacky, I wish a WaitForInputIdle function exist for devices too...

ZioBit
  • 905
  • 10
  • 29
opc0de
  • 11,557
  • 14
  • 94
  • 187