Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Webcam API w/ Filters and Adjustments
#1
Video 
I realized I'm kind of hijacking Madscijr's thread so here's my own. This uses the Windows API Avicap32 to capture RAW pixel data. Adjust brightness with up and down arrow keys. Adjust saturation with plus and minus keys on the numpad. "N" will toggle the negative filter on and off. "S" will toggle the sepia filter on and off. "R" will reset all values to default.
Pressing space will stop the loop and capture the last frame to clipboard and to a BMP using _SaveImage.
Download the framecallback.h file to make this work: 
.h   framecallback.h (Size: 355 bytes / Downloads: 18)
Code: (Select All)
Option _Explicit
'$Console
$VersionInfo:Comments=Avicap32 webcam to memory test
'Using $VersionInfo so we get modern controls
'------------------------------------------------------------------------------------------------------------------------------
'Capture Driver Constants
Const WM_CAP_START = &H0400
Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
Const WM_CAP_EDIT_COPY = WM_CAP_START + 30
Const WM_CAP_SET_SCALE = WM_CAP_START + 53
Const WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52
Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42
Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61
Const WM_CAP_FILE_SAVEDIB = WM_CAP_START + 25
Const WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44
Const WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45
Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41
Const WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5
Const CF_DIB = &H0008

Const PM_REMOVE = &H0001
Const WS_EX_NOACTIVATE = &H08000000

Const FPS = 30 'Not recommended to set this higher than frame rate of webcam/video device

Const VIDWIDTH = 640
Const VIDHEIGHT = 480

Type BITMAPINFOHEADER
    As _Unsigned Long biSize
    As Long biWidth, biHeight
    As _Unsigned Integer biPlanes, biBitCount
    As _Unsigned Long biCompression, biSizeImage
    As Long biXPelsPerMeter, biYPelsPerMeter
    As _Unsigned Long biClrUsed, biClrImportant
End Type

Type BITMAPINFO
    As BITMAPINFOHEADER bmiHeader
End Type

Type POINT
    As Long x, y
End Type

Type MSG
    As _Offset hwnd
    As _Unsigned Long message
    $If 64BIT Then
        As String * 4 padding1
    $End If
    As _Unsigned _Offset wParam
    As _Offset lParam
    As _Unsigned Long time
    $If 64BIT Then
        As String * 4 padding2
    $End If
    As POINT pt
    As _Unsigned Long lPrivat
End Type

Declare Dynamic Library "Avicap32"
    Function CreateCaptureWindow& Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As _Offset, ByVal dwStyle As _Unsigned Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As _Offset, ByVal nId As Long)
End Declare

Declare CustomType Library
    Sub SendMessage Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function SendMessage& Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function PeekMessage& Alias "PeekMessageA" (ByVal lpMsg As _Offset, ByVal hWnd As _Offset, ByVal wMsgFilterMin As _Unsigned Long, ByVal wMsgFilterMax As _Unsigned Long, ByVal wRemoveMsg As _Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As _Offset)
    Sub DispatchMessage (ByVal lpMsg As _Offset)
    Sub DestroyWindow (ByVal hWnd As _Offset)
    Function mmioStringToFOURCC& (sz As String, ByVal uFlags As _Unsigned Long)
    Function OpenClipboard& (ByVal hWndNewOwner As _Offset)
    Function GetClipboardData%& (ByVal uFormat As _Unsigned Long)
    Sub CloseClipboard ()
    Function GlobalLock%& (ByVal hMem As _Offset)
    Function GlobalUnlock& (ByVal hMem As _Offset)
    Function LoadLibrary%& (lpLibFileName As String)
    Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
End Declare

Declare Library ".\internal\c\c_compiler\include\vfw"
End Declare

Declare Library "framecallback"
End Declare

Dim Shared As Single SATURATION_LEVEL: SATURATION_LEVEL = 1.00 '0.00 for greyscale, 1.00 for normal, and >1.00 for oversaturation
Dim Shared As Single BRIGHTNESS_LEVEL: BRIGHTNESS_LEVEL = 1.00
Dim Shared As _Byte NEGATIVE: NEGATIVE = _FALSE
Dim Shared As _Byte SEPIA: SEPIA = _FALSE

Screen _NewImage(VIDWIDTH, VIDHEIGHT, 32)
_Delay 0.2 'Just in case

_ScreenMove (_DesktopWidth / 2) - VIDWIDTH / 2, (_DesktopHeight / 2) - VIDHEIGHT / 2

Dim As String captureWinText: captureWinText = "Webcam API Test  - Child" + Chr$(0)
Dim As _Offset childID


Dim As _Offset childWin: childWin = CreateCaptureWindow(_Offset(captureWinText), WS_EX_NOACTIVATE, 0, 0, VIDWIDTH, VIDHEIGHT, _WindowHandle, childID)
If childWin = 0 Then
    Print "Couldn't create capture window."
    End
End If
_Title "Webcam API Test - Parent"
SetupDriver childWin, _TRUE 'change _FALSE to _TRUE to use default settings

Print "Previewing... Press Space bar to stop"
Print "Press escape to kill the window"
Dim Shared As _MEM frame
Dim As _Integer64 k
Dim As MSG msg
Do
    k = _KeyHit
    Select Case k
        Case 32
            Exit Do
        Case 27
            KillDriver childWin
            End
        Case 43
            If SATURATION_LEVEL < 2.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL + .10
                '_Echo _ToStr$(SATURATION_LEVEL)
            End If
        Case 45
            If SATURATION_LEVEL > 0.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL - .10
                '_Echo _ToStr$(SATURATION_LEVEL)
            End If
        Case 18432
            If BRIGHTNESS_LEVEL < 2 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL + .10
                '_Echo _ToStr$(BRIGHTNESS_LEVEL)
            End If
        Case 20480
            If BRIGHTNESS_LEVEL > 0.00 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL - .10
                '_Echo _ToStr$(BRIGHTNESS_LEVEL)
            End If
        Case Asc("R"), Asc("r") 'Reset
            BRIGHTNESS_LEVEL = 1.00
            SATURATION_LEVEL = 1.00
            NEGATIVE = _FALSE
            SEPIA = _FALSE
        Case Asc("N"), Asc("n") 'negative filter toggle
            NEGATIVE = Not NEGATIVE
        Case Asc("S"), Asc("s") 'sepia filter toggle
            SEPIA = Not SEPIA
    End Select
    If PeekMessage(_Offset(msg), 0, 0, 0, PM_REMOVE) Then
        TranslateMessage _Offset(msg)
        DispatchMessage _Offset(msg)
    Else
        GrabFrame childWin
    End If
    Screen frame.IMAGE
    _Display
    _Limit FPS
Loop
Dim As _MEM clippedFrame
'GrabFrameToClipboard childWin, clippedFrame
_ClipboardImage = frame.IMAGE
_SaveImage "myimage.bmp", frame.IMAGE, "BMP"
Print "Disconnecting Driver"
KillDriver childWin

_MemFree frame
'_MemFree clippedFrame

Sleep

Sub SetupDriver (hwnd As _Offset, defaultSource As _Byte)
    Dim As _Offset libload: libload = LoadLibrary(Command$(0))
    Dim As _Offset myCallback: myCallback = GetProcAddress(libload, "CapVideoCallback")
    If myCallback = 0 Then
        Print "Can't find callback pointer"
        End
    End If
    Dim As BITMAPINFO format
    SendMessage hwnd, WM_CAP_DRIVER_CONNECT, 0, 0
    SendMessage hwnd, WM_CAP_SET_SCALE, _FALSE, 0
    'SendMessage hwnd, WM_CAP_SET_PREVIEWRATE, 1000 / FPS, 0
    SendMessage hwnd, WM_CAP_SET_PREVIEW, _FALSE, 0

    Dim As _Unsigned Long formatSize: formatSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If Len(format) <> formatSize Then
        KillDriver hwnd
        Print "Wrong size"
        Print formatSize, Len(format)
        End
    End If

    If SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Couldn't get format"
        End
    End If
    format.bmiHeader.biSize = Len(format)
    format.bmiHeader.biWidth = VIDWIDTH
    format.bmiHeader.biHeight = VIDHEIGHT
    format.bmiHeader.biPlanes = 1
    format.bmiHeader.biBitCount = 16 'yuy2 format
    format.bmiHeader.biSizeImage = VIDWIDTH * VIDHEIGHT * 2
    format.bmiHeader.biCompression = mmioStringToFOURCC("YUY2" + Chr$(0), &H00000010) 'MUST BE YUY2 FORMAT
    If SendMessage(hwnd, WM_CAP_SET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Failed to set video format"
        End
    End If
    If defaultSource = _FALSE Then
        SendMessage hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0 'PICK YUY2!!!
        SendMessage hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0
    End If
    SendMessage hwnd, WM_CAP_GET_VIDEOFORMAT, 0, _Offset(format)
    SendMessage hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, myCallback
End Sub

Sub KillDriver (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0
    DestroyWindow hwnd
End Sub

Sub SaveBMP (hwnd As _Offset, filename As String)
    filename = filename + Chr$(0)
    SendMessage hwnd, WM_CAP_FILE_SAVEDIB, 0, _Offset(filename)
End Sub

Sub GrabFrame (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0
End Sub

Sub GrabFrameToClipboard (hwnd As _Offset, image As _MEM)
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        KillDriver hwnd
        End
    End If
    SendMessage hwnd, WM_CAP_EDIT_COPY, 0, 0
    If OpenClipboard(0) = 0 Then
        Print "Couldn't open clipboard"
        KillDriver hwnd
        End
    End If
    Dim As _Offset hDIB: hDIB = GetClipboardData(CF_DIB)
    If hDIB = 0 Then
        Print "Failed to retrieve bitmap from clipboard"
        CloseClipboard
        KillDriver hwnd
        End
    End If
    Dim As _Offset pDIB: pDIB = GlobalLock(hDIB)
    If pDIB = 0 Then
        Print "Failed to lock the clipboard"
        CloseClipboard
        KillDriver hwnd
        End
    End If
    CloseClipboard
    Dim As _MEM p: p = _Mem(pDIB, 4)
    Dim As _Unsigned Long biSize: biSize = _MemGet(p, p.OFFSET, _Unsigned Long)
    Dim As _MEM pBI: pBI = _Mem(pDIB, biSize)
    Dim As BITMAPINFO bi
    _MemGet pBI, pBI.OFFSET, bi
    _MemFree pBI
    _MemFree p
    Dim As Long bytesPerPixel: bytesPerPixel = (bi.bmiHeader.biBitCount + 7) \ 8
    Dim As Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As _MEM m: m = _Mem(pDIB + Len(bi), bi.bmiHeader.biSizeImage)
    Dim As Long y, x, t
    Dim As _Unsigned _Byte pixel24(0 To 2)
    Dim As _Unsigned _Byte pixel32(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned Long q
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i


    If bi.bmiHeader.biHeight > 0 Then
        For y = 0 To Abs(bi.bmiHeader.biHeight) - 1
            pScanLine = m.OFFSET + (y * stride)
            For x = 0 To bi.bmiHeader.biWidth - 1
                If bi.bmiHeader.biBitCount = 24 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel24()
                    q = _RGB32(pixel24(2), pixel24(1), pixel24(0))
                ElseIf bi.bmiHeader.biBitCount = 32 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel32()
                    q = _RGBA32(pixel32(2), pixel32(1), pixel32(0), pixel32(3))
                Else
                    q = _RGB32(255, 255, 255)
                End If
                PSet (x, Abs(bi.bmiHeader.biHeight) - 1 - y), q
            Next x
        Next y
    Else
        For y = 0 To Abs(bi.bmiHeader.biHeight) - 1
            pScanLine = m.OFFSET + (y * stride)
            For x = 0 To bi.bmiHeader.biWidth - 1
                If bi.bmiHeader.biBitCount = 24 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel24()
                    q = _RGB32(pixel24(2), pixel24(1), pixel24(0))
                ElseIf bi.bmiHeader.biBitCount = 32 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel32()
                    q = _RGBA32(pixel32(2), pixel32(1), pixel32(0), pixel32(3))
                Else
                    q = _RGB32(255, 255, 255)
                End If
                PSet (x, y), q
            Next
        Next
    End If
    _Dest 0
    image = _MemImage(i)
    Dim As Long a: a = GlobalUnlock(pDIB)
End Sub

Function CapVideoCallback%& (hWnd As _Offset, lpVHdr As _Offset)
    Type VIDEOHDR
        As _Offset lpData
        As _Unsigned Long dwBufferLength, dwBytesUsed, dwTimeCaptured
        As String * 4 padding1
        As _Unsigned _Offset dwUser
        As _Unsigned Long dwFlags
        As String * 4 padding2
        As _Offset dwReserved1, dwReserved2, dwReserved3, dwReserved4
    End Type
    Dim As VIDEOHDR vhdr
    Dim As _MEM pVhdr: pVhdr = _Mem(lpVHdr, Len(vhdr))
    _MemGet pVhdr, pVhdr.OFFSET, vhdr
    _MemFree pVhdr
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        'KillDriver hWnd
        'End
    End If
    Dim As BITMAPINFO bi
    SendMessage hWnd, WM_CAP_GET_VIDEOFORMAT, frameSize, _Offset(bi)
    'Print bi.bmiHeader.biHeight
    Dim As _MEM lpData: lpData = _Mem(vhdr.lpData, vhdr.dwBufferLength)
    If _MemExists(frame) Then _MemFree frame
    Dim As Long bitsPerPixel: bitsPerPixel = bi.bmiHeader.biBitCount
    Dim As Long bytesPerPixel: bytesPerPixel = (bitsPerPixel + 7) \ 8
    Dim As _Unsigned Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As Long y, x
    Dim As _Unsigned _Byte yuy2(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned _Integer64 converted
    Dim As _Unsigned _Byte r, g, b
    Dim As _Offset pixelOffset
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i
    For y = 0 To bi.bmiHeader.biHeight - 1
        pScanLine = lpData.OFFSET + (y * stride)
        For x = 0 To bi.bmiHeader.biWidth - bytesPerPixel Step bytesPerPixel
            pixelOffset = pScanLine + (x * bytesPerPixel)
            _MemGet lpData, pixelOffset, yuy2()
            converted = ConvertYUY2toRGB(yuy2())
            PSet (x, y), converted And &HFFFFFFFF
            PSet (x + 1, y), _ShR(converted, 32) And &HFFFFFFFF
        Next
    Next
    _Dest 0
    frame = _MemImage(i)
End Function


Function ConvertYUY2toRGB~&& (yuy2() As _Unsigned _Byte)
    Dim As _Unsigned _Byte r1, g1, b1, r2, g2, b2
    Dim As Double Y1, Y2, U, V

    ' Extract values
    Y1 = yuy2(0) * BRIGHTNESS_LEVEL
    Y2 = yuy2(2) * BRIGHTNESS_LEVEL
    U = (yuy2(1) - 128) * SATURATION_LEVEL
    V = (yuy2(3) - 128) * SATURATION_LEVEL

    ' Convert first pixel
    r1 = _Clamp(Y1 + 1.13983 * V, 0, 255)
    g1 = _Clamp(Y1 - 0.39465 * U - 0.58060 * V, 0, 255)
    b1 = _Clamp(Y1 + 2.03211 * U, 0, 255)

    ' Convert second pixel
    r2 = _Clamp(Y2 + 1.13983 * V, 0, 255)
    g2 = _Clamp(Y2 - 0.39465 * U - 0.58060 * V, 0, 255)
    b2 = _Clamp(Y2 + 2.03211 * U, 0, 255)

    If NEGATIVE = _TRUE Then
        r1 = 255 - r1: g1 = 255 - g1: b1 = 255 - b1
        r2 = 255 - r2: g2 = 255 - g2: b2 = 255 - b2
    End If

    If SEPIA = _TRUE Then
        Dim As _Unsigned _Byte sepia_r1, sepia_g1, sepia_b1
        Dim As _Unsigned _Byte sepia_r2, sepia_g2, sepia_b2

        sepia_r1 = _Clamp((r1 * 0.393) + (g1 * 0.769) + (b1 * 0.189), 0, 255)
        sepia_g1 = _Clamp((r1 * 0.349) + (g1 * 0.686) + (b1 * 0.168), 0, 255)
        sepia_b1 = _Clamp((r1 * 0.272) + (g1 * 0.534) + (b1 * 0.131), 0, 255)

        sepia_r2 = _Clamp((r2 * 0.393) + (g2 * 0.769) + (b2 * 0.189), 0, 255)
        sepia_g2 = _Clamp((r2 * 0.349) + (g2 * 0.686) + (b2 * 0.168), 0, 255)
        sepia_b2 = _Clamp((r2 * 0.272) + (g2 * 0.534) + (b2 * 0.131), 0, 255)
        r1 = sepia_r1
        r2 = sepia_r2
        g1 = sepia_g1
        g2 = sepia_g2
        b1 = sepia_b1
        b2 = sepia_b2
    End If

    ' Pack pixels into a single return value
    ConvertYUY2toRGB = _RGB32(r1, g1, b1) Or _ShL(_RGB32(r2, g2, b2), 32)
End Function
               
The noticing will continue
Reply
#2
Very cool! Nice work. +1
Reply
#3
Added another feature. While the camera is previewing, press "P" to capture the current frame to a uniquely named PNG. Press "C" to capture the current frame to the clipboard.

Code: (Select All)
Option _Explicit
'$Console
$VersionInfo:Comments=Avicap32 webcam to memory test
'Using $VersionInfo so we get modern controls
'------------------------------------------------------------------------------------------------------------------------------
'Capture Driver Constants
Const WM_CAP_START = &H0400
Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
Const WM_CAP_EDIT_COPY = WM_CAP_START + 30
Const WM_CAP_SET_SCALE = WM_CAP_START + 53
Const WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52
Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42
Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61
Const WM_CAP_FILE_SAVEDIB = WM_CAP_START + 25
Const WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44
Const WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45
Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41
Const WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5
Const CF_DIB = &H0008

Const PM_REMOVE = &H0001
Const WS_EX_NOACTIVATE = &H08000000

Const FPS = 30 'Not recommended to set this higher than frame rate of webcam/video device

Const VIDWIDTH = 640
Const VIDHEIGHT = 480

Type BITMAPINFOHEADER
    As _Unsigned Long biSize
    As Long biWidth, biHeight
    As _Unsigned Integer biPlanes, biBitCount
    As _Unsigned Long biCompression, biSizeImage
    As Long biXPelsPerMeter, biYPelsPerMeter
    As _Unsigned Long biClrUsed, biClrImportant
End Type

Type BITMAPINFO
    As BITMAPINFOHEADER bmiHeader
End Type

Type POINT
    As Long x, y
End Type

Type MSG
    As _Offset hwnd
    As _Unsigned Long message
    $If 64BIT Then
        As String * 4 padding1
    $End If
    As _Unsigned _Offset wParam
    As _Offset lParam
    As _Unsigned Long time
    $If 64BIT Then
        As String * 4 padding2
    $End If
    As POINT pt
    As _Unsigned Long lPrivat
End Type

Declare Dynamic Library "Avicap32"
    Function CreateCaptureWindow& Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As _Offset, ByVal dwStyle As _Unsigned Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As _Offset, ByVal nId As Long)
End Declare

Declare CustomType Library
    Sub SendMessage Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function SendMessage& Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function PeekMessage& Alias "PeekMessageA" (ByVal lpMsg As _Offset, ByVal hWnd As _Offset, ByVal wMsgFilterMin As _Unsigned Long, ByVal wMsgFilterMax As _Unsigned Long, ByVal wRemoveMsg As _Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As _Offset)
    Sub DispatchMessage (ByVal lpMsg As _Offset)
    Sub DestroyWindow (ByVal hWnd As _Offset)
    Function mmioStringToFOURCC& (sz As String, ByVal uFlags As _Unsigned Long)
    Function OpenClipboard& (ByVal hWndNewOwner As _Offset)
    Function GetClipboardData%& (ByVal uFormat As _Unsigned Long)
    Sub CloseClipboard ()
    Function GlobalLock%& (ByVal hMem As _Offset)
    Function GlobalUnlock& (ByVal hMem As _Offset)
    Function LoadLibrary%& (lpLibFileName As String)
    Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
End Declare

Declare Library ".\internal\c\c_compiler\include\vfw"
End Declare

Declare Library "framecallback"
End Declare

Dim Shared As Single SATURATION_LEVEL: SATURATION_LEVEL = 1.00 '0.00 for greyscale, 1.00 for normal, and >1.00 for oversaturation
Dim Shared As Single BRIGHTNESS_LEVEL: BRIGHTNESS_LEVEL = 1.00
Dim Shared As _Byte NEGATIVE: NEGATIVE = _FALSE
Dim Shared As _Byte SEPIA: SEPIA = _FALSE

Screen _NewImage(VIDWIDTH, VIDHEIGHT, 32)
_Delay 0.2 'Just in case

_ScreenMove (_DesktopWidth / 2) - VIDWIDTH / 2, (_DesktopHeight / 2) - VIDHEIGHT / 2

Dim As String captureWinText: captureWinText = "Webcam API Test  - Child" + Chr$(0)
Dim As _Offset childID


Dim As _Offset childWin: childWin = CreateCaptureWindow(_Offset(captureWinText), WS_EX_NOACTIVATE, 0, 0, VIDWIDTH, VIDHEIGHT, _WindowHandle, childID)
If childWin = 0 Then
    Print "Couldn't create capture window."
    End
End If
_Title "Webcam API Test - Parent"
SetupDriver childWin, _TRUE 'change _FALSE to _TRUE to use default settings

Print "Previewing... Press Space bar to stop"
Print "Press escape to kill the window"
Dim Shared As _MEM frame
Dim As _Integer64 k
Dim As MSG msg
Dim As Long i
Do
    k = _KeyHit
    Select Case k
        Case 32
            Exit Do
        Case 27
            KillDriver childWin
            End
        Case 43
            If SATURATION_LEVEL < 2.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL + .10
                '_Echo _ToStr$(SATURATION_LEVEL)
            End If
        Case 45
            If SATURATION_LEVEL > 0.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL - .10
                '_Echo _ToStr$(SATURATION_LEVEL)
            End If
        Case 18432
            If BRIGHTNESS_LEVEL < 2 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL + .10
                '_Echo _ToStr$(BRIGHTNESS_LEVEL)
            End If
        Case 20480
            If BRIGHTNESS_LEVEL > 0.00 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL - .10
                '_Echo _ToStr$(BRIGHTNESS_LEVEL)
            End If
        Case Asc("R"), Asc("r") 'Reset
            BRIGHTNESS_LEVEL = 1.00
            SATURATION_LEVEL = 1.00
            NEGATIVE = _FALSE
            SEPIA = _FALSE
        Case Asc("N"), Asc("n") 'negative filter toggle
            NEGATIVE = Not NEGATIVE
        Case Asc("S"), Asc("s") 'sepia filter toggle
            SEPIA = Not SEPIA
        Case Asc("P"), Asc("p")
            If _FileExists("capture(" + _ToStr$(i) + ").png") Then
                While _FileExists("capture(" + _ToStr$(i) + ").png")
                    i = i + 1
                Wend
            End If
            _SaveImage "capture(" + _ToStr$(i) + ").png", frame.IMAGE, "PNG"
            i = i + 1
        Case Asc("C"), Asc("c")
            _ClipboardImage = frame.IMAGE
    End Select
    If PeekMessage(_Offset(msg), 0, 0, 0, PM_REMOVE) Then
        TranslateMessage _Offset(msg)
        DispatchMessage _Offset(msg)
    Else
        GrabFrame childWin
    End If
    Screen frame.IMAGE
    _Display
    _Limit FPS
Loop
Dim As _MEM clippedFrame
Print "Disconnecting Driver"
KillDriver childWin

_MemFree frame
'_MemFree clippedFrame

Sleep

Sub SetupDriver (hwnd As _Offset, defaultSource As _Byte)
    Dim As _Offset libload: libload = LoadLibrary(Command$(0))
    Dim As _Offset myCallback: myCallback = GetProcAddress(libload, "CapVideoCallback")
    If myCallback = 0 Then
        Print "Can't find callback pointer"
        End
    End If
    Dim As BITMAPINFO format
    SendMessage hwnd, WM_CAP_DRIVER_CONNECT, 0, 0
    SendMessage hwnd, WM_CAP_SET_SCALE, _FALSE, 0
    'SendMessage hwnd, WM_CAP_SET_PREVIEWRATE, 1000 / FPS, 0
    SendMessage hwnd, WM_CAP_SET_PREVIEW, _FALSE, 0

    Dim As _Unsigned Long formatSize: formatSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If Len(format) <> formatSize Then
        KillDriver hwnd
        Print "Wrong size"
        Print formatSize, Len(format)
        End
    End If

    If SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Couldn't get format"
        End
    End If
    format.bmiHeader.biSize = Len(format)
    format.bmiHeader.biWidth = VIDWIDTH
    format.bmiHeader.biHeight = VIDHEIGHT
    format.bmiHeader.biPlanes = 1
    format.bmiHeader.biBitCount = 16 'yuy2 format
    format.bmiHeader.biSizeImage = VIDWIDTH * VIDHEIGHT * 2
    format.bmiHeader.biCompression = mmioStringToFOURCC("YUY2" + Chr$(0), &H00000010) 'MUST BE YUY2 FORMAT
    If SendMessage(hwnd, WM_CAP_SET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Failed to set video format"
        End
    End If
    If defaultSource = _FALSE Then
        SendMessage hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0 'PICK YUY2!!!
        SendMessage hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0
    End If
    SendMessage hwnd, WM_CAP_GET_VIDEOFORMAT, 0, _Offset(format)
    SendMessage hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, myCallback
End Sub

Sub KillDriver (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0
    DestroyWindow hwnd
End Sub

Sub SaveBMP (hwnd As _Offset, filename As String)
    filename = filename + Chr$(0)
    SendMessage hwnd, WM_CAP_FILE_SAVEDIB, 0, _Offset(filename)
End Sub

Sub GrabFrame (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0
End Sub

Sub GrabFrameToClipboard (hwnd As _Offset, image As _MEM)
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        KillDriver hwnd
        End
    End If
    SendMessage hwnd, WM_CAP_EDIT_COPY, 0, 0
    If OpenClipboard(0) = 0 Then
        Print "Couldn't open clipboard"
        KillDriver hwnd
        End
    End If
    Dim As _Offset hDIB: hDIB = GetClipboardData(CF_DIB)
    If hDIB = 0 Then
        Print "Failed to retrieve bitmap from clipboard"
        CloseClipboard
        KillDriver hwnd
        End
    End If
    Dim As _Offset pDIB: pDIB = GlobalLock(hDIB)
    If pDIB = 0 Then
        Print "Failed to lock the clipboard"
        CloseClipboard
        KillDriver hwnd
        End
    End If
    CloseClipboard
    Dim As _MEM p: p = _Mem(pDIB, 4)
    Dim As _Unsigned Long biSize: biSize = _MemGet(p, p.OFFSET, _Unsigned Long)
    Dim As _MEM pBI: pBI = _Mem(pDIB, biSize)
    Dim As BITMAPINFO bi
    _MemGet pBI, pBI.OFFSET, bi
    _MemFree pBI
    _MemFree p
    Dim As Long bytesPerPixel: bytesPerPixel = (bi.bmiHeader.biBitCount + 7) \ 8
    Dim As Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As _MEM m: m = _Mem(pDIB + Len(bi), bi.bmiHeader.biSizeImage)
    Dim As Long y, x, t
    Dim As _Unsigned _Byte pixel24(0 To 2)
    Dim As _Unsigned _Byte pixel32(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned Long q
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i


    If bi.bmiHeader.biHeight > 0 Then
        For y = 0 To Abs(bi.bmiHeader.biHeight) - 1
            pScanLine = m.OFFSET + (y * stride)
            For x = 0 To bi.bmiHeader.biWidth - 1
                If bi.bmiHeader.biBitCount = 24 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel24()
                    q = _RGB32(pixel24(2), pixel24(1), pixel24(0))
                ElseIf bi.bmiHeader.biBitCount = 32 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel32()
                    q = _RGBA32(pixel32(2), pixel32(1), pixel32(0), pixel32(3))
                Else
                    q = _RGB32(255, 255, 255)
                End If
                PSet (x, Abs(bi.bmiHeader.biHeight) - 1 - y), q
            Next x
        Next y
    Else
        For y = 0 To Abs(bi.bmiHeader.biHeight) - 1
            pScanLine = m.OFFSET + (y * stride)
            For x = 0 To bi.bmiHeader.biWidth - 1
                If bi.bmiHeader.biBitCount = 24 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel24()
                    q = _RGB32(pixel24(2), pixel24(1), pixel24(0))
                ElseIf bi.bmiHeader.biBitCount = 32 Then
                    _MemGet m, pScanLine + (x * bytesPerPixel), pixel32()
                    q = _RGBA32(pixel32(2), pixel32(1), pixel32(0), pixel32(3))
                Else
                    q = _RGB32(255, 255, 255)
                End If
                PSet (x, y), q
            Next
        Next
    End If
    _Dest 0
    image = _MemImage(i)
    Dim As Long a: a = GlobalUnlock(pDIB)
End Sub

Function CapVideoCallback%& (hWnd As _Offset, lpVHdr As _Offset)
    Type VIDEOHDR
        As _Offset lpData
        As _Unsigned Long dwBufferLength, dwBytesUsed, dwTimeCaptured
        As String * 4 padding1
        As _Unsigned _Offset dwUser
        As _Unsigned Long dwFlags
        As String * 4 padding2
        As _Offset dwReserved1, dwReserved2, dwReserved3, dwReserved4
    End Type
    Dim As VIDEOHDR vhdr
    Dim As _MEM pVhdr: pVhdr = _Mem(lpVHdr, Len(vhdr))
    _MemGet pVhdr, pVhdr.OFFSET, vhdr
    _MemFree pVhdr
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        'KillDriver hWnd
        'End
    End If
    Dim As BITMAPINFO bi
    SendMessage hWnd, WM_CAP_GET_VIDEOFORMAT, frameSize, _Offset(bi)
    'Print bi.bmiHeader.biHeight
    Dim As _MEM lpData: lpData = _Mem(vhdr.lpData, vhdr.dwBufferLength)
    If _MemExists(frame) Then _MemFree frame
    Dim As Long bitsPerPixel: bitsPerPixel = bi.bmiHeader.biBitCount
    Dim As Long bytesPerPixel: bytesPerPixel = (bitsPerPixel + 7) \ 8
    Dim As _Unsigned Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As Long y, x
    Dim As _Unsigned _Byte yuy2(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned _Integer64 converted
    Dim As _Unsigned _Byte r, g, b
    Dim As _Offset pixelOffset
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i
    For y = 0 To bi.bmiHeader.biHeight - 1
        pScanLine = lpData.OFFSET + (y * stride)
        For x = 0 To bi.bmiHeader.biWidth - bytesPerPixel Step bytesPerPixel
            pixelOffset = pScanLine + (x * bytesPerPixel)
            _MemGet lpData, pixelOffset, yuy2()
            converted = ConvertYUY2toRGB(yuy2())
            PSet (x, y), converted And &HFFFFFFFF
            PSet (x + 1, y), _ShR(converted, 32) And &HFFFFFFFF
        Next
    Next
    _Dest 0
    frame = _MemImage(i)
End Function


Function ConvertYUY2toRGB~&& (yuy2() As _Unsigned _Byte)
    Dim As _Unsigned _Byte r1, g1, b1, r2, g2, b2
    Dim As Double Y1, Y2, U, V

    ' Extract values
    Y1 = yuy2(0) * BRIGHTNESS_LEVEL
    Y2 = yuy2(2) * BRIGHTNESS_LEVEL
    U = (yuy2(1) - 128) * SATURATION_LEVEL
    V = (yuy2(3) - 128) * SATURATION_LEVEL

    ' Convert first pixel
    r1 = _Clamp(Y1 + 1.13983 * V, 0, 255)
    g1 = _Clamp(Y1 - 0.39465 * U - 0.58060 * V, 0, 255)
    b1 = _Clamp(Y1 + 2.03211 * U, 0, 255)

    ' Convert second pixel
    r2 = _Clamp(Y2 + 1.13983 * V, 0, 255)
    g2 = _Clamp(Y2 - 0.39465 * U - 0.58060 * V, 0, 255)
    b2 = _Clamp(Y2 + 2.03211 * U, 0, 255)

    If NEGATIVE = _TRUE Then
        r1 = 255 - r1: g1 = 255 - g1: b1 = 255 - b1
        r2 = 255 - r2: g2 = 255 - g2: b2 = 255 - b2
    End If

    If SEPIA = _TRUE Then
        Dim As _Unsigned _Byte sepia_r1, sepia_g1, sepia_b1
        Dim As _Unsigned _Byte sepia_r2, sepia_g2, sepia_b2

        sepia_r1 = _Clamp((r1 * 0.393) + (g1 * 0.769) + (b1 * 0.189), 0, 255)
        sepia_g1 = _Clamp((r1 * 0.349) + (g1 * 0.686) + (b1 * 0.168), 0, 255)
        sepia_b1 = _Clamp((r1 * 0.272) + (g1 * 0.534) + (b1 * 0.131), 0, 255)

        sepia_r2 = _Clamp((r2 * 0.393) + (g2 * 0.769) + (b2 * 0.189), 0, 255)
        sepia_g2 = _Clamp((r2 * 0.349) + (g2 * 0.686) + (b2 * 0.168), 0, 255)
        sepia_b2 = _Clamp((r2 * 0.272) + (g2 * 0.534) + (b2 * 0.131), 0, 255)
        r1 = sepia_r1
        r2 = sepia_r2
        g1 = sepia_g1
        g2 = sepia_g2
        b1 = sepia_b1
        b2 = sepia_b2
    End If

    ' Pack pixels into a single return value
    ConvertYUY2toRGB = _RGB32(r1, g1, b1) Or _ShL(_RGB32(r2, g2, b2), 32)
End Function
The noticing will continue
Reply
#4
Added the ability to flip the video horizontally with "H" and vertically with "V". Also, removed old Clipboard and Save functions as those are not necessary.

Code: (Select All)
Option _Explicit
'$Console
$VersionInfo:Comments=Avicap32 webcam to memory test
'Using $VersionInfo so we get modern controls
'------------------------------------------------------------------------------------------------------------------------------
'Capture Driver Constants
Const WM_CAP_START = &H0400
Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
Const WM_CAP_SET_SCALE = WM_CAP_START + 53
Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42
Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61
Const WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44
Const WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45
Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41
Const WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5
Const CF_DIB = &H0008

Const PM_REMOVE = &H0001
Const WS_EX_NOACTIVATE = &H08000000

Const FPS = 30 'Not recommended to set this higher than frame rate of webcam/video device

Const VIDWIDTH = 640
Const VIDHEIGHT = 480

Type BITMAPINFOHEADER
    As _Unsigned Long biSize
    As Long biWidth, biHeight
    As _Unsigned Integer biPlanes, biBitCount
    As _Unsigned Long biCompression, biSizeImage
    As Long biXPelsPerMeter, biYPelsPerMeter
    As _Unsigned Long biClrUsed, biClrImportant
End Type

Type BITMAPINFO
    As BITMAPINFOHEADER bmiHeader
End Type

Type POINT
    As Long x, y
End Type

Type MSG
    As _Offset hwnd
    As _Unsigned Long message
    $If 64BIT Then
        As String * 4 padding1
    $End If
    As _Unsigned _Offset wParam
    As _Offset lParam
    As _Unsigned Long time
    $If 64BIT Then
        As String * 4 padding2
    $End If
    As POINT pt
    As _Unsigned Long lPrivat
End Type

Declare Dynamic Library "Avicap32"
    Function CreateCaptureWindow& Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As _Offset, ByVal dwStyle As _Unsigned Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As _Offset, ByVal nId As Long)
End Declare

Declare CustomType Library
    Sub SendMessage Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function SendMessage& Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function PeekMessage& Alias "PeekMessageA" (ByVal lpMsg As _Offset, ByVal hWnd As _Offset, ByVal wMsgFilterMin As _Unsigned Long, ByVal wMsgFilterMax As _Unsigned Long, ByVal wRemoveMsg As _Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As _Offset)
    Sub DispatchMessage (ByVal lpMsg As _Offset)
    Sub DestroyWindow (ByVal hWnd As _Offset)
    Function mmioStringToFOURCC& (sz As String, ByVal uFlags As _Unsigned Long)
    Function OpenClipboard& (ByVal hWndNewOwner As _Offset)
    Function GetClipboardData%& (ByVal uFormat As _Unsigned Long)
    Sub CloseClipboard ()
    Function GlobalLock%& (ByVal hMem As _Offset)
    Function GlobalUnlock& (ByVal hMem As _Offset)
    Function LoadLibrary%& (lpLibFileName As String)
    Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
End Declare

Declare Library ".\internal\c\c_compiler\include\vfw"
End Declare

Declare Library "framecallback"
End Declare

Dim Shared As Single SATURATION_LEVEL: SATURATION_LEVEL = 1.00 '0.00 for greyscale, 1.00 for normal, and >1.00 for oversaturation
Dim Shared As Single BRIGHTNESS_LEVEL: BRIGHTNESS_LEVEL = 1.00
Dim Shared As _Byte NEGATIVE: NEGATIVE = _FALSE
Dim Shared As _Byte SEPIA: SEPIA = _FALSE
Dim Shared As _Byte FLIPPED_H: FLIPPED_H = _FALSE
Dim Shared As _Byte FLIPPED_V: FLIPPED_V = _FALSE

Screen _NewImage(VIDWIDTH, VIDHEIGHT, 32)
_Delay 0.2 'Just in case

_ScreenMove (_DesktopWidth / 2) - VIDWIDTH / 2, (_DesktopHeight / 2) - VIDHEIGHT / 2

Dim As String captureWinText: captureWinText = "Webcam API Test  - Child" + Chr$(0)
Dim As _Offset childID


Dim As _Offset childWin: childWin = CreateCaptureWindow(_Offset(captureWinText), WS_EX_NOACTIVATE, 0, 0, VIDWIDTH, VIDHEIGHT, _WindowHandle, childID)
If childWin = 0 Then
    Print "Couldn't create capture window."
    End
End If
_Title "Webcam API Test - Parent"
SetupDriver childWin, _TRUE 'change _FALSE to _TRUE to use default settings

Print "Previewing... Press Space bar to stop"
Print "Press escape to kill the window"
Dim Shared As _MEM frame
Dim As _Integer64 k
Dim As MSG msg
Dim As Long i
Do
    k = _KeyHit
    Select Case k
        Case 32
            Exit Do
        Case 27
            KillDriver childWin
            End
        Case 43
            If SATURATION_LEVEL < 2.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL + .10
                '_Echo _ToStr$(SATURATION_LEVEL)
            End If
        Case 45
            If SATURATION_LEVEL > 0.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL - .10
                '_Echo _ToStr$(SATURATION_LEVEL)
            End If
        Case 18432
            If BRIGHTNESS_LEVEL < 2 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL + .10
                '_Echo _ToStr$(BRIGHTNESS_LEVEL)
            End If
        Case 20480
            If BRIGHTNESS_LEVEL > 0.00 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL - .10
                '_Echo _ToStr$(BRIGHTNESS_LEVEL)
            End If
        Case Asc("R"), Asc("r") 'Reset
            BRIGHTNESS_LEVEL = 1.00
            SATURATION_LEVEL = 1.00
            NEGATIVE = _FALSE
            SEPIA = _FALSE
            FLIPPED_H = _FALSE
            FLIPPED_V = _FALSE
        Case Asc("N"), Asc("n") 'negative filter toggle
            NEGATIVE = Not NEGATIVE
        Case Asc("S"), Asc("s") 'sepia filter toggle
            SEPIA = Not SEPIA
        Case Asc("P"), Asc("p")
            If _FileExists("capture(" + _ToStr$(i) + ").png") Then
                While _FileExists("capture(" + _ToStr$(i) + ").png")
                    i = i + 1
                Wend
            End If
            _SaveImage "capture(" + _ToStr$(i) + ").png", frame.IMAGE, "PNG"
            i = i + 1
        Case Asc("C"), Asc("c")
            _ClipboardImage = frame.IMAGE
        Case Asc("H"), Asc("h")
            FLIPPED_H = Not FLIPPED_H
        Case Asc("V"), Asc("v")
            FLIPPED_V = Not FLIPPED_V
    End Select
    If PeekMessage(_Offset(msg), 0, 0, 0, PM_REMOVE) Then
        TranslateMessage _Offset(msg)
        DispatchMessage _Offset(msg)
    Else
        GrabFrame childWin
    End If
    _PutImage , frame.IMAGE, _Dest
    _Display
    _Limit FPS
Loop
Dim As _MEM clippedFrame
Print "Disconnecting Driver"
KillDriver childWin

_MemFree frame
'_MemFree clippedFrame

'Sleep

Sub SetupDriver (hwnd As _Offset, defaultSource As _Byte)
    Dim As _Offset libload: libload = LoadLibrary(Command$(0))
    Dim As _Offset myCallback: myCallback = GetProcAddress(libload, "CapVideoCallback")
    If myCallback = 0 Then
        Print "Can't find callback pointer"
        End
    End If
    Dim As BITMAPINFO format
    SendMessage hwnd, WM_CAP_DRIVER_CONNECT, 0, 0
    SendMessage hwnd, WM_CAP_SET_SCALE, _FALSE, 0
    SendMessage hwnd, WM_CAP_SET_PREVIEW, _FALSE, 0

    Dim As _Unsigned Long formatSize: formatSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If Len(format) <> formatSize Then
        KillDriver hwnd
        Print "Wrong size"
        Print formatSize, Len(format)
        End
    End If

    If SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Couldn't get format"
        End
    End If
    format.bmiHeader.biSize = Len(format)
    format.bmiHeader.biWidth = VIDWIDTH
    format.bmiHeader.biHeight = VIDHEIGHT
    format.bmiHeader.biPlanes = 1
    format.bmiHeader.biBitCount = 16 'yuy2 format
    format.bmiHeader.biSizeImage = VIDWIDTH * VIDHEIGHT * 2
    format.bmiHeader.biCompression = mmioStringToFOURCC("YUY2" + Chr$(0), &H00000010) 'MUST BE YUY2 FORMAT
    If SendMessage(hwnd, WM_CAP_SET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Failed to set video format"
        End
    End If
    If defaultSource = _FALSE Then
        SendMessage hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0 'PICK YUY2!!!
        SendMessage hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0
    End If
    SendMessage hwnd, WM_CAP_GET_VIDEOFORMAT, 0, _Offset(format)
    SendMessage hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, myCallback
End Sub

Sub KillDriver (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0
    DestroyWindow hwnd
End Sub

Sub GrabFrame (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0
End Sub

Function CapVideoCallback%& (hWnd As _Offset, lpVHdr As _Offset)
    Type VIDEOHDR
        As _Offset lpData
        As _Unsigned Long dwBufferLength, dwBytesUsed, dwTimeCaptured
        As String * 4 padding1
        As _Unsigned _Offset dwUser
        As _Unsigned Long dwFlags
        As String * 4 padding2
        As _Offset dwReserved1, dwReserved2, dwReserved3, dwReserved4
    End Type
    Dim As VIDEOHDR vhdr
    Dim As _MEM pVhdr: pVhdr = _Mem(lpVHdr, Len(vhdr))
    _MemGet pVhdr, pVhdr.OFFSET, vhdr
    _MemFree pVhdr
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        'KillDriver hWnd
        'End
    End If
    Dim As BITMAPINFO bi
    SendMessage hWnd, WM_CAP_GET_VIDEOFORMAT, frameSize, _Offset(bi)
    'Print bi.bmiHeader.biHeight
    Dim As _MEM lpData: lpData = _Mem(vhdr.lpData, vhdr.dwBufferLength)
    If _MemExists(frame) Then _MemFree frame
    Dim As Long bitsPerPixel: bitsPerPixel = bi.bmiHeader.biBitCount
    Dim As Long bytesPerPixel: bytesPerPixel = (bitsPerPixel + 7) \ 8
    Dim As _Unsigned Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As Long y, x
    Dim As _Unsigned _Byte yuy2(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned _Integer64 converted
    Dim As _Unsigned _Byte r, g, b
    Dim As _Offset pixelOffset
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i
    For y = 0 To bi.bmiHeader.biHeight - 1
        pScanLine = lpData.OFFSET + (y * stride)
        For x = 0 To bi.bmiHeader.biWidth - bytesPerPixel Step bytesPerPixel
            pixelOffset = pScanLine + (x * bytesPerPixel)
            _MemGet lpData, pixelOffset, yuy2()
            converted = ConvertYUY2toRGB(yuy2())
            PSet (x, y), converted And &HFFFFFFFF
            PSet (x + 1, y), _ShR(converted, 32) And &HFFFFFFFF
        Next
    Next
    If FLIPPED_H Then
        Dim As Long hi: hi = _CopyImage(i)
        _PutImage , hi, i, (bi.bmiHeader.biWidth - 1, 0)-(0, bi.bmiHeader.biHeight - 1)
        _FreeImage hi
    End If
    If FLIPPED_V Then
        Dim As Long vi: vi = _CopyImage(i)
        _PutImage , vi, i, (bi.bmiHeader.biWidth - 1, bi.bmiHeader.biHeight - 1)-(0, 0)
        _FreeImage vi
    End If
    _Dest 0
    frame = _MemImage(i)
End Function


Function ConvertYUY2toRGB~&& (yuy2() As _Unsigned _Byte)
    Dim As _Unsigned _Byte r1, g1, b1, r2, g2, b2
    Dim As Double Y1, Y2, U, V

    ' Extract values
    Y1 = yuy2(0) * BRIGHTNESS_LEVEL
    Y2 = yuy2(2) * BRIGHTNESS_LEVEL
    U = (yuy2(1) - 128) * SATURATION_LEVEL
    V = (yuy2(3) - 128) * SATURATION_LEVEL

    ' Convert first pixel
    r1 = _Clamp(Y1 + 1.13983 * V, 0, 255)
    g1 = _Clamp(Y1 - 0.39465 * U - 0.58060 * V, 0, 255)
    b1 = _Clamp(Y1 + 2.03211 * U, 0, 255)

    ' Convert second pixel
    r2 = _Clamp(Y2 + 1.13983 * V, 0, 255)
    g2 = _Clamp(Y2 - 0.39465 * U - 0.58060 * V, 0, 255)
    b2 = _Clamp(Y2 + 2.03211 * U, 0, 255)

    If NEGATIVE = _TRUE Then
        r1 = 255 - r1: g1 = 255 - g1: b1 = 255 - b1
        r2 = 255 - r2: g2 = 255 - g2: b2 = 255 - b2
    End If

    If SEPIA = _TRUE Then
        Dim As _Unsigned _Byte sepia_r1, sepia_g1, sepia_b1
        Dim As _Unsigned _Byte sepia_r2, sepia_g2, sepia_b2

        sepia_r1 = _Clamp((r1 * 0.393) + (g1 * 0.769) + (b1 * 0.189), 0, 255)
        sepia_g1 = _Clamp((r1 * 0.349) + (g1 * 0.686) + (b1 * 0.168), 0, 255)
        sepia_b1 = _Clamp((r1 * 0.272) + (g1 * 0.534) + (b1 * 0.131), 0, 255)

        sepia_r2 = _Clamp((r2 * 0.393) + (g2 * 0.769) + (b2 * 0.189), 0, 255)
        sepia_g2 = _Clamp((r2 * 0.349) + (g2 * 0.686) + (b2 * 0.168), 0, 255)
        sepia_b2 = _Clamp((r2 * 0.272) + (g2 * 0.534) + (b2 * 0.131), 0, 255)
        r1 = sepia_r1
        r2 = sepia_r2
        g1 = sepia_g1
        g2 = sepia_g2
        b1 = sepia_b1
        b2 = sepia_b2
    End If

    ' Pack pixels into a single return value
    ConvertYUY2toRGB = _RGB32(r1, g1, b1) Or _ShL(_RGB32(r2, g2, b2), 32)
End Function

   
The noticing will continue
Reply
#5
Added the ability to individually increase and decrease the R, G, and B values. Hit "r" to decrease, hold shift and press "R" to increase. And so on and so forth, etc.

Code: (Select All)
Option _Explicit
'$Console
$VersionInfo:Comments=Avicap32 webcam to memory test
'Using $VersionInfo so we get modern controls
'------------------------------------------------------------------------------------------------------------------------------
'Capture Driver Constants
Const WM_CAP_START = &H0400
Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
Const WM_CAP_SET_SCALE = WM_CAP_START + 53
Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42
Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61
Const WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44
Const WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45
Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41
Const WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5
Const CF_DIB = &H0008

Const PM_REMOVE = &H0001
Const WS_EX_NOACTIVATE = &H08000000

Const FPS = 30 'Not recommended to set this higher than frame rate of webcam/video device

Const VIDWIDTH = 640
Const VIDHEIGHT = 480

Type BITMAPINFOHEADER
    As _Unsigned Long biSize
    As Long biWidth, biHeight
    As _Unsigned Integer biPlanes, biBitCount
    As _Unsigned Long biCompression, biSizeImage
    As Long biXPelsPerMeter, biYPelsPerMeter
    As _Unsigned Long biClrUsed, biClrImportant
End Type

Type BITMAPINFO
    As BITMAPINFOHEADER bmiHeader
End Type

Type POINT
    As Long x, y
End Type

Type MSG
    As _Offset hwnd
    As _Unsigned Long message
    $If 64BIT Then
        As String * 4 padding1
    $End If
    As _Unsigned _Offset wParam
    As _Offset lParam
    As _Unsigned Long time
    $If 64BIT Then
        As String * 4 padding2
    $End If
    As POINT pt
    As _Unsigned Long lPrivat
End Type

Declare Dynamic Library "Avicap32"
    Function CreateCaptureWindow& Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As _Offset, ByVal dwStyle As _Unsigned Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As _Offset, ByVal nId As Long)
End Declare

Declare CustomType Library
    Sub SendMessage Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function SendMessage& Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function PeekMessage& Alias "PeekMessageA" (ByVal lpMsg As _Offset, ByVal hWnd As _Offset, ByVal wMsgFilterMin As _Unsigned Long, ByVal wMsgFilterMax As _Unsigned Long, ByVal wRemoveMsg As _Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As _Offset)
    Sub DispatchMessage (ByVal lpMsg As _Offset)
    Sub DestroyWindow (ByVal hWnd As _Offset)
    Function mmioStringToFOURCC& (sz As String, ByVal uFlags As _Unsigned Long)
    Function OpenClipboard& (ByVal hWndNewOwner As _Offset)
    Function GetClipboardData%& (ByVal uFormat As _Unsigned Long)
    Sub CloseClipboard ()
    Function GlobalLock%& (ByVal hMem As _Offset)
    Function GlobalUnlock& (ByVal hMem As _Offset)
    Function LoadLibrary%& (lpLibFileName As String)
    Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
End Declare

Declare Library ".\internal\c\c_compiler\include\vfw"
End Declare

Declare Library "framecallback"
End Declare

Dim Shared As Single SATURATION_LEVEL: SATURATION_LEVEL = 1.00 '0.00 for greyscale, 1.00 for normal, and >1.00 for oversaturation
Dim Shared As Single BRIGHTNESS_LEVEL: BRIGHTNESS_LEVEL = 1.00
Dim Shared As _Byte NEGATIVE: NEGATIVE = _FALSE
Dim Shared As _Byte SEPIA: SEPIA = _FALSE
Dim Shared As _Byte FLIPPED_H: FLIPPED_H = _FALSE
Dim Shared As _Byte FLIPPED_V: FLIPPED_V = _FALSE
Dim Shared As Single COLOR_TEMP_WARM: COLOR_TEMP_WARM = 1.00
Dim Shared As Single COLOR_TEMP_COOL: COLOR_TEMP_COOL = 1.00
Dim Shared As Single COLOR_GREEN: COLOR_GREEN = 1.00

Screen _NewImage(VIDWIDTH, VIDHEIGHT, 32)
_Delay 0.2 'Just in case

_ScreenMove (_DesktopWidth / 2) - VIDWIDTH / 2, (_DesktopHeight / 2) - VIDHEIGHT / 2

Dim As String captureWinText: captureWinText = "Webcam API Test  - Child" + Chr$(0)
Dim As _Offset childID


Dim As _Offset childWin: childWin = CreateCaptureWindow(_Offset(captureWinText), WS_EX_NOACTIVATE, 0, 0, VIDWIDTH, VIDHEIGHT, _WindowHandle, childID)
If childWin = 0 Then
    Print "Couldn't create capture window."
    End
End If
_Title "Webcam API Test - Parent"
SetupDriver childWin, _TRUE 'change _FALSE to _TRUE to use default settings

Print "Previewing... Press Space bar to stop"
Print "Press escape to kill the window"
Dim Shared As _MEM frame
Dim As _Integer64 k
Dim As MSG msg
Dim As Long i
Do
    k = _KeyHit
    Select Case k
        Case 32 'Space bar
            Exit Do
        Case 27 'Escape - Reset
            BRIGHTNESS_LEVEL = 1.00
            SATURATION_LEVEL = 1.00
            NEGATIVE = _FALSE
            SEPIA = _FALSE
            FLIPPED_H = _FALSE
            FLIPPED_V = _FALSE
            COLOR_TEMP_WARM = 1.00
            COLOR_TEMP_COOL = 1.00
            COLOR_GREEN = 1.00
        Case 43 'numpad plus key
            If SATURATION_LEVEL < 2.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL + .10
            End If
        Case 45 'numpad minus key
            If SATURATION_LEVEL > 0.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL - .10
            End If
        Case 18432 'arrow key up
            If BRIGHTNESS_LEVEL < 2 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL + .10
            End If
        Case 20480 'arrow key down
            If BRIGHTNESS_LEVEL > 0.00 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL - .10
            End If
        Case Asc("N"), Asc("n") 'negative filter toggle
            NEGATIVE = Not NEGATIVE
        Case Asc("S"), Asc("s") 'sepia filter toggle
            SEPIA = Not SEPIA
        Case Asc("P"), Asc("p")
            If _FileExists("capture(" + _ToStr$(i) + ").png") Then
                While _FileExists("capture(" + _ToStr$(i) + ").png")
                    i = i + 1
                Wend
            End If
            _SaveImage "capture(" + _ToStr$(i) + ").png", frame.IMAGE, "PNG"
            i = i + 1
        Case Asc("C"), Asc("c")
            _ClipboardImage = frame.IMAGE
        Case Asc("H"), Asc("h")
            FLIPPED_H = Not FLIPPED_H
        Case Asc("V"), Asc("v")
            FLIPPED_V = Not FLIPPED_V
        Case Asc("R")
            If COLOR_TEMP_WARM < 2.00 Then
                COLOR_TEMP_WARM = COLOR_TEMP_WARM + .10
            End If
        Case Asc("r")
            If COLOR_TEMP_WARM > 0 Then
                COLOR_TEMP_WARM = COLOR_TEMP_WARM - .10
            End If
        Case Asc("G")
            If COLOR_GREEN < 2.00 Then
                COLOR_GREEN = COLOR_GREEN + .10
            End If
        Case Asc("g")
            If COLOR_GREEN > 0 Then
                COLOR_GREEN = COLOR_GREEN - .10
            End If
        Case Asc("B")
            If COLOR_TEMP_COOL < 2.00 Then
                COLOR_TEMP_COOL = COLOR_TEMP_COOL + .10
            End If
        Case Asc("b")
            If COLOR_TEMP_COOL > 0 Then
                COLOR_TEMP_COOL = COLOR_TEMP_COOL - .10
            End If
    End Select
    If PeekMessage(_Offset(msg), 0, 0, 0, PM_REMOVE) Then
        TranslateMessage _Offset(msg)
        DispatchMessage _Offset(msg)
    Else
        GrabFrame childWin
    End If
    _PutImage , frame.IMAGE, _Dest
    _Display
    _Limit FPS
Loop
Dim As _MEM clippedFrame
Print "Disconnecting Driver"
KillDriver childWin

_MemFree frame
'_MemFree clippedFrame

'Sleep

Sub SetupDriver (hwnd As _Offset, defaultSource As _Byte)
    Dim As _Offset libload: libload = LoadLibrary(Command$(0))
    Dim As _Offset myCallback: myCallback = GetProcAddress(libload, "CapVideoCallback")
    If myCallback = 0 Then
        Print "Can't find callback pointer"
        End
    End If
    Dim As BITMAPINFO format
    SendMessage hwnd, WM_CAP_DRIVER_CONNECT, 0, 0
    SendMessage hwnd, WM_CAP_SET_SCALE, _FALSE, 0
    SendMessage hwnd, WM_CAP_SET_PREVIEW, _FALSE, 0

    Dim As _Unsigned Long formatSize: formatSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If Len(format) <> formatSize Then
        KillDriver hwnd
        Print "Wrong size"
        Print formatSize, Len(format)
        End
    End If

    If SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Couldn't get format"
        End
    End If
    format.bmiHeader.biSize = Len(format)
    format.bmiHeader.biWidth = VIDWIDTH
    format.bmiHeader.biHeight = VIDHEIGHT
    format.bmiHeader.biPlanes = 1
    format.bmiHeader.biBitCount = 16 'yuy2 format
    format.bmiHeader.biSizeImage = VIDWIDTH * VIDHEIGHT * 2
    format.bmiHeader.biCompression = mmioStringToFOURCC("YUY2" + Chr$(0), &H00000010) 'MUST BE YUY2 FORMAT
    If SendMessage(hwnd, WM_CAP_SET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Failed to set video format"
        End
    End If
    If defaultSource = _FALSE Then
        SendMessage hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0 'PICK YUY2!!!
        SendMessage hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0
    End If
    SendMessage hwnd, WM_CAP_GET_VIDEOFORMAT, 0, _Offset(format)
    SendMessage hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, myCallback
End Sub

Sub KillDriver (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0
    DestroyWindow hwnd
End Sub

Sub GrabFrame (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0
End Sub

Function CapVideoCallback%& (hWnd As _Offset, lpVHdr As _Offset)
    Type VIDEOHDR
        As _Offset lpData
        As _Unsigned Long dwBufferLength, dwBytesUsed, dwTimeCaptured
        As String * 4 padding1
        As _Unsigned _Offset dwUser
        As _Unsigned Long dwFlags
        As String * 4 padding2
        As _Offset dwReserved1, dwReserved2, dwReserved3, dwReserved4
    End Type
    Dim As VIDEOHDR vhdr
    Dim As _MEM pVhdr: pVhdr = _Mem(lpVHdr, Len(vhdr))
    _MemGet pVhdr, pVhdr.OFFSET, vhdr
    _MemFree pVhdr
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        'KillDriver hWnd
        'End
    End If
    Dim As BITMAPINFO bi
    SendMessage hWnd, WM_CAP_GET_VIDEOFORMAT, frameSize, _Offset(bi)
    'Print bi.bmiHeader.biHeight
    Dim As _MEM lpData: lpData = _Mem(vhdr.lpData, vhdr.dwBufferLength)
    If _MemExists(frame) Then _MemFree frame
    Dim As Long bitsPerPixel: bitsPerPixel = bi.bmiHeader.biBitCount
    Dim As Long bytesPerPixel: bytesPerPixel = (bitsPerPixel + 7) \ 8
    Dim As _Unsigned Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As Long y, x
    Dim As _Unsigned _Byte yuy2(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned _Integer64 converted
    Dim As _Unsigned _Byte r, g, b
    Dim As _Offset pixelOffset
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i
    For y = 0 To bi.bmiHeader.biHeight - 1
        pScanLine = lpData.OFFSET + (y * stride)
        For x = 0 To bi.bmiHeader.biWidth - bytesPerPixel Step bytesPerPixel
            pixelOffset = pScanLine + (x * bytesPerPixel)
            _MemGet lpData, pixelOffset, yuy2()
            converted = ConvertYUY2toRGB(yuy2())
            PSet (x, y), converted And &HFFFFFFFF
            PSet (x + 1, y), _ShR(converted, 32) And &HFFFFFFFF
        Next
    Next
    If FLIPPED_H Then
        Dim As Long hi: hi = _CopyImage(i)
        _PutImage , hi, i, (bi.bmiHeader.biWidth - 1, 0)-(0, bi.bmiHeader.biHeight - 1)
        _FreeImage hi
    End If
    If FLIPPED_V Then
        Dim As Long vi: vi = _CopyImage(i)
        _PutImage , vi, i, (bi.bmiHeader.biWidth - 1, bi.bmiHeader.biHeight - 1)-(0, 0)
        _FreeImage vi
    End If
    _Dest 0
    frame = _MemImage(i)
End Function


Function ConvertYUY2toRGB~&& (yuy2() As _Unsigned _Byte)
    Dim As _Unsigned _Byte r1, g1, b1, r2, g2, b2
    Dim As Double Y1, Y2, U, V

    ' Extract values
    Y1 = yuy2(0) * BRIGHTNESS_LEVEL
    Y2 = yuy2(2) * BRIGHTNESS_LEVEL
    U = (yuy2(1) - 128) * SATURATION_LEVEL
    V = (yuy2(3) - 128) * SATURATION_LEVEL

    ' Convert first pixel
    r1 = _Clamp((Y1 + 1.13983 * V) * COLOR_TEMP_WARM, 0, 255)
    g1 = _Clamp((Y1 - 0.39465 * U - 0.58060 * V) * COLOR_GREEN, 0, 255)
    b1 = _Clamp((Y1 + 2.03211 * U) * COLOR_TEMP_COOL, 0, 255)

    ' Convert second pixel
    r2 = _Clamp((Y2 + 1.13983 * V) * COLOR_TEMP_WARM, 0, 255)
    g2 = _Clamp((Y2 - 0.39465 * U - 0.58060 * V) * COLOR_GREEN, 0, 255)
    b2 = _Clamp((Y2 + 2.03211 * U) * COLOR_TEMP_COOL, 0, 255)

    If NEGATIVE = _TRUE Then
        r1 = 255 - r1: g1 = 255 - g1: b1 = 255 - b1
        r2 = 255 - r2: g2 = 255 - g2: b2 = 255 - b2
    End If

    If SEPIA = _TRUE Then
        Dim As _Unsigned _Byte sepia_r1, sepia_g1, sepia_b1
        Dim As _Unsigned _Byte sepia_r2, sepia_g2, sepia_b2

        sepia_r1 = _Clamp((r1 * 0.393) + (g1 * 0.769) + (b1 * 0.189), 0, 255)
        sepia_g1 = _Clamp((r1 * 0.349) + (g1 * 0.686) + (b1 * 0.168), 0, 255)
        sepia_b1 = _Clamp((r1 * 0.272) + (g1 * 0.534) + (b1 * 0.131), 0, 255)

        sepia_r2 = _Clamp((r2 * 0.393) + (g2 * 0.769) + (b2 * 0.189), 0, 255)
        sepia_g2 = _Clamp((r2 * 0.349) + (g2 * 0.686) + (b2 * 0.168), 0, 255)
        sepia_b2 = _Clamp((r2 * 0.272) + (g2 * 0.534) + (b2 * 0.131), 0, 255)
        r1 = sepia_r1
        r2 = sepia_r2
        g1 = sepia_g1
        g2 = sepia_g2
        b1 = sepia_b1
        b2 = sepia_b2
    End If

    ' Pack pixels into a single return value
    ConvertYUY2toRGB = _RGB32(r1, g1, b1) Or _ShL(_RGB32(r2, g2, b2), 32)
End Function
           
The noticing will continue
Reply
#6
Added palette swapping using the number row. 1 through 4 will switch between the 4 available palettes. Press the escape key to reset.

Code: (Select All)
Option _Explicit
'$Console
$VersionInfo:Comments=Avicap32 webcam to memory test
'Using $VersionInfo so we get modern controls
'------------------------------------------------------------------------------------------------------------------------------
'Capture Driver Constants
Const WM_CAP_START = &H0400
Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
Const WM_CAP_SET_SCALE = WM_CAP_START + 53
Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP_START + 42
Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP_START + 61
Const WM_CAP_GET_VIDEOFORMAT = WM_CAP_START + 44
Const WM_CAP_SET_VIDEOFORMAT = WM_CAP_START + 45
Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP_START + 41
Const WM_CAP_SET_CALLBACK_FRAME = WM_CAP_START + 5
Const CF_DIB = &H0008

Const PM_REMOVE = &H0001
Const WS_EX_NOACTIVATE = &H08000000

Const FPS = 30 'Not recommended to set this higher than frame rate of webcam/video device

Const VIDWIDTH = 640
Const VIDHEIGHT = 480

Type BITMAPINFOHEADER
    As _Unsigned Long biSize
    As Long biWidth, biHeight
    As _Unsigned Integer biPlanes, biBitCount
    As _Unsigned Long biCompression, biSizeImage
    As Long biXPelsPerMeter, biYPelsPerMeter
    As _Unsigned Long biClrUsed, biClrImportant
End Type

Type BITMAPINFO
    As BITMAPINFOHEADER bmiHeader
End Type

Type POINT
    As Long x, y
End Type

Type MSG
    As _Offset hwnd
    As _Unsigned Long message
    $If 64BIT Then
        As String * 4 padding1
    $End If
    As _Unsigned _Offset wParam
    As _Offset lParam
    As _Unsigned Long time
    $If 64BIT Then
        As String * 4 padding2
    $End If
    As POINT pt
    As _Unsigned Long lPrivat
End Type

Declare Dynamic Library "Avicap32"
    Function CreateCaptureWindow& Alias "capCreateCaptureWindowA" (ByVal lpszWindowName As _Offset, ByVal dwStyle As _Unsigned Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hwndParent As _Offset, ByVal nId As Long)
End Declare

Declare CustomType Library
    Sub SendMessage Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function SendMessage& Alias "SendMessageA" (ByVal hWnd As _Offset, ByVal Msg As _Unsigned Long, ByVal wParam As _Offset, ByVal lParam As _Offset)
    Function PeekMessage& Alias "PeekMessageA" (ByVal lpMsg As _Offset, ByVal hWnd As _Offset, ByVal wMsgFilterMin As _Unsigned Long, ByVal wMsgFilterMax As _Unsigned Long, ByVal wRemoveMsg As _Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As _Offset)
    Sub DispatchMessage (ByVal lpMsg As _Offset)
    Sub DestroyWindow (ByVal hWnd As _Offset)
    Function mmioStringToFOURCC& (sz As String, ByVal uFlags As _Unsigned Long)
    Function OpenClipboard& (ByVal hWndNewOwner As _Offset)
    Function GetClipboardData%& (ByVal uFormat As _Unsigned Long)
    Sub CloseClipboard ()
    Function GlobalLock%& (ByVal hMem As _Offset)
    Function GlobalUnlock& (ByVal hMem As _Offset)
    Function LoadLibrary%& (lpLibFileName As String)
    Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
End Declare

Declare Library ".\internal\c\c_compiler\include\vfw"
End Declare

Declare Library "framecallback"
End Declare

Dim Shared As Single SATURATION_LEVEL: SATURATION_LEVEL = 1.00 '0.00 for greyscale, 1.00 for normal, and >1.00 for oversaturation
Dim Shared As Single BRIGHTNESS_LEVEL: BRIGHTNESS_LEVEL = 1.00
Dim Shared As _Byte NEGATIVE: NEGATIVE = _FALSE
Dim Shared As _Byte SEPIA: SEPIA = _FALSE
Dim Shared As _Byte FLIPPED_H: FLIPPED_H = _FALSE
Dim Shared As _Byte FLIPPED_V: FLIPPED_V = _FALSE
Dim Shared As Single COLOR_TEMP_WARM: COLOR_TEMP_WARM = 1.00
Dim Shared As Single COLOR_TEMP_COOL: COLOR_TEMP_COOL = 1.00
Dim Shared As Single COLOR_GREEN: COLOR_GREEN = 1.00
Dim Shared As _Unsigned _Byte PALETTE_SWAP: PALETTE_SWAP = 0

Screen _NewImage(VIDWIDTH, VIDHEIGHT, 32)
_Delay 0.2 'Just in case

_ScreenMove (_DesktopWidth / 2) - VIDWIDTH / 2, (_DesktopHeight / 2) - VIDHEIGHT / 2

Dim As String captureWinText: captureWinText = "Webcam API Test  - Child" + Chr$(0)
Dim As _Offset childID


Dim As _Offset childWin: childWin = CreateCaptureWindow(_Offset(captureWinText), WS_EX_NOACTIVATE, 0, 0, VIDWIDTH, VIDHEIGHT, _WindowHandle, childID)
If childWin = 0 Then
    Print "Couldn't create capture window."
    End
End If
_Title "Webcam API Test - Parent"
SetupDriver childWin, _TRUE 'change _FALSE to _TRUE to use default settings

Print "Previewing... Press Space bar to stop"
Print "Press escape to kill the window"
Dim Shared As _MEM frame
Dim As _Integer64 k
Dim As MSG msg
Dim As Long i
Do
    k = _KeyHit
    Select Case k
        Case 32 'Space bar
            Exit Do
        Case 27 'Escape - Reset
            BRIGHTNESS_LEVEL = 1.00
            SATURATION_LEVEL = 1.00
            NEGATIVE = _FALSE
            SEPIA = _FALSE
            FLIPPED_H = _FALSE
            FLIPPED_V = _FALSE
            COLOR_TEMP_WARM = 1.00
            COLOR_TEMP_COOL = 1.00
            COLOR_GREEN = 1.00
            PALETTE_SWAP = 0
        Case 43 'numpad plus key
            If SATURATION_LEVEL < 2.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL + .10
            End If
        Case 45 'numpad minus key
            If SATURATION_LEVEL > 0.00 Then
                SATURATION_LEVEL = SATURATION_LEVEL - .10
            End If
        Case 18432 'arrow key up
            If BRIGHTNESS_LEVEL < 2 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL + .10
            End If
        Case 20480 'arrow key down
            If BRIGHTNESS_LEVEL > 0.00 Then
                BRIGHTNESS_LEVEL = BRIGHTNESS_LEVEL - .10
            End If
        Case Asc("N"), Asc("n") 'negative filter toggle
            NEGATIVE = Not NEGATIVE
        Case Asc("S"), Asc("s") 'sepia filter toggle
            SEPIA = Not SEPIA
        Case Asc("P"), Asc("p")
            If _FileExists("capture(" + _ToStr$(i) + ").png") Then
                While _FileExists("capture(" + _ToStr$(i) + ").png")
                    i = i + 1
                Wend
            End If
            _SaveImage "capture(" + _ToStr$(i) + ").png", frame.IMAGE, "PNG"
            i = i + 1
        Case Asc("C"), Asc("c")
            _ClipboardImage = frame.IMAGE
        Case Asc("H"), Asc("h")
            FLIPPED_H = Not FLIPPED_H
        Case Asc("V"), Asc("v")
            FLIPPED_V = Not FLIPPED_V
        Case Asc("R")
            If COLOR_TEMP_WARM < 2.00 Then
                COLOR_TEMP_WARM = COLOR_TEMP_WARM + .10
            End If
        Case Asc("r")
            If COLOR_TEMP_WARM > 0 Then
                COLOR_TEMP_WARM = COLOR_TEMP_WARM - .10
            End If
        Case Asc("G")
            If COLOR_GREEN < 2.00 Then
                COLOR_GREEN = COLOR_GREEN + .10
            End If
        Case Asc("g")
            If COLOR_GREEN > 0 Then
                COLOR_GREEN = COLOR_GREEN - .10
            End If
        Case Asc("B")
            If COLOR_TEMP_COOL < 2.00 Then
                COLOR_TEMP_COOL = COLOR_TEMP_COOL + .10
            End If
        Case Asc("b")
            If COLOR_TEMP_COOL > 0 Then
                COLOR_TEMP_COOL = COLOR_TEMP_COOL - .10
            End If
        Case Asc("1")
            PALETTE_SWAP = 1
        Case Asc("2")
            PALETTE_SWAP = 2
        Case Asc("3")
            PALETTE_SWAP = 3
        Case Asc("4")
            PALETTE_SWAP = 4
    End Select
    If PeekMessage(_Offset(msg), 0, 0, 0, PM_REMOVE) Then
        TranslateMessage _Offset(msg)
        DispatchMessage _Offset(msg)
    Else
        GrabFrame childWin
    End If
    _PutImage , frame.IMAGE, _Dest
    _Display
    _Limit FPS
Loop
Dim As _MEM clippedFrame
Print "Disconnecting Driver"
KillDriver childWin

_MemFree frame
'_MemFree clippedFrame

'Sleep

Sub SetupDriver (hwnd As _Offset, defaultSource As _Byte)
    Dim As _Offset libload: libload = LoadLibrary(Command$(0))
    Dim As _Offset myCallback: myCallback = GetProcAddress(libload, "CapVideoCallback")
    If myCallback = 0 Then
        Print "Can't find callback pointer"
        End
    End If
    Dim As BITMAPINFO format
    SendMessage hwnd, WM_CAP_DRIVER_CONNECT, 0, 0
    SendMessage hwnd, WM_CAP_SET_SCALE, _FALSE, 0
    SendMessage hwnd, WM_CAP_SET_PREVIEW, _FALSE, 0

    Dim As _Unsigned Long formatSize: formatSize = SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If Len(format) <> formatSize Then
        KillDriver hwnd
        Print "Wrong size"
        Print formatSize, Len(format)
        End
    End If

    If SendMessage(hwnd, WM_CAP_GET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Couldn't get format"
        End
    End If
    format.bmiHeader.biSize = Len(format)
    format.bmiHeader.biWidth = VIDWIDTH
    format.bmiHeader.biHeight = VIDHEIGHT
    format.bmiHeader.biPlanes = 1
    format.bmiHeader.biBitCount = 16 'yuy2 format
    format.bmiHeader.biSizeImage = VIDWIDTH * VIDHEIGHT * 2
    format.bmiHeader.biCompression = mmioStringToFOURCC("YUY2" + Chr$(0), &H00000010) 'MUST BE YUY2 FORMAT
    If SendMessage(hwnd, WM_CAP_SET_VIDEOFORMAT, Len(format), _Offset(format)) = 0 Then
        KillDriver hwnd
        Print "Failed to set video format"
        End
    End If
    If defaultSource = _FALSE Then
        SendMessage hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0 'PICK YUY2!!!
        SendMessage hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0
    End If
    SendMessage hwnd, WM_CAP_GET_VIDEOFORMAT, 0, _Offset(format)
    SendMessage hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, myCallback
End Sub

Sub KillDriver (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0
    DestroyWindow hwnd
End Sub

Sub GrabFrame (hwnd As _Offset)
    SendMessage hwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0
End Sub

Function CapVideoCallback%& (hWnd As _Offset, lpVHdr As _Offset)
    Type VIDEOHDR
        As _Offset lpData
        As _Unsigned Long dwBufferLength, dwBytesUsed, dwTimeCaptured
        As String * 4 padding1
        As _Unsigned _Offset dwUser
        As _Unsigned Long dwFlags
        As String * 4 padding2
        As _Offset dwReserved1, dwReserved2, dwReserved3, dwReserved4
    End Type
    Dim As VIDEOHDR vhdr
    Dim As _MEM pVhdr: pVhdr = _Mem(lpVHdr, Len(vhdr))
    _MemGet pVhdr, pVhdr.OFFSET, vhdr
    _MemFree pVhdr
    Dim As _Unsigned Long frameSize: frameSize = SendMessage(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0)
    If frameSize = 0 Then
        Print "Failed to get video format size"
        'KillDriver hWnd
        'End
    End If
    Dim As BITMAPINFO bi
    SendMessage hWnd, WM_CAP_GET_VIDEOFORMAT, frameSize, _Offset(bi)
    'Print bi.bmiHeader.biHeight
    Dim As _MEM lpData: lpData = _Mem(vhdr.lpData, vhdr.dwBufferLength)
    If _MemExists(frame) Then _MemFree frame
    Dim As Long bitsPerPixel: bitsPerPixel = bi.bmiHeader.biBitCount
    Dim As Long bytesPerPixel: bytesPerPixel = (bitsPerPixel + 7) \ 8
    Dim As _Unsigned Long stride: stride = (((bi.bmiHeader.biWidth * bi.bmiHeader.biBitCount) + 31) And Not 31) \ 8
    Dim As Long y, x
    Dim As _Unsigned _Byte yuy2(0 To 3)
    Dim As _Offset pScanLine
    Dim As _Unsigned _Integer64 converted
    Dim As _Unsigned _Byte r, g, b
    Dim As _Offset pixelOffset
    Dim As Long i: i = _NewImage(bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 32)
    _Dest i
    For y = 0 To bi.bmiHeader.biHeight - 1
        pScanLine = lpData.OFFSET + (y * stride)
        For x = 0 To bi.bmiHeader.biWidth - bytesPerPixel Step bytesPerPixel
            pixelOffset = pScanLine + (x * bytesPerPixel)
            _MemGet lpData, pixelOffset, yuy2()
            converted = ConvertYUY2toRGB(yuy2())
            PSet (x, y), converted And &HFFFFFFFF
            PSet (x + 1, y), _ShR(converted, 32) And &HFFFFFFFF
        Next
    Next
    If FLIPPED_H Then
        Dim As Long hi: hi = _CopyImage(i)
        _PutImage , hi, i, (bi.bmiHeader.biWidth - 1, 0)-(0, bi.bmiHeader.biHeight - 1)
        _FreeImage hi
    End If
    If FLIPPED_V Then
        Dim As Long vi: vi = _CopyImage(i)
        _PutImage , vi, i, (bi.bmiHeader.biWidth - 1, bi.bmiHeader.biHeight - 1)-(0, 0)
        _FreeImage vi
    End If
    _Dest 0
    frame = _MemImage(i)
End Function


Function ConvertYUY2toRGB~&& (yuy2() As _Unsigned _Byte)
    Dim As _Unsigned _Byte r1, g1, b1, r2, g2, b2, r3, g3, b3
    Dim As Double Y1, Y2, U, V

    ' Extract values
    Y1 = yuy2(0) * BRIGHTNESS_LEVEL
    Y2 = yuy2(2) * BRIGHTNESS_LEVEL
    U = (yuy2(1) - 128) * SATURATION_LEVEL
    V = (yuy2(3) - 128) * SATURATION_LEVEL

    ' Convert first pixel
    r1 = _Clamp((Y1 + 1.13983 * V) * COLOR_TEMP_WARM, 0, 255)
    g1 = _Clamp((Y1 - 0.39465 * U - 0.58060 * V) * COLOR_GREEN, 0, 255)
    b1 = _Clamp((Y1 + 2.03211 * U) * COLOR_TEMP_COOL, 0, 255)

    ' Convert second pixel
    r2 = _Clamp((Y2 + 1.13983 * V) * COLOR_TEMP_WARM, 0, 255)
    g2 = _Clamp((Y2 - 0.39465 * U - 0.58060 * V) * COLOR_GREEN, 0, 255)
    b2 = _Clamp((Y2 + 2.03211 * U) * COLOR_TEMP_COOL, 0, 255)

    If NEGATIVE Then
        r1 = 255 - r1: g1 = 255 - g1: b1 = 255 - b1
        r2 = 255 - r2: g2 = 255 - g2: b2 = 255 - b2
    End If

    If PALETTE_SWAP > 0 Then
        Select Case PALETTE_SWAP
            Case 1
                ''Dobra
                r3 = _Clamp(r1 * 0.989 + g1 * 1.000 + b1 * 0.510, 0, 255)
                g3 = _Clamp(r1 * 0.157 + g1 * 0.500 + b1 * 0.400, 0, 255)
                b3 = _Clamp(r1 * 0.278 + g1 * 0.000 + b1 * 0.267, 0, 255)
                r1 = r3
                g1 = g3
                b1 = b3

                r3 = _Clamp(r2 * 0.989 + g2 * 1.000 + b2 * 0.510, 0, 255)
                g3 = _Clamp(r2 * 0.157 + g2 * 0.500 + b2 * 0.400, 0, 255)
                b3 = _Clamp(r2 * 0.278 + g2 * 0.000 + b2 * 0.267, 0, 255)
                r2 = r3
                g2 = g3
                b2 = b3
            Case 2
                ''Roden
                r3 = _Clamp(r1 * 0.545 + g1 * 0.0902 + b1 * 0.804, 0, 255)
                g3 = _Clamp(r1 * 0.412 + g1 * 0.502 + b1 * 0.522, 0, 255)
                b3 = _Clamp(r1 * 0.412 + g1 * 0.427 + b1 * 0.247, 0, 255)
                r1 = r3
                g1 = g3
                b1 = b3

                r3 = _Clamp(r2 * 0.545 + g2 * 0.0902 + b2 * 0.804, 0, 255)
                g3 = _Clamp(r2 * 0.412 + g2 * 0.502 + b2 * 0.522, 0, 255)
                b3 = _Clamp(r2 * 0.412 + g2 * 0.427 + b2 * 0.247, 0, 255)
                r2 = r3
                g2 = g3
                b2 = b3
            Case 3
                ''Flowers
                r3 = _Clamp(r1 * 0.753 + g1 * 1.000 + b1 * 0.000, 0, 255)
                g3 = _Clamp(r1 * 0.000 + g1 * 1.000 + b1 * 0.000, 0, 255)
                b3 = _Clamp(r1 * 0.000 + g1 * 1.000 + b1 * 1.000, 0, 255)
                r1 = r3
                g1 = g3
                b1 = b3

                r3 = _Clamp(r2 * 0.753 + g2 * 1.000 + b2 * 0.000, 0, 255)
                g3 = _Clamp(r2 * 0.000 + g2 * 1.000 + b2 * 0.000, 0, 255)
                b3 = _Clamp(r2 * 0.000 + g2 * 1.000 + b2 * 1.000, 0, 255)
                r2 = r3
                g2 = g3
                b2 = b3
            Case 4
                ''GBR
                r3 = _Clamp(r1 * 0 + g1 * 0 + b1 * 1, 0, 255)
                g3 = _Clamp(r1 * 1 + g1 * 0 + b1 * 0, 0, 255)
                b3 = _Clamp(r1 * 0 + g1 * 1 + b1 * 0, 0, 255)
                r1 = r3
                g1 = g3
                b1 = b3

                r3 = _Clamp(r2 * 0 + g2 * 0 + b2 * 1, 0, 255)
                g3 = _Clamp(r2 * 1 + g2 * 0 + b2 * 0, 0, 255)
                b3 = _Clamp(r2 * 0 + g2 * 1 + b2 * 0, 0, 255)
                r2 = r3
                g2 = g3
                b2 = b3
        End Select
    End If
    If SEPIA Then
        Dim As _Unsigned _Byte sepia_r1, sepia_g1, sepia_b1
        Dim As _Unsigned _Byte sepia_r2, sepia_g2, sepia_b2

        sepia_r1 = _Clamp((r1 * 0.393) + (g1 * 0.769) + (b1 * 0.189), 0, 255)
        sepia_g1 = _Clamp((r1 * 0.349) + (g1 * 0.686) + (b1 * 0.168), 0, 255)
        sepia_b1 = _Clamp((r1 * 0.272) + (g1 * 0.534) + (b1 * 0.131), 0, 255)

        sepia_r2 = _Clamp((r2 * 0.393) + (g2 * 0.769) + (b2 * 0.189), 0, 255)
        sepia_g2 = _Clamp((r2 * 0.349) + (g2 * 0.686) + (b2 * 0.168), 0, 255)
        sepia_b2 = _Clamp((r2 * 0.272) + (g2 * 0.534) + (b2 * 0.131), 0, 255)
        r1 = sepia_r1
        r2 = sepia_r2
        g1 = sepia_g1
        g2 = sepia_g2
        b1 = sepia_b1
        b2 = sepia_b2
    End If

    ' Pack pixels into a single return value
    ConvertYUY2toRGB = _RGB32(r1, g1, b1) Or _ShL(_RGB32(r2, g2, b2), 32)
End Function

               


Attached Files
.h   framecallback.h (Size: 355 bytes / Downloads: 13)
The noticing will continue
Reply
#7
Bro this is very cool.
The new era of QB64 may start now - AI in QB64.
We can just make a better camera app...
We can make an app for live video recording... maybe for annotations from camera
It is very good.  Smile
Reply
#8
Excellent! Now if we can just save video to AVI or animated GIF, and maybe even load / edit / save, that would open up some possibilities. 

@SpriggsySpriggs, can we control camera zoom with the API?
Reply
#9
(03-01-2025, 05:41 PM)madscijr Wrote: @SpriggsySpriggs, can we control camera zoom with the API?

We're grabbing raw pixel data but we're not really controlling the camera itself. Now, if we open the camera dialog again during preview, we can use Windows' sliders to adjust zoom and such.
The noticing will continue
Reply
#10
(03-01-2025, 06:38 PM)SpriggsySpriggs Wrote:
(03-01-2025, 05:41 PM)madscijr Wrote: @SpriggsySpriggs, can we control camera zoom with the API?

We're grabbing raw pixel data but we're not really controlling the camera itself. Now, if we open the camera dialog again during preview, we can use Windows' sliders to adjust zoom and such.
Gotcha... maybe if the camera's software itself has an API, but not that important for anything I'd be looking to do.  You've done quite enough, thank you! :-D 

I did some googling on generating an AVI, and found something about using FFMPEG for turning a bunch of still images into a movie, so maybe that could work (just save each frame to a file and then shell out to FFMPEG)? 

I'll play with this stuff later. One thing I want to try is "video echo"... Merging the images from the camera as they come in with what's already on the screen... Maybe it will show trails or look trippy. Another idea is: connect 2 or more laptops each with a webcam, where the other laptops send pictures over a LAN to laptop #1 which merges them in some funky way. I don't know what kind of throughput it would need for 1 or more streams of 320x240 resolution at 30 FPS? This stuff is fun to play with, that's for sure :-)
Reply




Users browsing this thread: 8 Guest(s)