Hallo,
ich bin relativer Neuling in VB.NET (komme von VBA und VB) und möchte von einer Wärmebildkamera die Videoframes auslesen und anzeigen. Ich habe Beispielcode in Word-VBA und C++.NET, komme damit aber nur eingeschränkt klar und scheitere an folgendem Problem:
Die Wärmebildkamera stellt eine unmanaged DLL als Schnittstelle bereit, die ich bereits vollständig in VB.NET als Klasse abgebildet habe und die auch bestens funktioniert (Zugriff auf vorhandene Kameras, auslesen von Temperaturen etc.). Ich weiß aber nicht, wie ich mit dem von der DLL bereitgestellten Pointer, der auf den Videoframe zeigt, umgehen muss:
Laut Dokumentation gibt ein Ereignis OnFrameInit Breite, Höhe und Tiefe des Frames aus – das funktioniert. Das Folgeereignis OnNewFrameEx gibt dann einen Zeiger auf den Buffer aus, der den Videoframe enthält, sowie die Metadaten des Frames (die ich ebenfalls lesen kann).
Was aber mache ich jetzt mit dem Buffer-Pointer?
Ich habe den Delegaten so definiert:
Public Delegate Function delOnNewFrameEx(ByRef Buffer As SByte, ByRef _
FrameMetadata As FrameMetadata) As Integer In C++ ist der erste Parameter vom Typ char*, in VB.NET müsste das SByte sein.
Der zweite hat folgende Struktur:
Public Structure FrameMetadata
Public Size As UShort ' size of this structure
Public Counter As UInteger ' frame counter
Public CounterHW As UInteger ' frame counter hardware
Public Timestamp As Integer ' time stamp in UNITS (10000000 per second)
Public TimestampMedia As Integer
Public FlagState As TFlagState
Public TempChip As Single
Public TempFlag As Single
Public TempBox As Single
Public PIFin As UShort
End Structure Aber was beinhaltet der erste Parameter und wie verarbeite ich ihn weiter? Ist das ein Zeiger auf den Speicherbereich, den ich dann in einer bestimmten Länge auslesen muss – aber wie geht das?
In VBA wird das wie folgt gemacht (und es funktioniert auch bei mir):
Function OnNewFrameEx(ByRef Buffer As Byte, ByRef FrameMetadata As Byte) As Long
Dim x As Integer, y As Integer, n As Integer, idx As Long
Dim c1 As Long, c2 As Long, d As Long, e As Long
Dim R As Byte, G As Byte, B As Byte
On Error GoTo OnNewFrameExM1
Call CopyMem(Arr(0, 0), Buffer, Size * 2)
For y = 0 To Height - 1
n = 0
idx = (Height - 1 - y) * Stride
For x = 0 To Width - 1 Step 2
c1 = Arr(n, y) - 16
d = Arr(n + 1, y) - 128
c2 = Arr(n + 2, y) - 16
e = Arr(n + 3, y) - 128
Rem idx = y * Stride + x
MyArr(idx) = clip((298 * c1 + 516 * d + 128) / 256)
MyArr(idx + 1) = clip((298 * c1 - 100 * d - 208 * e + 128) / 256)
MyArr(idx + 2) = clip((298 * c1 + 409 * e + 128) / 256)
MyArr(idx + 3) = clip((298 * c2 + 516 * d + 128) / 256)
MyArr(idx + 4) = clip((298 * c2 - 100 * d - 208 * e + 128) / 256)
MyArr(idx + 5) = clip((298 * c2 + 409 * e + 128) / 256)
idx = idx + 6
n = n + 4
Next x
Next y
If capture = False Then
Status = SetDIBits(hdc, hwnd, 0, BMinf.bmiHeader.biSizeImage, MyArr(0), _
BMinf, DIB_RGB_COLORS)
ThisDocument.PI_Image.BackColor = RGB(255, 255, 255)
End If
Frames = Frames + 1
If Frames = 1000 Then
VersionDLL = VersionToText(GetVersionIPC_DLL())
Frames = Frames + 1
End If
OnNewFrameExM1:
OnNewFrameEx = 0
End Function Ich bin nicht in der Lage, das funktionierend nach VB.NET zu übersetzen Die CopyMem-Deklaration habe ich bereits angepasst, aber die Parameter, die ich übergebe, scheinen nicht richtig zu sein (zu kurz, zu lang, falsche Typ?).
In C++ wird statt mit CopyMem mit LockBits gearbeitet – aber auch das habe ich trotz tagelanger Recherche weder ganz kapiert noch umsetzen können, wäre aber sicherer als CopyMem.
Ich würde gerne grundsätzlich verstehen, was da oben eigentlich gemacht wird (Video und Grafik sind leider nicht meine Themen…)?
Wie komme ich an den Frame dran? Wie mache ich daraus eine Bitmap, die ich anzeigen kann?
Bin für jeden Hinweis dankbar!!!
Viele Grüße
Tom Richter |