Click here to Skip to main content
15,886,110 members
Articles / Programming Languages / C#
Article

Webcam Web Service

Rate me:
Please Sign up or sign in to vote.
4.64/5 (11 votes)
13 May 20022 min read 416.7K   13.6K   103   65
ASP.NET Web Service written in C# to grab a picture from a webcam

Contents

Introduction

C# Webcam is a port to ASP.NET and C# of the C++ ATL Web Service. It demonstrates the ease of use of C# and ASP.NET to build Web Services compared to ATL Server Web Service.

The project is still based on the Webcam COM component developed in the C++ ATL Web Service. .NET COM Interop is used to import it in the C# project.

Web Service

With Visual Studio, create a new C# ASP.NET Web Service project. Add a reference to 'CamServer 1.0 Type Library' on the COM tab. If 'CamServer 1.0 Type Library' is not in the list, you need to register the Dll CamServer.dll in the 'COM Components' directory. Add this Web Method to the source code obtained by the wizard:

[WebMethod]
public byte[] GrabFrame( short nQuality )
{
    //Shoot a picture from my webcam
    CAMSERVERLib.Camera cam = new CAMSERVERLib.CameraClass();

    return (byte[])cam.GrabFrame( nQuality );
}
Compared to the C++ ATL Web Service we need only three lines of code to get the picture from the COM component and return it to the client.

To have a little more fun coding I decided to add some features. Now it writes to the Windows EventLog the IP and the name of the machine calling it, after a DNS resolution. I have also added the date and hour of the local computer directly in the picture. And at last it increments a system performance counter to keep an eye on the number of people calling it.
[WebMethod]
public byte[] GrabFrame( short nQuality )
{
    //Write to the EventLog the IP and Host name
    string addr = HttpContext.Current.Request.UserHostAddress.Trim();

    string name;

    IPHostEntry host = null;

    try
    {
        host = System.Net.Dns.GetHostByAddress( addr );

        if ( host != null )
        {
            name = host.HostName;
            for( int i = 0; i < host.Aliases.Length; i++ )
                name += "*" + host.Aliases[i];

            eventLog.WriteEntry( addr + " : " + name );
        }
        else
        {
            name = "ERROR";

            eventLog.WriteEntry( name );
        }
    }
    catch( System.Exception error )
    {
        // process the error error.Message
    }

    //Shoot a picture from my webcam
    CAMSERVERLib.Camera cam = new CAMSERVERLib.CameraClass();

    byte[] picture = (byte[])cam.GrabFrame( nQuality );

    //Increments Performance Counter
    performanceCounterShoot.Increment();

    //Add the hour
    MemoryStream ms = new MemoryStream( picture );
    Bitmap bmp = new Bitmap( ms );

    Graphics g = Graphics.FromImage( bmp );

    string strDate = DateTime.Now.ToLongDateString() + 
                     " - " + 
                     DateTime.Now.ToLongTimeString(); 

    g.DrawString(   strDate,
                    new Font( FontFamily.GenericSansSerif, 10 ),
                    new SolidBrush( Color.Black ), 
                    new RectangleF( 1,1,320,240 ) 
                );

    g.DrawString(   strDate,
                    new Font( FontFamily.GenericSansSerif, 10 ),
                    new SolidBrush( Color.White ), 
                    new RectangleF( 0,0,320,240 ) 
                );

    MemoryStream ms2 = new MemoryStream();

    //Get codecs
    ImageCodecInfo[] icf = ImageCodecInfo.GetImageEncoders();

    EncoderParameters encps = new EncoderParameters( 1 );
    EncoderParameter encp = new EncoderParameter( Encoder.Quality, (long) nQuality );

    //Set quality
    encps.Param[0] = encp;

    bmp.Save( ms2, icf[1], encps );
    ms2.Close();

    return ms2.ToArray();
}

Client

The client ActiveX has no need to be modified. It is just needed to change the url of the Web Service, that is now:
http://YOUR_IP/webcamcsharp/service1.asmx?WSDL

Don't forget to register with regsvr32.exe the AxCamClient.dll in the 'COM Components' directory.

Conclusion

With few lines of source code you may obtain the same result then with little more C++ work.

The solution may be better because the COM component pack the picture, we unpack it to add date and hour then we pack again the new picture to send back to the client.

Problems Faced 

  • None.

History

Version 1.00 April 10, 2002
First release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Team Leader
France France
I am an experienced Team Leader & Senior Solutions Architect with a passion for shipping high-quality products by empowering development team and culture toward an agile mindset. I bring technical vision and strategy, leading engineering teams to move product, processes and architecture forward.

Comments and Discussions

 
Generalayuda Pin
5353015030-Mar-04 4:13
5353015030-Mar-04 4:13 
GeneralRe: ayuda [Help] Pin
Colin Angus Mackay30-Mar-04 4:42
Colin Angus Mackay30-Mar-04 4:42 
GeneralRe: ayuda Pin
rrferreira21-Dec-06 10:46
rrferreira21-Dec-06 10:46 
Generaldll Error ...please help!! Pin
alexhongkong19-Jan-04 18:06
alexhongkong19-Jan-04 18:06 
GeneralRe: dll Error ...please help!! Pin
reel11-Aug-05 5:39
reel11-Aug-05 5:39 
GeneralRe: dll Error ...please help!! Pin
daldal11-Jan-06 12:48
daldal11-Jan-06 12:48 
GeneralHelp Pin
marnicola5-Jan-04 18:37
marnicola5-Jan-04 18:37 
GeneralMultiples WebCams on one PC Pin
Teh Joo Peng1-Jan-04 21:56
Teh Joo Peng1-Jan-04 21:56 
My Question: Can multiple WebCams of the same model run on a PC?

I have successfully previewed video and grabbed images from one Logitech’s QuickCam Express with the following code.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
using System.IO;

namespace NETCaptureWindow
{

public class MainCls
{
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button2;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Button button1;

private System.ComponentModel.Container components = null;

//user variables
private Form3 CaptureWindow;
public IntPtr hWndC;
public CAPDRIVERCAPS CapDrvCaps;

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, System.EventArgs e)
{
CaptureWindow = new Form3();
CaptureWindow.Show();

hWndC = AVICap.capCreateCaptureWindow("My Capture Window", AVICap.WS_CHILD|AVICap.WS_VISIBLE,
0, 0, 352, 288, CaptureWindow.Handle, 1);
AVICap.capDriverConnect(hWndC, 0);
AVICap.capPreviewRate(hWndC, 40);
AVICap.capPreview(hWndC, true);
//AVICap.capCaptureSequence(hWndC);
}

private void button2_Click(object sender, System.EventArgs e)
{
AVICap.capEditCopy(hWndC);
IDataObject iData = Clipboard.GetDataObject();
if(iData.GetDataPresent(DataFormats.Bitmap))
{
pictureBox1.Image = (Bitmap) iData.GetData(DataFormats.Bitmap);
}
}

}

public class Form3 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;

public Form3()
{
InitializeComponent();
}
}

internal class AVICap
{
public const int WS_CHILD = 0x40000000;
public const int WS_VISIBLE = 0x10000000;
public const int WM_USER = 0x0400;
public const int WM_CAP_START = WM_USER;
public const int WM_CAP_DRIVER_CONNECT = (WM_CAP_START+ 10);
public const int WM_CAP_SEQUENCE = (WM_CAP_START+ 62);
public const int WM_CAP_SET_PREVIEWRATE = (WM_CAP_START+ 52);
public const int WM_CAP_SET_PREVIEW = (WM_CAP_START+ 50);
public const int WM_CAP_DRIVER_GET_CAPS = (WM_CAP_START+ 14);
public const int WM_CAP_SET_OVERLAY = (WM_CAP_START+ 51);
public const int WM_CAP_SET_SCALE = (WM_CAP_START+ 53);
public const int WM_CAP_EDIT_COPY = (WM_CAP_START+ 30);

private const string vfwdll = "avicap32.dll";

[DllImport(vfwdll)]
public static extern bool capGetDriverDescription(int wDriverIndex, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);

[DllImport(vfwdll)]
public static extern IntPtr capCreateCaptureWindow(string lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWnd, int nID);

[DllImport("user32.dll")]
public static extern bool IsWindow(IntPtr hWnd /* handle to window*/);

//[DllImport("user32.dll")]
//public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, ref long lParam);

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, long lParam);

public static bool capDriverConnect(IntPtr hwnd, int i)
{
return ((bool)AVICapSM(hwnd, WM_CAP_DRIVER_CONNECT, (int) i, 0L));
}

public static bool capCaptureSequence(IntPtr hwnd)
{
return ((bool)AVICapSM(hwnd, WM_CAP_SEQUENCE, (int) 0, (long) 0L));
}

public static bool capPreviewRate(IntPtr hwnd, int wMS)
{
return ((bool)AVICapSM(hwnd, WM_CAP_SET_PREVIEWRATE, (int)(wMS), 0));
}

public static bool capPreview(IntPtr hwnd, bool f)
{
return ((bool)AVICapSM(hwnd, WM_CAP_SET_PREVIEW, Convert.ToInt32(f), 0L));
}

//#define capDriverGetCaps(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_GET_CAPS, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPCAPDRIVERCAPS)(s)))

public static bool capDriverGetCaps(IntPtr hwnd, CAPDRIVERCAPS s, int wSize)
{
return ((bool)AVICapSM(hwnd, WM_CAP_DRIVER_GET_CAPS, (int) wSize, Convert.ToInt64((CAPDRIVERCAPS) s)));
}

//#define capOverlay(hwnd, f) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_OVERLAY, (WPARAM)(BOOL)(f), 0L))

public static bool capOverlay(IntPtr hwnd, bool f)
{
return ((bool)AVICapSM(hwnd, WM_CAP_SET_OVERLAY, Convert.ToInt32(f), 0L));
}

//#define capPreviewScale(hwnd, f) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_SCALE, (WPARAM)(BOOL)f, 0L))

public static bool capPreviewScale(IntPtr hwnd, bool f)
{
return ((bool)AVICapSM(hwnd, WM_CAP_SET_SCALE, Convert.ToInt32(f), 0L));
}

//#define capEditCopy(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_EDIT_COPY, 0, 0L))

public static bool capEditCopy(IntPtr hwnd)
{
return ((bool)AVICapSM(hwnd, WM_CAP_EDIT_COPY, 0, 0L));
}

public static bool AVICapSM(IntPtr hwnd, int m, int w, long l)
{
/*
bool iswin = IsWindow(hwnd);
int sm = SendMessage(hwnd, m, w, l);

return Convert.ToBoolean(sm);
*/

//return (IsWindow(hwnd)) ? Convert.ToBoolean(SendMessage(hwnd, Convert.ToUInt32(m), w, ref l)) : Convert.ToBoolean(0);
return (IsWindow(hwnd)) ? Convert.ToBoolean(SendMessage(hwnd, Convert.ToUInt32(m), w, l)) : Convert.ToBoolean(0);
}
}

[StructLayout(LayoutKind.Sequential)]
public struct CAPDRIVERCAPS
{
public UInt32 wDeviceIndex; // Driver index in system.ini
public Int16 fHasOverlay; // Can device overlay?
public Int16 fHasDlgVideoSource; // Has Video source dlg?
public Int16 fHasDlgVideoFormat; // Has Format dlg?
public Int16 fHasDlgVideoDisplay; // Has External out dlg?
public Int16 fCaptureInitialized; // Driver ready to capture?
public Int16 fDriverSuppliesPalettes; // Can driver make palettes?

// following always NULL on Win32.
public IntPtr hVideoIn; // Driver In channel
public IntPtr hVideoOut; // Driver Out channel
public IntPtr hVideoExtIn; // Driver Ext In channel
public IntPtr hVideoExtOut; // Driver Ext Out channel
}
}


Teh Joo Peng
GeneralRe: Multiples WebCams on one PC Pin
Laurent Kempé2-Jan-04 10:46
Laurent Kempé2-Jan-04 10:46 
GeneralRe: Multiples WebCams on one PC Pin
Teh Joo Peng4-Jan-04 19:47
Teh Joo Peng4-Jan-04 19:47 
GeneralRe: Multiples WebCams on one PC Pin
Laurent Kempé4-Jan-04 20:32
Laurent Kempé4-Jan-04 20:32 
GeneralWhy not use Alt+Print Screen Pin
Osrald26-Dec-03 21:31
Osrald26-Dec-03 21:31 
GeneralRe: Why not use Alt+Print Screen Pin
Laurent Kempé26-Dec-03 21:55
Laurent Kempé26-Dec-03 21:55 
QuestionDoesn't work on Win2003 ?? Pin
m@amabilis.hr24-Nov-03 3:36
m@amabilis.hr24-Nov-03 3:36 
AnswerRe: Doesn't work on Win2003 ?? Pin
Laurent Kempé24-Nov-03 3:55
Laurent Kempé24-Nov-03 3:55 
GeneralGet exception when using CamServer.dll Pin
VINH TRAN17-Nov-03 11:58
VINH TRAN17-Nov-03 11:58 
GeneralRe: Get exception when using CamServer.dll Pin
Anonymous2-Dec-03 0:47
Anonymous2-Dec-03 0:47 
GeneralRe: Get exception when using CamServer.dll Pin
mrbronz10-Feb-11 6:54
mrbronz10-Feb-11 6:54 
GeneralActive X Client Test Container and Web Reference Pin
tyounsi12-Mar-03 4:38
tyounsi12-Mar-03 4:38 
GeneralProgram using Webcam dll balloons in memory Pin
Yare7-Feb-03 4:51
Yare7-Feb-03 4:51 
GeneralRe: Program using Webcam dll balloons in memory Pin
Shaun Wilde26-Feb-03 1:23
Shaun Wilde26-Feb-03 1:23 
GeneralRe: Program using Webcam dll balloons in memory Pin
Laurent Kempé26-Feb-03 9:12
Laurent Kempé26-Feb-03 9:12 
GeneralRe: Program using Webcam dll balloons in memory Pin
Shaun Wilde26-Feb-03 11:59
Shaun Wilde26-Feb-03 11:59 
GeneralRe: Program using Webcam dll balloons in memory Pin
Janed17-Aug-04 13:30
Janed17-Aug-04 13:30 
GeneralFound a exact copy of this article.... Pin
Kant25-Oct-02 17:14
Kant25-Oct-02 17:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.