2013-04-24 42 views
6

Câu hỏi: Tôi có mã dưới đây để chụp ảnh từ webcam.Làm thế nào để sao chép hình ảnh mà không cần sử dụng clipboard?

Vấn đề của tôi là phần này:

SendMessage(hCaptureWnd, WM_CAP_COPY, 0, 0);     // copy it to the clipboard 

gì nó làm là sao chép hình ảnh từ cửa sổ vào clipboard, và sau đó tạo ra một mảng byte ra khỏi nó.

Tính năng này hoạt động - miễn là bạn không sử dụng khay nhớ tạm trong khi chương trình đang chạy.
Vấn đề là, điều này thậm chí không làm việc cho bản thân mình, như tôi đôi khi sao chép một cái gì đó trong khi Visual Studio mất lứa tuổi để bắt đầu gỡ lỗi ứng dụng web, và sau đó nó bị treo.

Vì vậy, ở đây câu hỏi của tôi:
Làm cách nào để có được hình ảnh mà không cần sử dụng khay nhớ tạm? Hoặc cụ thể hơn, làm thế nào để chuyển đổi hCaptureWnd thành System.Drawing.Image?


- Chỉnh sửa:
Tôi quên nói "không tạo tệp, tôi muốn mảng byte".
Đó là một ứng dụng web, vì vậy người dùng các ứng dụng chạy dưới không nên có quyền ghi vào hệ thống tập tin (văn bản vào một tập tin duy nhất để thử nghiệm tạm thời) ...
- End Edit:


/// <summary> 
/// Captures a frame from the webcam and returns the byte array associated 
/// with the captured image 
/// </summary> 
/// <param name="connectDelay">number of milliseconds to wait between connect 
/// and capture - necessary for some cameras that take a while to 'warm up'</param> 
/// <returns>byte array representing a bitmp or null (if error or no webcam)</returns> 
private static byte[] InternalCaptureToByteArray(int connectDelay = 500) 
{ 
    Clipboard.Clear();            // clear the clipboard 
    int hCaptureWnd = capCreateCaptureWindowA("ccWebCam", 0, 0, 0, // create the hidden capture window 
     350, 350, 0, 0); 
    SendMessage(hCaptureWnd, WM_CAP_CONNECT, 0, 0);     // send the connect message to it 
    Thread.Sleep(connectDelay);          // sleep the specified time 
    SendMessage(hCaptureWnd, WM_CAP_GET_FRAME, 0, 0);    // capture the frame 
    SendMessage(hCaptureWnd, WM_CAP_COPY, 0, 0);     // copy it to the clipboard 
    SendMessage(hCaptureWnd, WM_CAP_DISCONNECT, 0, 0);    // disconnect from the camera 
    Bitmap bitmap = (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap); // copy into bitmap 

    if (bitmap == null) 
     return null; 

    using (MemoryStream stream = new MemoryStream()) 
    { 
     bitmap.Save(stream, ImageFormat.Bmp); // get bitmap bytes 
     return stream.ToArray(); 
    } // End Using stream 

} // End Function InternalCaptureToByteArray 

Note (http://msdn.microsoft.com/en-us/library/windows/desktop/dd756879(v=vs.85).aspx):

HWND VFWAPI capCreateCaptureWindow(
    LPCTSTR lpszWindowName, 
    DWORD dwStyle, 
    int x, 
    int y, 
    int nWidth, 
    int nHeight, 
    HWND hWnd, 
    int nID 
); 


#define VFWAPI WINAPI 

typedef HANDLE HWND; 
typedef PVOID HANDLE; 
typedef void *PVOID; 

Full mã cho tài liệu tham khảo

using System; 
using System.IO; 
using System.Drawing; 
using System.Threading; 
using System.Windows.Forms; 
using System.Drawing.Imaging; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 


// http://www.creativecodedesign.com/node/66 
// http://www.barebonescoder.com/2012/01/finding-your-web-cam-with-c-directshow-net/ 
// http://www.codeproject.com/Articles/15219/WebCam-Fast-Image-Capture-Service-using-WIA 
// http://www.c-sharpcorner.com/uploadfile/yougerthen/integrate-the-web-webcam-functionality-using-C-Sharp-net-and-com-part-viii/ 
// http://forums.asp.net/t/1410057.aspx 


namespace cc.Utility 
{ 


    // bool isCaptured = ccWebCam.CaptureSTA("capture.jpg"); // Access to path C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\capture.jpg" denied. 
    // byte[] captureBytes = ccWebCam.CaptureSTA(); 

    /// <summary> 
    /// Timur Kovalev (http://www.creativecodedesign.com): 
    /// This class provides a method of capturing a webcam image via avicap32.dll api. 
    /// </summary>  
    public static class ccWebCam 
    { 
     #region *** PInvoke Stuff - methods to interact with capture window *** 

     [DllImport("user32", EntryPoint = "SendMessage")] 
     private static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam); 

     [DllImport("avicap32.dll", EntryPoint = "capCreateCaptureWindowA")] 
     private static extern int capCreateCaptureWindowA(string lpszWindowName, int dwStyle, 
      int X, int Y, int nWidth, int nHeight, int hwndParent, int nID); 


     private const int WM_CAP_CONNECT = 1034; 
     private const int WM_CAP_DISCONNECT = 1035; 
     private const int WM_CAP_COPY = 1054; 
     private const int WM_CAP_GET_FRAME = 1084; 


     #endregion 


     private static object objWebCamThreadLock = new object(); 


     //CaptureToFile(@"D:\Stefan.Steiger\Documents\Visual Studio 2010\Projects\Post_Ipag\image3.jpg"): 
     public static bool Capture(string filePath, int connectDelay = 500) 
     { 
      lock (objWebCamThreadLock) 
      { 
       return cc.Utility.ccWebCam.InternalCaptureAsFileInThread(filePath, connectDelay); 
      } 
     } // End Treadsafe Function Capture 


     public static byte[] Capture(int connectDelay = 500) 
     { 
      lock (objWebCamThreadLock) 
      { 
       return InternalCaptureToByteArrayInThread(connectDelay); 
      } 
     } // End Treadsafe Function Capture 


     /// <summary> 
     /// Captures a frame from the webcam and returns the byte array associated 
     /// with the captured image. The image is also stored in a file 
     /// </summary> 
     /// <param name="filePath">path the file wher ethe image will be saved</param> 
     /// <param name="connectDelay">number of milliseconds to wait between connect 
     /// and capture - necessary for some cameras that take a while to 'warm up'</param> 
     /// <returns>true on success, false on failure</returns> 
     private static bool InternalCaptureAsFileInThread(string filePath, int connectDelay = 500) 
     { 
      bool success = false; 
      Thread catureThread = new Thread(() => 
      { 
       success = InternalCaptureAsFile(filePath, connectDelay); 
      }); 
      catureThread.SetApartmentState(ApartmentState.STA); 
      catureThread.Start(); 
      catureThread.Join(); 
      return success; 
     } // End Function InternalCaptureAsFileInThread 


     /// <summary> 
     /// Captures a frame from the webcam and returns the byte array associated 
     /// with the captured image. The image is also stored in a file 
     /// </summary> 
     /// <param name="filePath">path the file wher ethe image will be saved</param> 
     /// <param name="connectDelay">number of milliseconds to wait between connect 
     /// and capture - necessary for some cameras that take a while to 'warm up'</param> 
     /// <returns>true on success, false on failure</returns> 
     private static bool InternalCaptureAsFile(string filePath, int connectDelay = 500) 
     { 
      byte[] capture = ccWebCam.InternalCaptureToByteArray(connectDelay); 
      if (capture != null) 
      { 
       // Access to path C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\image1.jpg" denied. 
       File.WriteAllBytes(filePath, capture); 
       return true; 
      } 
      return false; 
     } // End Function InternalCaptureAsFile 


     /// <summary> 
     /// Captures a frame from the webcam and returns the byte array associated 
     /// with the captured image. Runs in a newly-created STA thread which is 
     /// required for this method of capture 
     /// </summary> 
     /// <param name="connectDelay">number of milliseconds to wait between connect 
     /// and capture - necessary for some cameras that take a while to 'warm up'</param> 
     /// <returns>byte array representing a bitmp or null (if error or no webcam)</returns> 
     private static byte[] InternalCaptureToByteArrayInThread(int connectDelay = 500) 
     { 
      byte[] bytes = null; 
      Thread catureThread = new Thread(() => 
      { 
       bytes = InternalCaptureToByteArray(connectDelay); 
      }); 
      catureThread.SetApartmentState(ApartmentState.STA); 
      catureThread.Start(); 
      catureThread.Join(); 
      return bytes; 
     } // End Function InternalCaptureToByteArrayInThread 


     /// <summary> 
     /// Captures a frame from the webcam and returns the byte array associated 
     /// with the captured image 
     /// </summary> 
     /// <param name="connectDelay">number of milliseconds to wait between connect 
     /// and capture - necessary for some cameras that take a while to 'warm up'</param> 
     /// <returns>byte array representing a bitmp or null (if error or no webcam)</returns> 
     private static byte[] InternalCaptureToByteArray(int connectDelay = 500) 
     { 
      Clipboard.Clear();            // clear the clipboard 
      int hCaptureWnd = capCreateCaptureWindowA("ccWebCam", 0, 0, 0, // create the hidden capture window 
       350, 350, 0, 0); 
      SendMessage(hCaptureWnd, WM_CAP_CONNECT, 0, 0);     // send the connect message to it 
      Thread.Sleep(connectDelay);          // sleep the specified time 
      SendMessage(hCaptureWnd, WM_CAP_GET_FRAME, 0, 0);    // capture the frame 
      SendMessage(hCaptureWnd, WM_CAP_COPY, 0, 0);     // copy it to the clipboard 
      SendMessage(hCaptureWnd, WM_CAP_DISCONNECT, 0, 0);    // disconnect from the camera 
      Bitmap bitmap = (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap); // copy into bitmap 

      if (bitmap == null) 
       return null; 

      using (MemoryStream stream = new MemoryStream()) 
      { 
       bitmap.Save(stream, ImageFormat.Bmp); // get bitmap bytes 
       return stream.ToArray(); 
      } // End Using stream 

     } // End Function InternalCaptureToByteArray 


    } 


} 

tôi đã cố gắng như thế này, nhưng nó chỉ được một hình ảnh đen ...

[DllImport("user32.dll")] 
    static extern IntPtr GetWindowDC(IntPtr hWnd); 

    [DllImport("gdi32.dll", SetLastError = true)] 
    static extern IntPtr CreateCompatibleDC(IntPtr hdc); 

    enum TernaryRasterOperations : uint 
    { 
     /// <summary>dest = source</summary> 
     SRCCOPY = 0x00CC0020, 
     /// <summary>dest = source OR dest</summary> 
     SRCPAINT = 0x00EE0086, 
     /// <summary>dest = source AND dest</summary> 
     SRCAND = 0x008800C6, 
     /// <summary>dest = source XOR dest</summary> 
     SRCINVERT = 0x00660046, 
     /// <summary>dest = source AND (NOT dest)</summary> 
     SRCERASE = 0x00440328, 
     /// <summary>dest = (NOT source)</summary> 
     NOTSRCCOPY = 0x00330008, 
     /// <summary>dest = (NOT src) AND (NOT dest)</summary> 
     NOTSRCERASE = 0x001100A6, 
     /// <summary>dest = (source AND pattern)</summary> 
     MERGECOPY = 0x00C000CA, 
     /// <summary>dest = (NOT source) OR dest</summary> 
     MERGEPAINT = 0x00BB0226, 
     /// <summary>dest = pattern</summary> 
     PATCOPY = 0x00F00021, 
     /// <summary>dest = DPSnoo</summary> 
     PATPAINT = 0x00FB0A09, 
     /// <summary>dest = pattern XOR dest</summary> 
     PATINVERT = 0x005A0049, 
     /// <summary>dest = (NOT dest)</summary> 
     DSTINVERT = 0x00550009, 
     /// <summary>dest = BLACK</summary> 
     BLACKNESS = 0x00000042, 
     /// <summary>dest = WHITE</summary> 
     WHITENESS = 0x00FF0062, 
     /// <summary> 
     /// Capture window as seen on screen. This includes layered windows 
     /// such as WPF windows with AllowsTransparency="true" 
     /// </summary> 
     CAPTUREBLT = 0x40000000 
    } 

    [DllImport("gdi32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop); 

    [DllImport("gdi32.dll")] 
    static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); 

    [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)] 
    static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); 

    [DllImport("gdi32.dll")] 
    static extern bool DeleteDC(IntPtr hdc); 

    [DllImport("user32.dll")] 
    static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); 

    [DllImport("gdi32.dll")] 
    static extern bool DeleteObject(IntPtr hObject); 


    public static void ScreenshotWindow(IntPtr windowHandle) 
    { 
     Rect Rect = new Rect(); 

     GetWindowRect(windowHandle, ref Rect); 
     int width = Rect.Right - Rect.Left; 
     int height = Rect.Bottom - Rect.Top; 

     IntPtr windowDeviceContext = GetWindowDC(windowHandle); 
     IntPtr destDeviceContext = CreateCompatibleDC(windowDeviceContext); 
     IntPtr bitmapHandle = CreateCompatibleBitmap(windowDeviceContext, width, height); 
     IntPtr oldObject = SelectObject(destDeviceContext, bitmapHandle); 

     BitBlt(destDeviceContext, 0, 0, width, height, windowDeviceContext, 0, 0, TernaryRasterOperations.CAPTUREBLT | TernaryRasterOperations.SRCCOPY); 
     SelectObject(destDeviceContext, oldObject); 

     DeleteDC(destDeviceContext); 
     ReleaseDC(windowHandle, destDeviceContext); 


     Image screenshot = Image.FromHbitmap(bitmapHandle); 
     DeleteObject(bitmapHandle); 

     screenshot.Save("d:\\temp\\mywebcamimage.png", System.Drawing.Imaging.ImageFormat.Png); 

     /* 
     // TODO - Remove above save when it works 
     using (MemoryStream stream = new MemoryStream()) 
     { 
      screenshot.Save(stream, System.Drawing.Imaging.ImageFormat.Png); 
      return stream.ToArray(); 
     } 
     */ 
    } 

Và rồi sau này SendMessage(hCaptureWnd, WM_CAP_GET_FRAME, 0, 0);

ScreenshotWindow(new IntPtr(hCaptureWnd)); 
+0

Tôi không hiểu tại sao bạn không chỉ ... * không * sao chép hình ảnh vào clipboard và thay vào đó chuyển đổi nó trực tiếp đến một mảng byte. Có phải trình xử lý tin nhắn 'WM_CAP_COPY' có chứa logic này không? Thư viện nào cung cấp thư này? Bạn có thể ghi đè hành vi của nó không? –

+0

@Cody Grey: Thư viện đó là Windows! WinAPI! Và không, tôi không thể thay đổi cửa sổ, tôi không có mã nguồn (không phải là tôi không thể tháo rời và vá, nhưng đó là cách tiếp cận sai ở đây);) Và để trả lời câu hỏi của bạn: Bởi vì tôi không biết làm thế nào để tạo một hình ảnh từ hCaptureWnd, đó là vấn đề đặt ra ... –

+0

Hmm, tại sao tôi không thể tìm thấy bất kỳ tài liệu nào về nó? Đoán tôi ra khỏi giải đấu của tôi ở đây, tôi chưa bao giờ nghe nói về nó. –

Trả lời

1

Building Roman R. của câu trả lời:

Điểm tốt hơn của đạo đức là bạn cần phải đăng ký khung gọi lại, và sau đó gọi grabframe, và rằng bạn không thể trực tiếp đúc C kiểu char [] thành byte [] và bạn nhận dữ liệu bitmap thô - không phải bitmap và kích thước hình ảnh là 640x480, bất kể nội dung được đặt trong capCreateCaptureWindowA và lpData cần phải là IntPtr, không phải là UIntPtr, vì Marshal.Copy không có quá tải cho UIntPtr, và sử dụng WriteBitmapFile, có thể ghi dữ liệu bitmap thô vào bitmap KHÔNG sử dụng mã không an toàn hoặc ánh xạ tiêu đề tệp bitmap và bất kỳ ai đã viết Marshal.Copy đều có thể sao chép giá trị âm, bởi vì chiều dài là int, không phải là ...

Ngoài ra, cần phải xoay hình ảnh 180 độ tuổi vì bất kỳ lý do gì ...
Ngoài ra, tôi đã thay đổi hằng số WM thành tên chính xác của chúng.

SendMessage(hCaptureWnd, WM_CAP_SET_CALLBACK_FRAME, 0, capVideoStreamCallback); 
    SendMessage(hCaptureWnd, WM_CAP_GRAB_FRAME, 0, 0);    // capture the frame 

Với những điều bổ sung

// http://msdn.microsoft.com/en-us/library/windows/desktop/dd757688(v=vs.85).aspx 
    [StructLayout(LayoutKind.Sequential)] 
    private struct VIDEOHDR 
    { 
     // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx 


     // typedef unsigned char BYTE; 
     // typedef BYTE far *LPBYTE; 
     // unsigned char* lpData 


     //public byte[] lpData; // LPBYTE lpData; // Aaargh, invalid cast, not a .NET byte array... 
     public IntPtr lpData; // LPBYTE lpData; 
     public UInt32 dwBufferLength; // DWORD  dwBufferLength; 
     public UInt32 dwBytesUsed; // DWORD  dwBytesUsed; 
     public UInt32 dwTimeCaptured; // DWORD  dwTimeCaptured; 


     // typedef ULONG_PTR DWORD_PTR; 
     // #if defined(_WIN64) 
     // typedef unsigned __int64 ULONG_PTR; 
     // #else 
     // typedef unsigned long ULONG_PTR; 
     // #endif 
     public IntPtr dwUser; // DWORD_PTR dwUser; 
     public UInt32 dwFlags; // DWORD  dwFlags; 

     [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 4)] 
     public System.UIntPtr[] dwReserved; // DWORD_PTR dwReserved[4]; 

     // Does not make a difference 
     //public System.UIntPtr[] dwReserved = new System.UIntPtr[4]; // DWORD_PTR dwReserved[4]; 
    } 




    private delegate System.IntPtr capVideoStreamCallback_t(System.UIntPtr hWnd, ref VIDEOHDR lpVHdr); 
    [DllImport("user32", EntryPoint = "SendMessage")] 
    private static extern int SendMessage(int hWnd, uint Msg, int wParam, capVideoStreamCallback_t routine); 




    // http://eris.liralab.it/yarpdoc/vfw__extra__from__wine_8h.html 
    private const int WM_USER = 0x0400; // 1024 
    private const int WM_CAP_START = WM_USER; 
    private const int WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10; 
    private const int WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11; 

    private const int WM_CAP_FILE_SAVEDIB = WM_CAP_START + 25; 
    private const int WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5; 
    private const int WM_CAP_GRAB_FRAME = WM_CAP_START + 60; 
    private const int WM_CAP_EDIT_COPY = WM_CAP_START + 30; 




    // http://lists.ximian.com/pipermail/mono-devel-list/2011-March/037272.html 

    private static byte[] baSplendidIsolation; 


    private static System.IntPtr capVideoStreamCallback(System.UIntPtr hWnd, ref VIDEOHDR lpVHdr) 
    { 
     //System.Windows.Forms.MessageBox.Show("hello"); 
     //System.Windows.Forms.MessageBox.Show(lpVHdr.dwBufferLength.ToString() + " " + lpVHdr.dwBytesUsed.ToString()); 
     byte[] _imageTemp = new byte[lpVHdr.dwBufferLength]; 
     Marshal.Copy(lpVHdr.lpData, _imageTemp, 0, (int) lpVHdr.dwBufferLength); 
     //System.IO.File.WriteAllBytes(@"d:\temp\mycbfile.bmp", _imageTemp); // AAaaarg, it's raw bitmap data... 

     // http://stackoverflow.com/questions/742236/how-to-create-a-bmp-file-from-byte-in-c-sharp 
     // http://stackoverflow.com/questions/2654480/writing-bmp-image-in-pure-c-c-without-other-libraries 

     // Tsssss... 350 x 350 was the expected setting, but never mind... 
     // fortunately alex told me about WM_CAP_FILE_SAVEDIB, so I could compare to the direct output 
     int width = 640; 
     int height = 480; 
     int stride = width*3; 

     baSplendidIsolation = null; 
     baSplendidIsolation = WriteBitmapFile(@"d:\temp\mycbfilecc.bmp", width, height, _imageTemp); 

     /* 
     unsafe 
     { 
      fixed (byte* ptr = _imageTemp) 
      { 
       using (Bitmap image = new Bitmap(width, height, stride, PixelFormat.Format24bppRgb, new IntPtr(ptr))) 
       { 
        image.Save(@"d:\temp\mycbfile2.bmp"); 
       } 
      } 
     } 
     */ 

     //var hdr = (Elf32_Phdr)Marshal.PtrToStructure(ptr, typeof(Elf32_Phdr)); 
     return System.IntPtr.Zero; 
    } 


    private static byte[] WriteBitmapFile(string filename, int width, int height, byte[] imageData) 
    { 
     using (var stream = new MemoryStream(imageData)) 
     using (var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb)) 
     { 
      BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,bmp.Width, bmp.Height) 
               ,ImageLockMode.WriteOnly 
               ,bmp.PixelFormat 
      ); 

      Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length); 

      bmp.UnlockBits(bmpData); 


      if (bmp == null) 
       return null; 

      bmp.RotateFlip(RotateFlipType.Rotate180FlipNone); 
      bmp.Save(filename); // For testing only 

      using (MemoryStream ms = new MemoryStream()) 
      { 
       bmp.Save(ms, ImageFormat.Png); // get bitmap bytes 
       return ms.ToArray(); 
      } // End Using stream 

     } 

    } // End Function WriteBitmapFile 


    /// <summary> 
    /// Captures a frame from the webcam and returns the byte array associated 
    /// with the captured image 
    /// </summary> 
    /// <param name="connectDelay">number of milliseconds to wait between connect 
    /// and capture - necessary for some cameras that take a while to 'warm up'</param> 
    /// <returns>byte array representing a bitmp or null (if error or no webcam)</returns> 
    private static byte[] InternalCaptureToByteArray(int connectDelay = 500) 
    { 
     Clipboard.Clear(); 
     int hCaptureWnd = capCreateCaptureWindowA("ccWebCam", 0, 0, 0, 
      350, 350, 0, 0); // create the hidden capture window 
     SendMessage(hCaptureWnd, WM_CAP_DRIVER_CONNECT, 0, 0); // send the connect message to it 
     //SendMessage(hCaptureWnd, WM_CAP_DRIVER_CONNECT, i, 0); // i device number retval != 0 --> valid device_id 

     Thread.Sleep(connectDelay);          // sleep the specified time 
     SendMessage(hCaptureWnd, WM_CAP_SET_CALLBACK_FRAME, 0, capVideoStreamCallback); 
     SendMessage(hCaptureWnd, WM_CAP_GRAB_FRAME, 0, 0);    // capture the frame 

     //SendMessage(hCaptureWnd, WM_CAP_FILE_SAVEDIB, 0, "d:\\temp\\testmywebcamimage.bmp"); 
     //ScreenshotWindow(new IntPtr(hCaptureWnd)); 

     //SendMessage(hCaptureWnd, WM_CAP_EDIT_COPY, 0, 0); // copy it to the clipboard 


     // using (Graphics g2 = Graphics.FromHwnd(new IntPtr(hCaptureWnd))) 

     SendMessage(hCaptureWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);    // disconnect from the camera 

     return baSplendidIsolation; 

     /* 
     Bitmap bitmap = (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap); // copy into bitmap 

     if (bitmap == null) 
      return null; 

     using (MemoryStream stream = new MemoryStream()) 
     { 
      bitmap.Save(stream, ImageFormat.Bmp); // get bitmap bytes 
      return stream.ToArray(); 
     } // End Using stream 
     */ 
    } // End Function InternalCaptureToByteArray 
+0

Giá trị hex của WM_CAP_GRAB_FRAME & WM_CAP_SET_CALLBACK_FRAME bạn đã sử dụng trong mã của mình là gì. tôi đang sử dụng một cách khác như bên dưới công khai const WMint_DRIVER_CONNECT = 0x40a; công khai constint WM_CAP_DRIVER_DISCONNECT = 0x40b; const uint công khai WM_CAP_EDIT_COPY = 0x41e; const uint công khai WM_CAP_SET_PREVIEW = 0x432; const uint công khai WM_CAP_SET_OVERLAY = 0x433; const uint công khai WM_CAP_SET_PREVIEWRATE = 0x434; –

3

Bạn cần phải gửi một thông điệp khác nhau, đặc biệt WM_CAP_FILE_SAVEDIB, để lưu dữ liệu trong một tệp trên đĩa. Sau đó, bạn sẽ có thể tải nó trong một đối tượng Bitmap để xử lý thêm (tôi không biết về bất kỳ chức năng tích hợp cam-to-byte [] nào).

[DllImport("user32", EntryPoint = "SendMessage")] 
private static extern int SendMessage(
    int hWnd, uint Msg, int wParam, string strFileName); 

private const int WM_USER = 0x0400; 
private const int WM_CAP_START = WM_USER; 
private const int WM_CAP_FILE_SAVEDIB = WM_CAP_START + 25; 

//before 
SendMessage(hCaptureWnd, WM_CAP_COPY, 0, 0); 

//after 
string tempFile = Server.MapPath("~/App_Data/tempCap.bmp"); 
SendMessage(hCaptureWnd, WM_CAP_FILE_SAVEDIB, 0, tempFile); //create tempfile 
Bitmap bitmap = new Bitmap(tempFile); //read tempfile 
using (MemoryStream stream = new MemoryStream()) 
{ 
    bitmap.Save(stream, ImageFormat.Bmp); 
    return stream.ToArray(); 
} 
+0

OK, đó là dành cho tệp và những gì cho mảng byte (không tải tệp)? –

+0

Tôi không nghĩ rằng dll cung cấp một tin nhắn thẳng cam-to-byte [] – Alex

+0

Vâng tất nhiên là không, nhưng WinAPI hy vọng cung cấp một cách để chuyển đổi hCaptureWnd thành một bitmap. –

6

Không có những điều như WM_CAP_GET_FRAME. Tên chính xác của tin nhắn là WM_CAP_GRAB_FRAME và được mô tả trên MSDN.

gì nó làm là:

nhắn

Các WM_CAP_GRAB_FRAME lấy và hiển thị một khung đơn từ người lái xe chụp. Sau khi chụp, lớp phủ và xem trước bị tắt . Bạn có thể gửi thông báo này một cách rõ ràng hoặc bằng cách sử dụng macro capGrabFrame .

Để nhận dữ liệu thực tế bạn cần sử dụng frame callback as described further on MSDN. Hàm gọi lại sẽ cho bạn các byte hình ảnh, mà bạn có thể ghi vào tệp hoặc sử dụng cho bất kỳ xử lý nào mà không cần chuyển qua clipboard.

... là chức năng gọi lại được sử dụng với tính năng phát trực tuyến để tùy chọn xử lý một khung hình của video đã quay. Tên capVideoStreamCallback là trình giữ chỗ cho tên hàm do ứng dụng cung cấp.

[Và bạn có ở đó a] ... Con trỏ tới cấu trúc VIDEOHDR chứa thông tin về khung đã chụp.

Một lần nữa, API này là lựa chọn không may mắn cho việc quay video. Quá cũ, quá hạn chế.

Các vấn đề liên quan