Pointer auf DIB Picture

Hallo,

eine Function wird bei mir reglemaessig aufgerufen. Als Parameter wird ihr ein zeiger ( Pointer) mitgeliefert der auf die Adresse im Speicher zeigt wo ein DIB Bild liegt. Weiss jemand wie man das Bild aus dem Speicher holen kann und es in einer picture oder Image Box anzeigen lassen kann?
Müsste doch irgendwie mit Copymemory und Bitbit gehen oder liege ich nun total daneben?

MFG Alex

@ Rainer, also soweit bin ich schon gekommen, nur nun bin ich mit meinem Latein am ende :frowning:

Hallo,

eine Function wird bei mir reglemaessig aufgerufen. Als
Parameter wird ihr ein zeiger ( Pointer) mitgeliefert der auf
die Adresse im Speicher zeigt wo ein DIB Bild liegt. Weiss
jemand wie man das Bild aus dem Speicher holen kann und es in
einer picture oder Image Box anzeigen lassen kann?
Müsste doch irgendwie mit Copymemory und Bitbit gehen oder
liege ich nun total daneben?

Hallo
Meinst Du vielleicht ein Handle für eine Bitmap?
Ein DIB Bild liegt nicht an einer Adresse, sondern hat ein Handle oder seine Bitmap-Bits liegen an einer Adresse. Zur Bitmap gehören allerdings weitere Strukturen. Sorry, kann ich nicht vollständig aus dem Kopf. Ist es eine vollständige Bilddatei? Dann mach es doch über Dateizugriff.
Mit einer Adresse mit unbekannter Verwendung kannst Du nichts anfangen.
Ich bin an das Thema über CreateDibSection herangegangen.
Klappte klasse. Wenn Dein Bild in eine PictureBox mit BitBlt kopiert wird, dann kannst Du es auch von dort abspeichern.
Ich habe in einen Artikel geschrieben, wie man diese Bitmap beständig macht.
Da must Du durch die API-Beschreibungen schauen, ich bin mir auch nicht sicher, was Du meinst…
Ich habe in einen Artikel geschrieben, wie man diese Bitmap beständig macht.

MfG
Vielleicht fragst Du nochmal etwas genauer.

Hallo Matthias,

ok ich versuche es mal anders zu erklären.
Ich initialisiere meine Webcam und lasse mir die Bilder auf dem Rechner anzeigen. Die Bilder der Webcam, werden dann in einem sep. Fenster angezeigt, worauf ich keinen Zugriff habe.
Ich koennte ein Foto machen, dieses abspeichern und dann weiterbearbeiten. Ok aber bei 15 Frames /sek. würde es den Rechner sprengen :frowning:
Die Webcam hat ein ereignis was sich FrameCallBack nennt und bei jedem neuem Bild aufgerufen wird. Dieser Function wird ein Parameter „lpVHdr“ mitgegenen was auf eine Adresse im Speicher verweist, wo das Bild liegt ( ist ein Longwert).

Ich habe nun folgendes probiert

Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SetDIBitsToDevice24 Lib "gdi32" Alias "SetDIBitsToDevice" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BitmapInfoHeader, ByVal wUsage As Long) As Long

Private Type videoHDR
lpData As Long 'address to video buffer
dwBufLen As Long ' size in bytes of data buffer
dwBytesUsed As Long ' size of locked pointer in bytes
dwTimecaptured As Long
dwUser As Long ' user specific data
dwFlags As Long
dwReserved(3) As Long '4
End Type

Private Type BITMAPFILEHEADER
 bfType As Integer
 bfSize As Long
 bfReserved1 As Integer
 bfReserved2 As Integer
 bfOffBits As Long
End Type

Dim m\_memBits() As Byte
Dim m\_bih As BitmapInfoHeader
Dim videoheader As videoHDR

Private Sub ezVidCap1\_FrameCallback(ByVal lpVHdr As Long)
Call CopyMem(videoheader, ByVal lpVHdr, Len(videoheader))
ReDim m\_memBits(videoheader.dwBytesUsed)
Call CopyMem(m\_memBits(0), videoheader.lpData, videoheader.dwBytesUsed)
Call DrawDIB(Picture1.hdc)
End Sub

Public Function DrawDIB(ByVal outDC As Long, Optional ByVal outX As Long = 0, Optional ByVal outY As Long = 0, Optional ByVal outROP As RasterOpConstants = vbSrcCopy) As Long
Dim pwidth As Integer, pheight As Integer
pwidth = 320: pheight = 240
DrawDIB = SetDIBitsToDevice24(outDC, 320, 240, pwidth, pheight, 0, 0, 0, pheight, m\_memBits(0), m\_bih, 0)
End Function

So nun noch eine kurze Erklärung :smile:

Beim Aufruf von
Soweit scheint es ja zu klappen. Ich kopiere die Daten von der Adresse x in die Strucktur Videoheader und danach in das Array. Dieses ist auch praetig gefuellt ( 152064 daten)
Ich rufe dann die Function DrawPicure auf um so das Bild in die Piturebox 1 zu zeichen. Ein Laufzeitfehler tritt nicht auf, nur wird auch kein Bild angezeigt :frowning:
Weisst du woran der Fehler liegt?

MFG Alex

Hallo

Die Webcam hat ein ereignis was sich FrameCallBack nennt und
bei jedem neuem Bild aufgerufen wird. Dieser Function wird ein
Parameter „lpVHdr“ mitgegenen was auf eine Adresse im Speicher
verweist, wo das Bild liegt ( ist ein Longwert).

Na, das ist ja interessant. Woher weißt Du den Typ „videoHdr“?

Private Type videoHDR
lpData As Long 'address to video buffer

Ist der Video buffer wirklich eine ganze DIB? Oder nur eine DDB?(=Deviceabhängig)

dwBufLen As Long ’ size in bytes of data buffer

Na immerhin bekommst Du eine Daten-Länge, sonst könntest Du gar nicht kopieren.

Private Sub ezVidCap1_FrameCallback(ByVal lpVHdr As Long)
Call CopyMem(videoheader, ByVal lpVHdr, Len(videoheader))

Das hab ich noch verstanden.

ReDim m_memBits(videoheader.dwBytesUsed)
Call CopyMem(m_memBits(0), videoheader.lpData,
videoheader.dwBytesUsed)

Na schön, hier hast Du anscheinend den Videopuffer nach m_membits(0) kopiert. Hast Du auch m_membits() auf DwBufLen dimensioniert??

Call DrawDIB(Picture1.hdc)

Klar, Bild soll nach Picture1…

End Sub

Public Function DrawDIB(ByVal outDC As Long, Optional ByVal
outX As Long = 0, Optional ByVal outY As Long = 0, Optional
ByVal outROP As RasterOpConstants = vbSrcCopy) As Long
Dim pwidth As Integer, pheight As Integer
pwidth = 320: pheight = 240
DrawDIB = SetDIBitsToDevice24(outDC, 320, 240, pwidth,
pheight, 0, 0, 0, pheight, m_memBits(0), m_bih, 0)
End Function

SetDIBitsToDevice hab ich noch nicht ausprobiert.
Man kann sich aber auf DIB’s beschränken, braucht also selbst keine Umwandlung vorzunehmen.
Dein einziges Problem wird es sein, deine Daten aus dem Puffer in eine verwendbare DIB zu verwandeln.
Also was ist im Puffer und was ist die vollständige Struktur für die DIB?
Im Prinzip sitzt Du im Dunkeln ohne Doku. Probier doch mal mit schwarzem und mit weißem Bild, was dann der Puffer enthält, kausal oder nicht usw…
Viel Spaß noch.
MfG

Hallo

Hallo Matthias :smile:

danke erst einmal für deine Antwort :wink:

Die Webcam hat ein ereignis was sich FrameCallBack nennt und
bei jedem neuem Bild aufgerufen wird. Dieser Function wird ein
Parameter „lpVHdr“ mitgegenen was auf eine Adresse im Speicher
verweist, wo das Bild liegt ( ist ein Longwert).

Na, das ist ja interessant. Woher weißt Du den Typ „videoHdr“?

Wenn du mal goggle anwirfst und nach lpVHdr suchst ( sind net grad viele ergebnisse, kommst du irgendwo auf eine Seite wo das steht :smile:

Private Type videoHDR
lpData As Long 'address to video buffer

Ist der Video buffer wirklich eine ganze DIB? Oder nur eine
DDB?(=Deviceabhängig)

Nein eine ganze DIB

dwBufLen As Long ’ size in bytes of data buffer

Na immerhin bekommst Du eine Daten-Länge, sonst könntest Du
gar nicht kopieren.

Private Sub ezVidCap1_FrameCallback(ByVal lpVHdr As Long)
Call CopyMem(videoheader, ByVal lpVHdr, Len(videoheader))

Das hab ich noch verstanden.

Logisch die Daten werden in videoheader kopiert

ReDim m_memBits(videoheader.dwBytesUsed)
Call CopyMem(m_memBits(0), videoheader.lpData,
videoheader.dwBytesUsed)

Na schön, hier hast Du anscheinend den Videopuffer nach
m_membits(0) kopiert. Hast Du auch m_membits() auf DwBufLen
dimensioniert??

Durch die obige Anweisung redim … wird das Array dimensioniert auf glaub über 25000 Werte,die dann auch gefuellt werden. Warum ich dort
m_membits(0) stehen habe, weiss ich net so recht, da es auf der einen Seite so stand.

Call DrawDIB(Picture1.hdc)

Klar, Bild soll nach Picture1…

genau, aber das macht es nicht :frowning:

End Sub

Public Function DrawDIB(ByVal outDC As Long, Optional ByVal
outX As Long = 0, Optional ByVal outY As Long = 0, Optional
ByVal outROP As RasterOpConstants = vbSrcCopy) As Long
Dim pwidth As Integer, pheight As Integer
pwidth = 320: pheight = 240
DrawDIB = SetDIBitsToDevice24(outDC, 320, 240, pwidth,
pheight, 0, 0, 0, pheight, m_memBits(0), m_bih, 0)
End Function

SetDIBitsToDevice hab ich noch nicht ausprobiert.
Man kann sich aber auf DIB’s beschränken, braucht also selbst
keine Umwandlung vorzunehmen.

und wenn mache ich das? Hast du da eine Idee ?

Dein einziges Problem wird es sein, deine Daten aus dem Puffer
in eine verwendbare DIB zu verwandeln.
Also was ist im Puffer und was ist die vollständige Struktur
für die DIB?
Im Prinzip sitzt Du im Dunkeln ohne Doku. Probier doch mal mit
schwarzem und mit weißem Bild, was dann der Puffer enthält,
kausal oder nicht usw…

Das problem ist das die Daten von einer Webcam kommen und ich so immer farbsegmente drinne habe, aber vom prinzip her varieren die Bilder schon arg.
Wenn ich dort programmiere das das Bild als „DIB“ gespeichert werden soll, so denke ich mal das er die daten auch nur aus dem Speicher nimmt. Also muss es doch irgendwie gehen *grml*
Nur leider findet man keine Anleutung dazu :frowning:

Viel Spaß noch.
MfG

MFG

Hallo
Also erstmal, ich hab im MSDN(von 1999) nachgeschaut, was die Suche mit VideoHdr oder wie das hieß ergibt.
Die Nachrichten heißen dort anders.
Dein Redim habe ich zuerst nicht gesehen.
Wie ich schon gesagt habe, habe ich mit CreateDibSection angefangen, eine Bitmap ohne Palette mit diskreten Farbwerten zu erzeugen.
Bei Deiner Geschichte müßte ich anfangen, Experimente zu machen.
Ich habe beispielsweise noch nie eine Verbindung zu einem Videotreiber bzw. Cam-Treiber hergestellt.
Wie sag ich z.B. dem Treiber die Adresse für die Benachrichtigung?
Der Gerätename ist mir auch unbekannt usw…
Viel Spaß noch.
MfG

Hallo Matthias,

das Stichwort heisst Subclassing :smile:
Du programmierst einfach eine Callback Function :wink:
Schaue dich mal um nach Video for Windows, da findest du dazu ne menge anleitungen, wie das Funktioniert. Nur leider wird das Bild der Cam in einem neuen Fenster erzeugt, worauf du keinen Zugriff hast.

Wenn du magst poste ich dir gerne mal den Quelltext der 2 module und der Form und ein Bild dazustellen.
Aber das ist ne ganze menge .

MFG Alex

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Alex

das Stichwort heisst Subclassing :smile:

Das kenn ich, habe ich mal für einen Bildschirmschoner gemacht, bzw. aus einem Beispiel übernommen.
Wenn Du aber ganz genial sein willst, findest Du raus, wie der Treiber angesprochen wird, ohne im Original-Programm Zeiger zu „verbiegen“.

Jetzt muss ich aber aufhören, weil ich nicht wirklich die Ahnung von Videoprogrammen habe.

Im msdn steht auch noch etwas von Videokanälen und ActivX, DirectShow usw…
MfG
Matthias

Hallo

Ich hab mal eine ergänzende Idee.
Du schreibst unter anderem, du hättest auf das Fenster mit dem Video keinen Zugriff, könntest aber ein Foto von machen.

Also wie wär das?:
Probeweise den Fokus auf das betreffende Window setzen,
per Timer Funktionen auslösen(damit der Fokus sich nicht ändert) um den Titel des Videofensters zu ermitteln.
Dieser Titel sollte immer gleich sein, bzw. hoffentlich hat es einen Titel oder andere eindeutige immer gleiche Eigenschaften.
Nach dem Window mit dem Titel kannst Du dann später suchen, und mit BitBlt den Bildinhalt kopieren.

Den Speicher mit dem Bilddaten ausfindig zu machen, wäre natürlich wesentlich eleganter und eventuell auch schneller.

MfG
Matthias