Seite 1 von 2
RGB-Bytearray konvertieren
Verfasst: 24.04.2005 04:02
von garfield9992003
Hallo miteinander.
Ein Grafikproblem zwingt mich zum wachbleiben
Ich habe ein RGB-Bytearray, zudem ist die Anzahl der Pixel pro Linie (*3=Bytes/Linie) und die Anzahl der Linien gegeben. (Farbtiefe=16bit)
Wie bewege ich Purebasic dazu, das Ganze in einem brauchbaren Format zu speichern? Mit CatchImage kam ich auf keine Ergebnisse.
Mit RGB() kann man ja die Farbwerte wandeln. Aber dann weis ich immer noch nicht so recht, wie ich das Bild als Bitmap oder JPG speichern könnte.
Hat vielleicht jemand eine Idee? Oder sehe ich den Wald vor lauter Bäumen nicht.
Grüße
Frank
Verfasst: 24.04.2005 15:14
von garfield9992003
Ergänzung:
Beispiel für meine gegebene Situation:
472 Pixel/Linie * 3 Bytes(RGB) ---> 1416 Bytes/Linie
945 Linien Bildhöhe
----> macht ein Bytearray mit 1338120 Bytes Rohdaten
Es sollen dann ggfs. Ausgaben in BMP, JPG, TIFF möglich sein.
Und das ohne kostenpflichtige 3rd Party-Tools.
Natürlich variiert später auch die Farbtiefe des Bildes und so - aber das ist kein Problem, wenn ich ersteinmal den Lösungsansatz für mein Beispiel habe.
Grüße
Verfasst: 24.04.2005 15:25
von Lukaso
Hier mal nen anstoß:
Code: Alles auswählen
img = CreateImage(0, BreiteInPixel, HoeheInPixel)
If img
StartDrawing(ImageOutput())
For y = 1 To HoeheInPixel
For x = 1 To BreiteInPixel
Plot(x, y RGB(r, g, b))
Next
Next
StopDrawing()
SaveImage(0, "C:\test.bmp", #PB_ImagePlugin_BMP)
EndIf
Code nicht getestet!
MFG Lukaso
Verfasst: 24.04.2005 15:31
von Danilo
garfield9992003 hat geschrieben:Ergänzung:
Jetzt hab ich es verstanden.
garfield9992003 hat geschrieben:Beispiel für meine gegebene Situation:
472 Pixel/Linie * 3 Bytes(RGB) ---> 1416 Bytes/Linie
945 Linien Bildhöhe
----> macht ein Bytearray mit 1338120 Bytes Rohdaten
Es sollen dann ggfs. Ausgaben in BMP, JPG, TIFF möglich sein.
Und das ohne kostenpflichtige 3rd Party-Tools.
CreateImage(1, 472, 945)
Danach alle Pixel des Arrays in einer Schleife auf das Bild
zeichnen, mit Plot(x,y,RGB( array(x,y)\r, array(x,y)\g, array(x,y)\b )).
Mit SaveImage und dem gewünschten Encoder (PNG,JPEG)
speichern.
Diese Methode sollte Platformunabhängig sein.
Auf Windows kannst Du das zeichnen der Pixel noch über
SetDIBits_() beschleunigen. Beispiele dazu findest Du im
CodeArchiv auf PureArea.net oder per Forensuche im alten
Forum.
Verfasst: 24.04.2005 15:54
von garfield9992003
Habt im Moment vielen Dank, ich werde mir das nun ansehen und berichten. Tempo spielt natürlich eine Rolle - Aber da bin ich von PureBasic noch nie enttäuscht worden
Grüße
Frank
Verfasst: 24.04.2005 22:16
von garfield9992003
Ich habe mich nun einige Stunden mit dem Thema beschäftigt.
Euer Vorschlag funktioniert auch im etwa so.
Nur verstehe ich nun nicht, warum alle weissen Pixel schwarz dargestellt werden... *kopfkratz*
Die schnellste Lösung wäre bestimmt mit Drawingbuffer/CopyMemory das Bytearray direkt in den Speicherbereich von Createimage zu kopieren- jedoch bei ImageOutput funktioniert der DrawingBuffer wohl nicht.
Bei einer DinA4-Seite mit 300 dpi dauert das For-Plot-Next jedoch
Tipps, wie es mit CopyMem doch gehen könnte?
Grüße
Frank
Verfasst: 24.04.2005 22:56
von Lukaso
garfield9992003 hat geschrieben:Nur verstehe ich nun nicht, warum alle weissen Pixel schwarz dargestellt werden... *kopfkratz*
Vll. verwächselst du RGB(0, 0, 0) mit RBG(255, 255, 255)? Einfach ne If Abfrage um es wieder gerade zu biegen
MFG Lukaso
Verfasst: 25.04.2005 13:24
von NicTheQuick
Das Problem wird sicherlich sein, dass ein Image im Speicher pro Bildpunkt immer 32 Bit verwendet und dann funktioniert das mit dem [c]CopyMemory()[/c] nicht so einfach.
Also entweder musst du die Struktur des Arrays auf 4 Bytes erhöhen oder du musst Danilos Methode benutzen.
Und für Danilos Methode hätte ich noch eine Ergänzung. Wenn die Bytes
[c]r.b[/c], [c]g.b[/c] und [c]b.b[/c] in der Struktur sind, sind sie in Purebasic somit auch signed. Das heißt, das müssen wir nch ändern. Also so:
Code: Alles auswählen
Plot(x,y,RGB(array(x,y)\r & $FF, array(x,y)\g & $FF, array(x,y)\b & $FF))
Verfasst: 25.04.2005 14:20
von garfield9992003
Danke für den Hinweis mit dem Signed Byte.... Klar, nun sind meine schwarzen Pixel auch weiss. Da hätte ich nun nicht mehr dran gedacht.
Frank
Verfasst: 25.04.2005 14:37
von Danilo
garfield9992003 hat geschrieben:Bei einer DinA4-Seite mit 300 dpi dauert das For-Plot-Next jedoch

Sagte ich doch, weshalb ich Dir oben schon SetDIBits_()
vorschlug.
Code: Alles auswählen
;
; by Danilo, 25.04.2005
;
#ImageWidth = 500
#ImageHeight = 255
Procedure Mem2Image(Image,Width,Height,mem)
Structure _LTI_BITMAPINFO
bmiHeader.BITMAPINFOHEADER
bmiColors.RGBQUAD[1]
EndStructure
hBmp = UseImage(Image)
If hBmp
hDC = StartDrawing(ImageOutput())
If hDC
bmi._LTI_BITMAPINFO
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiheader\biWidth = Width
bmi\bmiheader\biHeight = Height
bmi\bmiheader\biPlanes = 1
bmi\bmiheader\biBitCount = 24
bmi\bmiheader\biCompression = #BI_RGB
If SetDIBits_(hDC,hBmp,0,ImageHeight(),mem,bmi,#DIB_RGB_COLORS) <> 0
Result = hBmp
EndIf
StopDrawing()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Structure _RGB
r.b
g.b
b.b
EndStructure
; alloc memory array
mem = AllocateMemory(#ImageWidth*#ImageHeight*SizeOf(_RGB))
If mem=0 : MessageRequester("ERROR","Cant allocate memory!"):End : EndIf
; fill memory array
For y = 0 To #ImageHeight-1
RtlFillMemory_(mem+y*#ImageWidth*SizeOf(_RGB),#ImageWidth*SizeOf(_RGB),y)
Next
; create image
image1 = CreateImage(1,#ImageWidth,#ImageHeight)
If image1
; copy memory array to image
Mem2Image(1,#ImageWidth,#ImageHeight,mem)
OpenWindow(0,0,0,ImageWidth(),ImageHeight(),#PB_Window_ScreenCentered|#PB_Window_SystemMenu,"Image")
CreateGadgetList(WindowID())
ImageGadget(0,0,0,ImageWidth(),ImageHeight(),image1)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Else
MessageRequester("ERROR","Cant load image!",#MB_ICONERROR)
EndIf
Dabei solltest Du beachten das dieses Bild falschrum ist,
d.h. die erste Zeile im Bild ist im SpeicherArray die unterste
Zeile.
PB-Arrays kann man aber nicht einfach so als geradlinigen
Speicher ansprechen, da in PB x und y verkehrt herum sind.
Deshalb kann man PB-Arrays mit C oder mit WinAPI nicht
einfach nutzen.