|
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 |
Elor
Anmeldungsdatum: 12.07.2013 Beiträge: 205 Wohnort: Konstanz
|
Verfasst am: 24.08.2016, 16:40 Titel: |
|
|
nemored hat Folgendes geschrieben: |
Mal zur Verdeutlichung, was ich meine:
Code:
sub testsub(testvar as zstring)
print "SIZEOF: " & sizeof(testvar)
print "LEN: " & len(testvar)
print "value: " & testvar
end sub
dim as zstring*99 testvar = "abc"
testsub(testvar)
|
Heiligs Blechle, genau darin hatte ich eigentlich den Vorteil gesehen. Ich hätte eigentlich erwartet das man die Größe dort auch auslesen kann (hab das vorher aber leider nicht probiert).
grindstone hat Folgendes geschrieben: |
@Elor: Ich fürchte, du verstehst mich immer noch miss.
|
Nein, ganz im Gegenteil, ich hab das mit den Tücken, die du da angesprochen hast, sehr genau verstanden, du aber mich nicht! |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4604 Wohnort: ~/
|
Verfasst am: 24.08.2016, 16:50 Titel: |
|
|
UEZ hat Folgendes geschrieben: | Wie bekomme ich einen Hex String, z.B. ein PNG Bild als Binär Daten abgespeichert, im Speicher gespeichert, um das Bild später mit GDI+ zu streamen? |
Mit CINT oder VAL, VALINT oder welche Version auch immer (BASIC hat so viele schöne Schlüsselwörter ) kannst du einen Hex-String in eine Dezimalzahl umwandeln. Das wäre für deine Stringlänge aber deutlich zu groß; deswegen würde ich den in Blöcken von je zwei Zeichen einlesen, die dann in ein UBYTE umwandeln und das in den Buffer legen.
Code: | dim as string PNG_Image_String = "&h89504E470D0A1A0A000"
' Überprüfung, dass es sich um ein Hex-String handelt, überspringe ich jetzt mal
for i as integer = 3 to len(PNG_Image_String)-1 STEP 2
' Ob die beiden Zeichen im richtigen Bereich 0-f liegen, interessiert mich jetzt auch nicht
print "nächstes UBYTE: "; cubyte("&h" & mid(PNG_Image_String, i, 2))
next
' und dass am Schluss noch eine einsame 0 hängt, habe ich auch nicht berücksichtigt
|
so etwa in der Art.
Elor hat Folgendes geschrieben: | Ich hätte eigentlich erwartet das man die Größe dort auch auslesen kann |
Nein, das geht leider nicht, und das hängt mit der Art zusammen, wie Parameter übergeben werden. Normalerweise ist klar, welche Art von Parameter übergeben wird und wie groß dieser ist, weshalb der Parameter ja auch z. B. AS INTEGER oder AS SINGLE deklariert sein müssen. Bei STRING geht das auch noch problemlos, weil der Header klar definiert ist und dort alle weiteren Informationen drin stehen. Bei einem ZSTRING gibt es aber keinen Header, sondern es wird einfach der Pointer auf den Beginn übergeben; die Länge geht dabei verloren. Ansonsten wäre keine zu anderen Programmiersprachen kompatible Übergabe eines ZSTRING möglich. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 24.08.2016, 17:49 Titel: |
|
|
@nemored: ok danke.
Was habe ich hier falsch gemacht? -> http://pastebin.com/G1jp0wi9
In der Funktion _GDIPlus_BitmapCreateFromMemory. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4604 Wohnort: ~/
|
Verfasst am: 24.08.2016, 19:26 Titel: |
|
|
Du kreierst, wenn ich das richtig sehe, vom Hex-String, und nicht von seinen hexadezimalen Werten. Da steht z. B. ganz am Anfang "89", was du als 137 interpretiert haben willst (vermute ich). Bestenfalls würde er das aber als ASC("8") und ASC("9") interpretieren. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 24.08.2016, 21:03 Titel: |
|
|
nemored hat Folgendes geschrieben: | Du kreierst, wenn ich das richtig sehe, vom Hex-String, und nicht von seinen hexadezimalen Werten. Da steht z. B. ganz am Anfang "89", was du als 137 interpretiert haben willst (vermute ich). Bestenfalls würde er das aber als ASC("8") und ASC("9") interpretieren. |
Eigentlich will ich den Speicher "buffer" mit den UByte Werten vom dem langen Hex String befüllen, so dass das PNG Bild mit GDI+ erstellt werden kann. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4604 Wohnort: ~/
|
Verfasst am: 24.08.2016, 21:46 Titel: |
|
|
Ich denke, du wirst den von PNG_Image() zurückgegebenen String erst noch in der Art meines letzten Quellcodes bearbeiten müssen, sprich: aus ihm einen neuen String erzeugen, den du dann an _GDIPlus_BitmapCreateFromMemory übergeben kannst (allerdings habe ich keine Ahnung, was _GDIPlus_BitmapCreateFromMemory macht und welchen Parameter sie erwartet, daher ist das von meiner Seite nur geraten.
Also von meinem letzten Code ausgehend halt nicht
Code: | print "nächstes UBYTE: "; cubyte("&h" & mid(PNG_Image_String, i, 2)) |
sondern
Code: | bufferString &= chr(cubyte("&h" & mid(PNG_Image_String, i, 2))) |
Oder, wenn du schon einen UBYTE-Puffer hast, dann an die nächste Stelle den Byte-Wert reinschieben. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 24.08.2016, 22:04 Titel: |
|
|
nemored hat Folgendes geschrieben: | Ich denke, du wirst den von PNG_Image() zurückgegebenen String erst noch in der Art meines letzten Quellcodes bearbeiten müssen, sprich: aus ihm einen neuen String erzeugen, den du dann an _GDIPlus_BitmapCreateFromMemory übergeben kannst (allerdings habe ich keine Ahnung, was _GDIPlus_BitmapCreateFromMemory macht und welchen Parameter sie erwartet, daher ist das von meiner Seite nur geraten.
Also von meinem letzten Code ausgehend halt nicht
Code: | print "nächstes UBYTE: "; cubyte("&h" & mid(PNG_Image_String, i, 2)) |
sondern
Code: | bufferString &= chr(cubyte("&h" & mid(PNG_Image_String, i, 2))) |
Oder, wenn du schon einen UBYTE-Puffer hast, dann an die nächste Stelle den Byte-Wert reinschieben. |
Diese Funktion soll den langen Hex String nehmen, die UByte Werte in den Buffer schreiben, einen Stream erstellen und diesen Stream an GdipCreateBitmapFromStream übergeben, so dass GdipCreateBitmapFromStream das Bild erstellen kann:
Code: | Function _GDIPlus_BitmapCreateFromMemory(binImage As String, bBitmap_GDI As Bool = FALSE) As Any Ptr
Dim As ULong iLen, i, j = 0
Dim As HGLOBAL hGlobal
Dim As LPSTREAM hStream
Dim As Any Ptr hBitmap
Dim buffer As UByte Ptr
iLen = Len(binImage) / 2
buffer = Allocate(iLen * SizeOf(UByte))
For i = 1 To Len(binImage) Step 2
buffer[j] = CUByte("&h" & Mid(binImage, i, 2))
j += 1
Next
Var hMemory = GlobalAlloc(GMEM_MOVEABLE, iLen)
Var lpMemory = GlobalLock(hMemory)
RtlCopyMemory(lpMemory, buffer, iLen)
GlobalUnlock(hMemory)
CreateStreamOnHGlobal(hGlobal, 0, @hStream)
GdipCreateBitmapFromStream(hStream, @hBitmap)
IUnknown_Release(hStream)
Deallocate(buffer)
If bBitmap_GDI = TRUE Then
Dim hBitmap_GDI As Any Ptr
GdipCreateHBITMAPFromBitmap(hBitmap, @hBitmap_GDI, &hFF000000)
GdipDisposeImage(hBitmap)
Return hBitmap_GDI
EndIf
Return hBitmap
End Function |
Irgendwo ist noch ein Fehler, da das Bild nicht erstellt werden kann. Vermutlich liegt der Fehler in den oberen Zeilen von GdipCreateBitmapFromStream.
Den kompletten Code hatte ich auf Pastebin gepostet, um nicht den Rahmen hier zu sprengen, da der Hex String relativ lang ist. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
St_W
Anmeldungsdatum: 22.07.2007 Beiträge: 949 Wohnort: Austria
|
Verfasst am: 24.08.2016, 22:54 Titel: |
|
|
Hab ich das richtig verstanden, dass du einen hexString (z.B. "ABCD") als Eingabe hast und dessen Wert (als Binärdaten) ermitteln willst (z.B. 0xABCD)? Falls nein kannst du gleich meine Vorschläge unterhalb ignorieren
Du könntest natürlich mit VAL("&H" + MID(inputString, ..., 2)) oder ähnlich den String mit Hilfsfunktionen der FB Runtime Lib Stück für Stück konvertieren, aber das wird wohl sehr schnell sehr inperformant.
Besser ist es wenn du dir die entsprechende Konvertierung von Hex Strings in Hex-Werte selbst implementierst und anstatt ständig neue Strings zu erstellen mit Pointern arbeitest (der String-Indizierungs-Operator [] wird hier sehr hilfreich sein). Ein Beispiel:
https://opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/LocalTests/XTSTest/hexString.c _________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 24.08.2016, 23:17 Titel: |
|
|
@ST_W: ich will nichts ermitteln, sondern der Hex Code ist vorgegeben, d.h. ich habe das Bild in diesen Hex String umgewandelt.
Du hast mit GDI+ die Möglichkeit ein Binärstring, welches als Binärstring in dem Source Code mitkompiliert werden kann, zu laden und z.B. in der GUI darzustellen.
Ich weiß, dass dies funktioniert, aber nicht wie in FB. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4604 Wohnort: ~/
|
Verfasst am: 25.08.2016, 00:29 Titel: |
|
|
Ok, ich gebe zu, ich sollte gelegentlich mal genauer lesen.
Die Daten scheinen wie gewünscht in den buffer zu kommen. Andere Idee: Wenn du einen Stream erstellst, ist es dann möglicherweise unvorteilhaft, den Speicher zu dealloziieren, bevor du mit dem Stream-Zugriff fertig bist? Der greift ja dann vermutlich nachher auf bereits freigegebenen Speicher zu (ich denke nicht, dass er eine Kopie des Inhalts anlegt). _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 25.08.2016, 01:26 Titel: |
|
|
@UEZ: Das Bild an sich wird korrekt erstellt. Es ist eine Art roter Schwimmreifen auf schwarzem Grund mit einer Größe von 193 x 184 Pixeln. Mit der eingefügten Zeile kannst du das Bild aus der Function herausziehen. Code: | Function _GDIPlus_BitmapCreateFromMemory(binImage As String, bBitmap_GDI As Bool = FALSE) As Any Ptr
Dim As ULong iLen, i, j = 0
Dim As HGLOBAL hGlobal
Dim As LPSTREAM hStream
Dim As Any Ptr hBitmap
Dim buffer As UByte Ptr
iLen = Len(binImage) / 2
buffer = Allocate(iLen * SizeOf(UByte))
For i = 1 To Len(binImage) Step 2
buffer[j] = CUByte("&h" & Mid(binImage, i, 2))
j += 1
Next
BSave(ExePath + "\bild.png", buffer, j)'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Var hMemory = GlobalAlloc(GMEM_MOVEABLE, iLen)
Var lpMemory = GlobalLock(hMemory)
RtlCopyMemory(lpMemory, buffer, iLen)
GlobalUnlock(hMemory)
'CreateStreamOnHGlobal(hGlobal, 0, @hStream)
CreateStreamOnHGlobal(hMemory, 0, @hStream)'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
GdipCreateBitmapFromStream(hStream, @hBitmap)
IUnknown_Release(hStream)
Deallocate(buffer)
If bBitmap_GDI = TRUE Then
Dim hBitmap_GDI As Any Ptr
GdipCreateHBITMAPFromBitmap(hBitmap, @hBitmap_GDI, &hFF000000)
GdipDisposeImage(hBitmap)
Return hBitmap_GDI
EndIf
Return hBitmap
End Function | Der von der Function zurückgegebene Pointer hBitmap ist allerdings 0. Vermutlich geht in der GdipCreateBitmapFromStream etwas schief.
Gruß
grindstone
EDIT: Fehler gefunden. Siehe 2. markierte Zeile. _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
St_W
Anmeldungsdatum: 22.07.2007 Beiträge: 949 Wohnort: Austria
|
Verfasst am: 25.08.2016, 03:43 Titel: |
|
|
UEZ hat Folgendes geschrieben: | Code: |
[...]
Dim buffer As UByte Ptr
iLen = Len(binImage) / 2
buffer = Allocate(iLen * SizeOf(UByte))
For i = 1 To Len(binImage) Step 2
buffer[j] = CUByte("&h" & Mid(binImage, i, 2))
j += 1
Next
[...]
|
|
Sorry, ich hatte auch nur überflogen und nicht genau gelesen, aber ich glaube doch genau das hier gemeint zu haben. Anstatt hier für jedes 2. Byte einen neuen String zusammenzubasteln könntest du so machen wie im oben verlinkten Code.
Falls du allerdings ohnehin die ganzen Daten statisch definieren willst, kannst du gleich die Daten entsprechend aufbereiten, z.B.: Code: | dim as ubyte x(...) = { &h10, &h20, &hAB, &HCD, &hEF } |
_________________ Aktuelle FreeBasic Builds, Projekte, Code-Snippets unter http://users.freebasic-portal.de/stw/
http://www.mv-lacken.at Musikverein Lacken (MV Lacken) |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 25.08.2016, 09:39 Titel: |
|
|
@grindstone: Danke, das hatte ich in der Tat übersehen und ich habe vielleicht den Code 100x durchgesehen! Jetzt funktioniert's.
Ich muss jetzt nocht testen, ob der Speicher wieder freigegeben wird. Dann will ich noch den Hex String durch Base64 oder was ähnlichem ersetzen.
@St_W: das muss ich mir duch den Kopf gehen lassen, gleich den Code zu erstellen, aber ich weiß nicht, ob RtlCopyMemory auch ein Array akzeptiert. _________________ Gruß,
UEZ |
|
Nach oben |
|
|
nemored
Anmeldungsdatum: 22.02.2007 Beiträge: 4604 Wohnort: ~/
|
Verfasst am: 25.08.2016, 10:43 Titel: |
|
|
Zitat: | @St_W: das muss ich mir duch den Kopf gehen lassen, gleich den Code zu erstellen, aber ich weiß nicht, ob RtlCopyMemory auch ein Array akzeptiert. |
Sollte aber funktionieren, wenn du einen Pointer auf das erste Array-Element übergibst. Im Speicher hängen da auch nur einfach alle Werte hintereinander.
edit: Tippfehler korrigiert _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Zuletzt bearbeitet von nemored am 25.08.2016, 15:05, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1215 Wohnort: Ruhrpott
|
Verfasst am: 25.08.2016, 11:09 Titel: |
|
|
UEZ hat Folgendes geschrieben: | ...ich habe vielleicht den Code 100x durchgesehen! | Ja, das ist einer von diesen gemeinen Fehlern, die sich ganz klein machen und sich nicht bewegen, wenn man hinschaut.
Elor hat Folgendes geschrieben: | Nein, ganz im Gegenteil, ich hab das mit den Tücken, die du da angesprochen hast, sehr genau verstanden, du aber mich nicht! | Ein Fall für die Philosophen: Wenn zwei der gleichen Meinung sind, bedeutet das nicht zwingend, daß Harmonie herrscht.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
|
UEZ
Anmeldungsdatum: 24.06.2016 Beiträge: 129 Wohnort: Opel Stadt
|
Verfasst am: 25.08.2016, 14:27 Titel: |
|
|
Der vollständige Code hier nochmals ohne den langen Hex String; den gibt auf Pastebin -> http://pastebin.com/G1jp0wi9
Code: | 'coded by UEZ build 2016-08-25
#include "fbgfx.bi"
#include "win/gdiplus.bi"
Using FB
Using GDIPLUS
Declare Function _GDIPlus_BitmapCreateFromMemory(ByRef binImage As String, bBitmap_GDI As Bool = FALSE) As Any Ptr
Declare Function PNG_Image() As String
Dim Shared gdipToken As ULONG_PTR
Dim GDIp As GdiplusStartupInput
GDIp.GdiplusVersion = 1
GdiplusStartup(@gdipToken, @GDIp, NULL)
Dim As Single iW_Img, iH_Img
Dim As Any Ptr hImage
Dim binString As String = PNG_Image()
hImage = _GDIPlus_BitmapCreateFromMemory(binString)
GdipGetImageDimension(hImage, @iW_Img, @iH_Img)
binString = ""
ScreenControl FB.SET_DRIVER_NAME, "GDI"
ScreenRes iW_Img, iH_Img, 32
WindowTitle "GDI+ Create Bitmap from Memory by UEZ"
Dim as HWND hHWND
ScreenControl(FB.GET_WINDOW_HANDLE, Cast(Integer, hHWND))
Dim As Any Ptr hCanvas, hTexture, hBrush, hBitmap, hGfx
GdipCreateFromHWND(hHWND, @hCanvas)
'erstelle Schachbrett Muster
GdipCreateBitmapFromScan0(16, 16, 0, PixelFormat32bppARGB, 0, @hBitmap)
GdipGetImageGraphicsContext(hBitmap, @hGfx)
GdipGraphicsClear(hGfx, &hFFE8E8E8)
GdipCreateSolidFill(&hFFF8F8F8, @hBrush)
GdipFillRectangle(hGfx, hBrush, 0, 0, 8, 8)
GdipFillRectangle(hGfx, hBrush, 8, 8, 8, 8)
GdipCreateTexture(hBitmap, 0, @hTexture)
GdipFillRectangle(hCanvas, hTexture, 0, 0, iW_Img, iW_Img)
GdipDrawImageRect(hCanvas, hImage, 0, 0, iW_Img, iH_Img)
Dim evt As EVENT
Do
If (ScreenEvent(@evt)) Then
Select Case evt.Type
Case SC_ESCAPE, EVENT_WINDOW_CLOSE
GdipDeleteBrush(hBrush)
GdipDeleteBrush(hTexture)
GdipDisposeImage(hImage)
GdipDisposeImage(hBitmap)
GdipDeleteGraphics(hCanvas)
GdipDeleteGraphics(hGfx)
GdiplusShutdown(gdipToken)
Exit Do
End Select
EndIf
Sleep(20)
Loop
Function _GDIPlus_BitmapCreateFromMemory(ByRef binImage As String, bBitmap_GDI As Bool = FALSE) As Any Ptr
Dim As ULong iLen, i, j = 0
Dim As HGLOBAL hGlobal
Dim As LPSTREAM hStream
Dim As Any Ptr hBitmap
Dim buffer As UByte Ptr
iLen = Len(binImage) / 2
buffer = Allocate(iLen * SizeOf(UByte))
For i = 1 To Len(binImage) Step 2
buffer[j] = CUByte("&h" & Mid(binImage, i, 2))
j += 1
Next
Var hMemory = GlobalAlloc(GMEM_MOVEABLE, iLen)
Var lpMemory = GlobalLock(hMemory)
RtlCopyMemory(lpMemory, buffer, iLen)
GlobalUnlock(hMemory)
CreateStreamOnHGlobal(hMemory, 0, @hStream)
GdipCreateBitmapFromStream(hStream, @hBitmap)
IUnknown_Release(hStream)
Deallocate(buffer)
If bBitmap_GDI = TRUE Then
Dim hBitmap_GDI As Any Ptr
GdipCreateHBITMAPFromBitmap(hBitmap, @hBitmap_GDI, &hFF000000)
GdipDisposeImage(hBitmap)
Return hBitmap_GDI
EndIf
Return hBitmap
End Function |
_________________ 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.
|
|