Hier der Code (ohne GUI-Include). Der Webcam-Code ist auch nur aus verschiedenen Samples zusammengebastelt. Leider sind die Kommentare und die Struktur etwas konfus, da ich das ursprünglich für was anderes Entwickelt hatte und dann später erst zu einem Game gemacht hab. Die Bildverarbeitung geschieht so, dass ich das Bild zuerst in ein Array kopiere (mit GetBitmapBits_()) und dann nach der Bearbeitung mit SetBitmapBits_() zurückhole. Dann mit DrawImage() ganz normal ausgeben. Die Effekte entstehen dadurch, dass ich die ganzen Pixelkoordinaten durch eine Manipulationsmatrix variiere:
Code: Alles auswählen
#WM_CAP_START = #WM_USER
#WM_CAP_UNICODE_START = #WM_USER +100
#WM_CAP_PAL_SAVEA = #WM_CAP_START + 81
#WM_CAP_PAL_SAVEW = #WM_CAP_UNICODE_START + 81
#WM_CAP_UNICODE_END = #WM_CAP_PAL_SAVEW
#WM_CAP_ABORT = #WM_CAP_START + 69
#WM_CAP_DLG_VIDEOCOMPRESSION = #WM_CAP_START + 46
#WM_CAP_DLG_VIDEODISPLAY = #WM_CAP_START + 43
#WM_CAP_DLG_VIDEOFORMAT = #WM_CAP_START + 41
#WM_CAP_DLG_VIDEOSOURCE = #WM_CAP_START + 42
#WM_CAP_DRIVER_CONNECT = #WM_CAP_START + 10
#WM_CAP_DRIVER_DISCONNECT = #WM_CAP_START + 11
#WM_CAP_DRIVER_GET_CAPS = #WM_CAP_START + 14
#WM_CAP_DRIVER_GET_NAMEA = #WM_CAP_START + 12
#WM_CAP_DRIVER_GET_NAMEW = #WM_CAP_UNICODE_START + 12
#WM_CAP_DRIVER_GET_VERSIONA = #WM_CAP_START + 13
#WM_CAP_DRIVER_GET_VERSIONW = #WM_CAP_UNICODE_START + 13
#WM_CAP_EDIT_COPY = #WM_CAP_START + 30
#WM_CAP_END = #WM_CAP_UNICODE_END
#WM_CAP_FILE_ALLOCATE = #WM_CAP_START + 22
#WM_CAP_FILE_GET_CAPTURE_FILEA = #WM_CAP_START + 21
#WM_CAP_FILE_GET_CAPTURE_FILEW = #WM_CAP_UNICODE_START + 21
#WM_CAP_FILE_SAVEASA = #WM_CAP_START + 23
#WM_CAP_FILE_SAVEASW = #WM_CAP_UNICODE_START + 23
#WM_CAP_FILE_SAVEDIBA = #WM_CAP_START + 25
#WM_CAP_FILE_SAVEDIBW = #WM_CAP_UNICODE_START + 25
#WM_CAP_FILE_SET_CAPTURE_FILEA = #WM_CAP_START + 20
#WM_CAP_FILE_SET_CAPTURE_FILEW = #WM_CAP_UNICODE_START + 20
#WM_CAP_FILE_SET_INFOCHUNK = #WM_CAP_START + 24
#WM_CAP_GET_AUDIOFORMAT = #WM_CAP_START + 36
#WM_CAP_GET_CAPSTREAMPTR = #WM_CAP_START + 1
#WM_CAP_GET_MCI_DEVICEA = #WM_CAP_START + 67
#WM_CAP_GET_MCI_DEVICEW = #WM_CAP_UNICODE_START + 67
#WM_CAP_GET_SEQUENCE_SETUP = #WM_CAP_START + 65
#WM_CAP_GET_STATUS = #WM_CAP_START + 54
#WM_CAP_GET_USER_DATA = #WM_CAP_START + 8
#WM_CAP_GET_VIDEOFORMAT = #WM_CAP_START + 44
#WM_CAP_GRAB_FRAME = #WM_CAP_START + 60
#WM_CAP_GRAB_FRAME_NOSTOP = #WM_CAP_START + 61
#WM_CAP_PAL_AUTOCREATE = #WM_CAP_START + 83
#WM_CAP_PAL_MANUALCREATE = #WM_CAP_START + 84
#WM_CAP_PAL_OPENA = #WM_CAP_START + 80
#WM_CAP_PAL_OPENW = #WM_CAP_UNICODE_START + 80
#WM_CAP_PAL_PASTE = #WM_CAP_START + 82
#WM_CAP_SEQUENCE = #WM_CAP_START + 62
#WM_CAP_SEQUENCE_NOFILE = #WM_CAP_START + 63
#WM_CAP_SET_AUDIOFORMAT = #WM_CAP_START + 35
#WM_CAP_SET_CALLBACK_CAPCONTROL = #WM_CAP_START + 85
#WM_CAP_SET_CALLBACK_ERRORA = #WM_CAP_START + 2
#WM_CAP_SET_CALLBACK_ERRORW = #WM_CAP_UNICODE_START + 2
#WM_CAP_SET_CALLBACK_FRAME = #WM_CAP_START + 5
#WM_CAP_SET_CALLBACK_STATUSA = #WM_CAP_START + 3
#WM_CAP_SET_CALLBACK_STATUSW = #WM_CAP_UNICODE_START + 3
#WM_CAP_SET_CALLBACK_VIDEOSTREAM = #WM_CAP_START + 6
#WM_CAP_SET_CALLBACK_WAVESTREAM = #WM_CAP_START + 7
#WM_CAP_SET_CALLBACK_YIELD = #WM_CAP_START + 4
#WM_CAP_SET_MCI_DEVICEA = #WM_CAP_START + 66
#WM_CAP_SET_MCI_DEVICEW = #WM_CAP_UNICODE_START + 66
#WM_CAP_SET_OVERLAY = #WM_CAP_START + 51
#WM_CAP_SET_PREVIEW = #WM_CAP_START + 50
#WM_CAP_SET_PREVIEWRATE = #WM_CAP_START + 52
#WM_CAP_SET_SCALE = #WM_CAP_START + 53
#WM_CAP_SET_SCROLL = #WM_CAP_START + 55
#WM_CAP_SET_SEQUENCE_SETUP = #WM_CAP_START + 64
#WM_CAP_SET_USER_DATA = #WM_CAP_START + 9
#WM_CAP_SET_VIDEOFORMAT = #WM_CAP_START + 45
#WM_CAP_SINGLE_FRAME = #WM_CAP_START + 72
#WM_CAP_SINGLE_FRAME_CLOSE = #WM_CAP_START + 71
#WM_CAP_SINGLE_FRAME_OPEN = #WM_CAP_START + 70
#WM_CAP_STOP = #WM_CAP_START + 68
#AVSTREAMMASTER_AUDIO = 0
#AVSTREAMMASTER_NONE = 1
#btnStart = 10
#btnStop = 11
IncludeFile "GUI_Include.pb"
; DECLARES...
Declare CreateMatrixTable(FunctionNo.l)
Declare DoBlur()
Declare DoMovement()
Declare DoMatrix()
Global BufferSize.l
Global SourceBuffer.l
Global ShowBuffer.l
Global WorkBuffer.l
Global DiscoBuffer.l
Global CurrentEffect.l
Global Fakt1.f
Global Fakt2.f
Global Fakt3.f
Global Variant.f
UseJPEGImageDecoder()
UseJPEGImageEncoder()
; INITIALIZE FIELDS
; Tabelle für Matrix
Dim X_Matrix(320, 240) ; X-Sourcepunkt
Dim Y_Matrix(320, 240) ; Y-Sourcepunkt
Fakt1.f = 0.5
Fakt2.f = 0.5
Fakt3.f = 0.5
KameraID.l = Val(ProgramParameter())
If KameraID.l = 0
KameraID.l = 1
EndIf
Open_Window_0()
; ############ AVICAP-DLL vorbereiten und initialisieren #############
OpenLibrary(0, "avicap32.dll")
*capAddress = IsFunction(0, "capGetDriverDescriptionA")
DId.l = 0
Repeat
Name.s = Space(255)
Description.s = Space(255)
Ret.l = CallFunctionFast(*capAddress, DId.l, Name.s, Len(Name.s), Description.s, Len(Description.s))
If Trim(Name.s) <> ""
Debug Str(DId.l) + ":" + Name.s + " - " + Description.s
DId.l = DId.l + 1
EndIf
Until Trim(Name.s) = ""
; ############ Daten und Umgebung vorbereiten ################
; Matrix-Tabelle vorbereiten
CurrentEffect.l = 0
CreateMatrixTable(0)
; Bildschirmauflösung testen... (min 16 Bit)
CreateImage(1, 320, 240)
BitsPerPixel.l = ImageDepth()
If BitsPerPixel < 24
MessageRequester("Problem...","Das Programm benötigt unbedingt 32 Bit Farbtiefe!")
End
EndIf
FreeImage(1)
; Buffer-Grösse berechnen (320x240)...
BufferSize.l = 320 * 240 * (BitsPerPixel / 8) - 1
; Speicher reservieren (Als Array mit Pointer SourceBuffer. Dadurch Zugriff über Array möglich)
SourceBuffer.l = AllocateMemory(BufferSize.l)
WorkBuffer.l = AllocateMemory(BufferSize.l)
ShowBuffer.l = AllocateMemory(BufferSize.l)
; CreateImage(2,500,372)
If LoadImage(2,"DiscoBack.jpg") = 0
MessageRequester("Problem...","Datei DiscoBack.jpg ist nicht lesbar oder nicht vorhanden!")
End
EndIf
DiscoBufferSize.l = ImageWidth() * ImageHeight() * 4 - 1
DiscoBuffer.l = AllocateMemory(DiscoBufferSize.l)
GetBitmapBits_(ImageID(), DiscoBufferSize.l, DiscoBuffer.l)
;
; Kamera ansteuern und aktivieren...
If OpenLibrary(0, "avicap32.dll")
*capAddress = IsFunction(0, "capCreateCaptureWindowA")
; hWndC = CallFunctionFast(*capAddress, "My Capture Window", #WS_CHILD | #WS_VISIBLE, 10, 10, 320, 240, WindowID(),1)
hWndC = CallFunctionFast(*capAddress, "My Capture Window", #WS_CHILD | #WS_VISIBLE, 695, 12, 40, 30, WindowID(), 1)
SendMessage_(hWndC, #WM_CAP_DRIVER_CONNECT, KameraID.l, 0) ; Treiber connecten
; SendMessage_(hWndC, #WM_CAP_DLG_VIDEOFORMAT, 1, 0) ; Format (auflösung etc. ändern)
; SendMessage_(hWndC, #WM_CAP_DLG_VIDEOSOURCE, 1, 0) ; Formateinstellungen (Farbe, Kontrast etc.)
SendMessage_(hWndC,#WM_CAP_SET_SCALE, #True, 0) ; Kein Stretching verwenden
SendMessage_(hWndC, #WM_CAP_SET_PREVIEW, #True, 0) ; Preview einschalten (sonst kann man das Bild nicht bekommen, oder?)
SendMessage_(hWndC, #WM_CAP_SET_PREVIEWRATE, 50, 0) ; Wiederholrate einstellen (Millisekunden zwischen den Bildern)
Else
MessageRequester("Scotty, wir haben ein Problem...","Sorry, ich hab leider keine avicap32.dll gefunden...")
EndIf
; ############### MAIN LOOP ######################
Repeat
; Bild per Clipboard holen...
SendMessage_(hWndC, #WM_CAP_EDIT_COPY, 0, 0)
img.l = GetClipboardData(#PB_ClipboardImage)
; Daten in's Memory laden... (in SourceBuffer.l)
GetBitmapBits_(img.l, BufferSize.l, SourceBuffer.l)
; ############## BEARBEITEN ################
If CurrentEffect.l = 7
DoMovement()
SetBitmapBits_(img.l, BufferSize.l, ShowBuffer.l)
EndIf
If CurrentEffect.l = 6
DoBlur()
SetBitmapBits_(img.l, BufferSize.l, ShowBuffer.l)
EndIf
If CurrentEffect.l < 6
DoMatrix()
SetBitmapBits_(img.l, BufferSize.l, ShowBuffer.l)
EndIf
; CopyMemory(showbuffer.l, sourcebuffer.l, buffersize.l)
; ########## ENDE DER BEARBEITUNG #############
; Ergebnis ausgeben...
StartDrawing(WindowOutput())
DrawImage(img.l, 10, 12, 640, 480)
StopDrawing()
; Window-Events auswerten...
Event = WaitWindowEvent()
If Event=#PB_Event_Gadget
EvTyp = EventType()
Debug "Typ: " + Str(EvTyp)
Select EventGadgetID()
Case #btnExit ; Ende
Event = #PB_Event_CloseWindow
Case #btnFormat ; Webcam-Format
SendMessage_(hWndC, #WM_CAP_DLG_VIDEOFORMAT, 1, 0) ; Format (auflösung etc. ändern)
Case #btnSettings ; Webcam-Settings
SendMessage_(hWndC, #WM_CAP_DLG_VIDEOSOURCE, 1, 0) ; Formateinstellungen (Farbe, Kontrast etc.)
Case #btnFoto
CreateImage(3,320,240)
StartDrawing(ImageOutput())
DrawImage(img.l, 0, 0, 320, 240)
StopDrawing()
Zaehler.l = 1
Vorgabe.s = "KidsCam_" + Str(Zaehler.l) + ".jpg"
While ReadFile(1, Vorgabe.s) <> 0
CloseFile(1)
Zaehler.l = Zaehler.l + 1
Vorgabe.s = "KidsCam_" + Str(Zaehler.l) + ".jpg"
Wend
Filename.s = SaveFileRequester("Bild speichern", Vorgabe.s, "Bilder (*.jpg)|*.jpg|Alle Dateien (*.*)|*.*", 0)
If Filename.s <> ""
; Jetzt speichern
If Right(LCase(Filename.s), 4) <> ".jpg"
; Endung noch anhängen
Filename.s = Filename.s + ".jpg"
EndIf
SaveImage(3, Filename.s, #PB_ImagePlugin_JPEG, 8)
EndIf
FreeImage(3)
Case #Button_1 ; MIRROR1
CurrentEffect.l = 1
CreateMatrixTable(1)
SetGadgetState(#Button_1,1)
SetGadgetState(#Button_2,0)
SetGadgetState(#Button_3,0)
SetGadgetState(#Button_4,0)
SetGadgetState(#Button_5,0)
SetGadgetState(#Button_6,0)
SetGadgetState(#Button_7,0)
Case #Button_2 ; MIRROR2
CurrentEffect.l = 2
CreateMatrixTable(2)
SetGadgetState(#Button_1,0)
SetGadgetState(#Button_2,1)
SetGadgetState(#Button_3,0)
SetGadgetState(#Button_4,0)
SetGadgetState(#Button_5,0)
SetGadgetState(#Button_6,0)
SetGadgetState(#Button_7,0)
Case #Button_3 ; MIRROR3
CurrentEffect.l = 3
CreateMatrixTable(3)
SetGadgetState(#Button_1,0)
SetGadgetState(#Button_2,0)
SetGadgetState(#Button_3,1)
SetGadgetState(#Button_4,0)
SetGadgetState(#Button_5,0)
SetGadgetState(#Button_6,0)
SetGadgetState(#Button_7,0)
Case #Button_4 ; MIRROR4
CurrentEffect.l = 4
CreateMatrixTable(4)
SetGadgetState(#Button_1,0)
SetGadgetState(#Button_2,0)
SetGadgetState(#Button_3,0)
SetGadgetState(#Button_4,1)
SetGadgetState(#Button_5,0)
SetGadgetState(#Button_6,0)
SetGadgetState(#Button_7,0)
Case #Button_5 ; MIRROR5
CurrentEffect.l = 5
CreateMatrixTable(5)
SetGadgetState(#Button_1,0)
SetGadgetState(#Button_2,0)
SetGadgetState(#Button_3,0)
SetGadgetState(#Button_4,0)
SetGadgetState(#Button_5,1)
SetGadgetState(#Button_6,0)
SetGadgetState(#Button_7,0)
Case #Button_6 ; Spuk
CurrentEffect.l = 6
SetGadgetState(#Button_1,0)
SetGadgetState(#Button_2,0)
SetGadgetState(#Button_3,0)
SetGadgetState(#Button_4,0)
SetGadgetState(#Button_5,0)
SetGadgetState(#Button_6,1)
SetGadgetState(#Button_7,0)
Case #Button_7 ; Disko
CurrentEffect.l = 7
SetGadgetState(#Button_1,0)
SetGadgetState(#Button_2,0)
SetGadgetState(#Button_3,0)
SetGadgetState(#Button_4,0)
SetGadgetState(#Button_5,0)
SetGadgetState(#Button_6,0)
SetGadgetState(#Button_7,1)
EndSelect
EndIf
; Loop
Until Event = #PB_Event_CloseWindow
; Programm aufräumen und beenden...
SendMessage_(hWndC, #WM_CAP_STOP, 0, 0)
SendMessage_(hWndC, #WM_CAP_DRIVER_DISCONNECT, 0, 0)
FreeImage(2)
CloseWindow(#Window_0)
CloseLibrary(0)
End
Procedure DoBlur()
; Ausgabe über WorkBuffer
y.l=ShowBuffer.l
For x.l = SourceBuffer.l To SourceBuffer.l + BufferSize.l
NewVal.l = 15 * (PeekB(y.l) & $FF)
NewVal.l = NewVal.l + PeekB(x.l) & $FF
NewVal.l = NewVal.l / 16
If NewVal.l>255:NewVal.l=255:EndIf
If NewVal.l<0:NewVal.l=0:EndIf
PokeB(y.l, NewVal.l)
y.l = y.l + 1
Next
EndProcedure
Procedure DoMovement()
y.l=WorkBuffer.l
z.l=ShowBuffer.l
c.l = 0
Fakt1.f = Fakt1.f + 0.01
Fakt2.f = Fakt2.f + 0.02
Fakt3.f = Fakt3.f + 0.05
If Fakt1.f > 1: Fakt1.f = 0.5: EndIf
If Fakt2.f > 1: Fakt2.f = 0.5: EndIf
If Fakt3.f > 1: Fakt3.f = 0.5: EndIf
For x.l = SourceBuffer.l+2 To SourceBuffer.l + BufferSize.l Step 4
NewVal.l = (PeekB(x.l) & $FF) - (PeekB(y.l) & $FF)
If NewVal.l > 25
If NewVal.l > 255: NewVal.l = 255: EndIf
PokeB(z.l, NewVal.l * Fakt1.f)
PokeB(z.l+1, NewVal.l * Fakt2.f)
PokeB(z.l+2, NewVal.l * Fakt3.f)
Else
PokeB(z.l, PeekB(DiscoBuffer.l + c.l) & $FF)
PokeB(z.l+1, PeekB(DiscoBuffer.l + c.l + 1) & $FF)
PokeB(z.l+2, PeekB(DiscoBuffer.l + c.l + 2) & $FF)
;NewVal.l = PeekB(z.l) & $FF
;NewVal.l = NewVal.l - 1
;If NewVal.l < 254: NewVal.l = 0: EndIf
;PokeB(z.l, NewVal.l)
;PokeB(z.l+1, NewVal.l)
;PokeB(z.l+2, NewVal.l)
EndIf
PokeB(y.l, PeekB(x.l) & $FF)
y.l = y.l + 4
z.l = z.l + 4
c.l = c.l + 4
Next
EndProcedure
Procedure DoMatrix()
; Matrixeffekt anwenden
For x.l = 0 To 319
For y.l = 0 To 239
SourcePos.l = Y_Matrix(x.l, y.l) * 320 * 4 + X_Matrix(x.l, y.l) * 4
DestPos.l = y.l * 320 * 4 + x.l * 4
PokeB(ShowBuffer.l + DestPos.l, PeekB(SourceBuffer.l + SourcePos.l) & $FF)
PokeB(ShowBuffer.l + DestPos.l + 1, PeekB(SourceBuffer.l + SourcePos.l + 1) & $FF)
PokeB(ShowBuffer.l + DestPos.l + 2, PeekB(SourceBuffer.l + SourcePos.l + 2) & $FF)
Next
Next
EndProcedure
Procedure CreateMatrixTable(FunctionNo.l)
; Matrixtabelle anlegen
; Init
Winkel1.f = 0
Winkel2.f = 0
Winkel3.f = 0
Winkel4.f = 0
Variant.f = Variant.f + 0.104
If Variant.f > 6.283: Variant.f = 0: EndIf
; Koordinatentabelle neu berechnen
For x.l = 0 To 319
Winkel1.f = 0
Winkel3.f = Winkel3.f + 0.0196
Winkel4.f = 0
For y.l = 0 To 239
Winkel1.f = Winkel1.f + 0.105
Winkel2.f = Winkel2.f + 0.0003
Winkel4.f = winkel4.f + 0.026
Select FunctionNo.l
Case 0
X_Matrix(x.l, y.l) = x.l
Y_Matrix(x.l, y.l) = y.l
Case 1
X_Matrix(x.l, y.l) = x.l + Cos(Winkel2.f)*7
Y_Matrix(x.l, y.l) = y.l + Sin(Winkel2.f)*7
Case 2
X_Matrix(x.l, y.l) = x.l
Y_Matrix(x.l, y.l) = y.l + Sin(Winkel1.f)*7
Case 3
X_Matrix(x.l, y.l) = x.l + Sin(Winkel3.f)*22
Y_Matrix(x.l, y.l) = y.l + Sin(Winkel4.f)*22
Case 4
X_Matrix(x.l, y.l) = x.l - Sin(Winkel3.f*3)*6
Y_Matrix(x.l, y.l) = y.l - Cos(Winkel4.f*2)*6
Case 5
X_Matrix(x.l, y.l) = x.l + Cos(winkel1.f) * 7
Y_Matrix(x.l, y.l) = y.l + Sin(winkel4.f) * 10
EndSelect
If X_Matrix(x.l, y.l) > 319: X_Matrix(x.l, y.l) = 319: EndIf
If X_Matrix(x.l, y.l) < 0: X_Matrix(x.l, y.l) = 0: EndIf
If Y_Matrix(x.l, y.l) > 239: Y_Matrix(x.l, y.l) = 239: EndIf
If Y_Matrix(x.l, y.l) < 0: Y_Matrix(x.l, y.l) = 0: EndIf
Next
Next
EndProcedure
Die Ideen dazu hätte ich schon, kann nur nicht so gut Icons malen. Hier meine Idee:
Spiegeleffekte 1-5: Ein Gitter das deformiert ist und die Ziffern 1 bis 5 leicht transparent eingeblendet haben (evtl. rechts unten)
Disko: Eine Tanzfläche mit bunten Scheinwerferstrahlen? Oder eine Spiegelkugel mit bunten Strahlen?