|
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 21.07.2016, 17:17 Titel: GDI+ Funktion GdipCreateBitmapFromScan0 |
|
|
Wie kann ich unter FB den Scan0 Parameter in der GDI+ Funktion GdipCreateBitmapFromScan0 implementieren, um direkt in die Bitmap zu zeichnen? Ich möchte nicht die Funktion GdipBitmapLockBits benutzen!
Dokumentation zu dieser Funktion: "https://msdn.microsoft.com/en-us/library/windows/desktop/ms536315(v=vs.85).aspx"
Was ich bisher versucht habe:
Code: | #Include Once "win\gdiplus.bi"
Using GDIPLUS
Declare Function Test(ByVal hImage As Any Ptr = 0) As Any Ptr
Type tBitmapData
scan0(0 To 512 * 4) As UByte
End Type
Function Test(ByVal hImage As Any Ptr = 0) As Any Ptr
Dim As Single iW, iH
Dim As Any Ptr hBitmap
Dim bmp AS BITMAPDATA
Dim As Integer iStatus
Dim As UByte Ptr pARGB
Dim pBitmapData As tBitmapData
GdipCreateBitmapFromScan0(512, 512, 512 * 4, PixelFormat32bppARGB, @pBitmapData, @hBitmap)
'GdipCreateBitmapFromScan0(512, 512, 512 * 4, PixelFormat32bppARGB, 0, @hBitmap)
Return hBitmap
End Function
Dim GDIPlusStartupInput As GDIPLUSSTARTUPINPUT
Dim As ULONG_PTR GDIPlusToken
GDIPlusStartupInput.GdiplusVersion = 1
If (GdiplusStartup(@GDIPlusToken, @GDIPlusStartupInput, NULL) <> 0) Then
Print "FAILED TO INIT GDI+!"
EndIf
Dim hBmp_new As Any Ptr
hBmp_new = Test()
Print "Handle: ";hBmp_new
Dim CLSID_01 As CLSID
CLSIDFROMSTRING(WStr("{557CF406-1A04-11D3-9A73-0000F81EF32E}"), @CLSID_01)
If (GdipSaveImageToFile(hBmp_new, WStr("1.png"), @CLSID_01 , NULL) <> 0) Then
Print "Image save has FAILED!"
EndIf
GdipDisposeImage(hBmp_new)
GdiplusShutdown(GDIPlusToken)
Sleep |
Danke. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 21.07.2016, 19:38 Titel: |
|
|
Du brauchst den Pointer auf den Inhalt des Arrays, also vmtl @pBitmapData .scan0(0) und nicht @pBitmapData . _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 21.07.2016, 20:58 Titel: |
|
|
Jojo hat Folgendes geschrieben: | Du brauchst den Pointer auf den Inhalt des Arrays, also vmtl @pBitmapData .scan0(0) und nicht @pBitmapData . |
Wenn ich den Code mit
Code: | GdipCreateBitmapFromScan0(512, 512, 512 * 4, PixelFormat32bppARGB, @pBitmapData.scan0(0), @hBitmap) |
ausführe, dann stürzt die Exe ab (wahrscheinlich mit einer Speicherschutzverletzung). _________________ Gruß,
UEZ |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 21.07.2016, 21:06 Titel: |
|
|
Dein Array ist ja auch viel zu klein. Da passt eine Zeile rein, und du gibst an, dass das Bild 512 Zeilen hat. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 21.07.2016, 23:06 Titel: |
|
|
Jojo hat Folgendes geschrieben: | Dein Array ist ja auch viel zu klein. Da passt eine Zeile rein, und du gibst an, dass das Bild 512 Zeilen hat. |
Stimmt. 32Bit hat 4 Bytes pro Pixel. Somit sollte 512 * 512 * 4 das Array groß sein.
Code: | #Include Once "win\gdiplus.bi"
Using GDIPLUS
Declare Function Test(ByVal hImage As Any Ptr = 0) As Any Ptr
Type tBitmapData
scan0(0 To 512 * 512 * 4) As UByte
End Type
Function Test(ByVal hImage As Any Ptr = 0) As Any Ptr
Dim As Single iW, iH
Dim As Any Ptr hBitmap
Dim bmp AS BITMAPDATA
Dim As Integer iStatus
Dim As UByte Ptr pARGB
Dim pBitmapData As tBitmapData
GdipCreateBitmapFromScan0(512, 512, 512 * 4, PixelFormat32bppARGB, @pBitmapData.scan0(0), @hBitmap)
Return hBitmap
End Function
Dim GDIPlusStartupInput As GDIPLUSSTARTUPINPUT
Dim As ULONG_PTR GDIPlusToken
GDIPlusStartupInput.GdiplusVersion = 1
If (GdiplusStartup(@GDIPlusToken, @GDIPlusStartupInput, NULL) <> 0) Then
Print "FAILED TO INIT GDI+!"
EndIf
Dim hBmp_new As Any Ptr
hBmp_new = Test()
Print "Handle: ";hBmp_new
Dim CLSID_01 As CLSID
CLSIDFROMSTRING(WStr("{557CF406-1A04-11D3-9A73-0000F81EF32E}"), @CLSID_01)
If (GdipSaveImageToFile(hBmp_new, WStr("1.png"), @CLSID_01 , NULL) <> 0) Then
Print "Image save has FAILED!"
EndIf
GdipDisposeImage(hBmp_new)
GdiplusShutdown(GDIPlusToken)
Sleep |
Hmmm, funktioniert trotzdem nicht. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 22.07.2016, 02:24 Titel: |
|
|
Manchmal hilft es, die verlinkte Dokumentation zu lesen.
Zitat: | Pointer to an array of bytes that contains the pixel data. The caller is responsible for allocating and freeing the block of memory pointed to by this parameter. |
Das von dir erstellte Array verliert nach verlassen der Test-Funktion seine Gültigkeit. Es muss aber mindestens bis zum GdipDisposeImage verfügbar sein, sonst schreibt oder liest GDI+ Speicher, der schon freigegeben wurde!
Code: | #Include Once "win\gdiplus.bi"
Using GDIPLUS
Declare Function Test(ByVal hImage As Any Ptr = 0) As Any Ptr
Dim Shared As Byte bitmap(0 To (512 * 512 * 4) - 1)
Function Test(ByVal hImage As Any Ptr = 0) As Any Ptr
Dim As Single iW, iH
Dim As Any Ptr hBitmap
Dim bmp AS BITMAPDATA
Dim As Integer iStatus
GdipCreateBitmapFromScan0(512, 512, 512 * 4, PixelFormat32bppARGB, @bitmap(0), @hBitmap)
Return hBitmap
End Function
Dim GDIPlusStartupInput As GDIPLUSSTARTUPINPUT
Dim As ULONG_PTR GDIPlusToken
GDIPlusStartupInput.GdiplusVersion = 1
If (GdiplusStartup(@GDIPlusToken, @GDIPlusStartupInput, NULL) <> 0) Then
Print "FAILED TO INIT GDI+!"
EndIf
Dim hBmp_new As Any Ptr
hBmp_new = Test()
Print "Handle: ";hBmp_new
For i As Integer = 0 To UBound(bitmap)
bitmap(i) = i
Next
Dim CLSID_01 As CLSID
CLSIDFROMSTRING(WStr("{557CF406-1A04-11D3-9A73-0000F81EF32E}"), @CLSID_01)
If (GdipSaveImageToFile(hBmp_new, WStr("C:\1.png"), @CLSID_01 , NULL) <> 0) Then
Print "Image save has FAILED!"
EndIf
GdipDisposeImage(hBmp_new)
GdiplusShutdown(GDIPlusToken)
Sleep |
_________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 22.07.2016, 09:40 Titel: |
|
|
Jojo hat Folgendes geschrieben: | Manchmal hilft es, die verlinkte Dokumentation zu lesen.
Zitat: | Pointer to an array of bytes that contains the pixel data. The caller is responsible for allocating and freeing the block of memory pointed to by this parameter. |
Das von dir erstellte Array verliert nach verlassen der Test-Funktion seine Gültigkeit. Es muss aber mindestens bis zum GdipDisposeImage verfügbar sein, sonst schreibt oder liest GDI+ Speicher, der schon freigegeben wurde!
|
Danke Jojo.
Nun ja, ich dachte, dass ich mit
Code: | Type tBitmapData
scan0(1 To 512 * 512 * 4) As Byte
End Type |
den Speicherblock zugeteilt habe, zumal ich in der Funktion die Pixel setzen möchte.
Ok, über die FB Internas gibt es noch viel zu lernen, was wann zugreifbar ist und wann nicht.
Btw, wie kann ich
Code: | Dim Shared As Byte bitmap(0 To (512 * 512 * 4) - 1) |
dynamisch halten, wenn ich z.B. dieses Array anhand eines geladenen Bildes erstellen möchte? _________________ Gruß,
UEZ |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 22.07.2016, 13:34 Titel: |
|
|
Zitat: | den Speicherblock zugeteilt habe, zumal ich in der Funktion die Pixel setzen möchte. |
Nein, ein TYPE ist quasi nur eine Vorlage für ein später zu erstellendes Objekt. Du musst entweder ein Array im globalen Scope erstellen (so wie ich das hier im Beispiel gemacht habe, was aber ziemlich unsauber ist) oder das Array mit NEW dynamisch erstellen und mit DELETE nach Verwendung wieder löschen.
Zitat: | Dim Shared As Byte bitmap(0 To (512 * 512 * 4) - 1) |
Die Frage verstehe ich nicht ganz - du möchtest ein Bild von der Platte in ein vordefiniertes Array packen? Wenn ja, musst du schauen welche GDI+-Funktionen sich dafür anbieten. Höchstwahrscheinlich wird es aus Sicherheitsgründen keine Funktion geben, die beliebige Bilder von der Platte in ein Array lesen kann (da du ja im Allgemeinen vorher nicht weißt, wie groß das Array sein muss), aber du kannst sicher das Bild normal laden und dann in dein Array rüberkopieren. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 22.07.2016, 14:45 Titel: |
|
|
Zitat: | Die Frage verstehe ich nicht ganz - du möchtest ein Bild von der Platte in ein vordefiniertes Array packen? Wenn ja, musst du schauen welche GDI+-Funktionen sich dafür anbieten. Höchstwahrscheinlich wird es aus Sicherheitsgründen keine Funktion geben, die beliebige Bilder von der Platte in ein Array lesen kann (da du ja im Allgemeinen vorher nicht weißt, wie groß das Array sein muss), aber du kannst sicher das Bild normal laden und dann in dein Array rüberkopieren. |
Ich hatte bereits ein Thema zu GDI+ und Multithreading aufgemacht, nur ist diese Lösung keine performante Lösung, da sie, je höher der Threadanteil, langsamer läuft.
Was ich im Prinzip machen will ist ein Bild laden und dieses Bild per Multi Threading manipulieren (z.B. Median Filter). Die DLL mit den diversen Filtern habe ich bereits fertig gestellt, wollte aber die "langsamen" Funktionen per Multi Threading beschleunigen.
Da das Array von dem Quell Bild abhängt, muss es dynamisch erstellt werden. Die 512x512 Pixel waren nur Test, um zu verstehen, wie ich das implementieren kann. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|