Seite 1 von 1
Bild mit GetDIBits_ gelesen wird nicht richtig dargestellt
Verfasst: 07.10.2008 14:14
von Thomas_freak
Hallo, ich bin neu hier.
Ich habe ein jpg mit GetDIBits_ pder Pointer in ein Array ausgelesen und möchte dieses weiterverarbeiten, leider habe ich bei der Überprüfung gesehen, dass es nicht richtig funktioniert. Das Bild wird verzerrt angezeigt und die Farbe rot scheint zu fehlen, zumindest ist eine rote Rose bzw. das Gewirr, dort wo sie sein müsste, jetzt blau.
Hat jemand eine idee?
Code: Alles auswählen
Procedure CopyImageToMem(Img.l, mem.l)
Protected bmi.BITMAPINFO
Protected w.l, h.l, hBmp.l, hDC.l
w = ImageWidth(Img)
h = ImageHeight(Img)
hBmp = ImageID(Img)
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiHeader\biWidth = w
bmi\bmiHeader\biHeight = -h
bmi\bmiHeader\biPlanes = 1
bmi\bmiHeader\biBitCount = 32
bmi\bmiHeader\biCompression = #BI_RGB
hDC = StartDrawing( ImageOutput(Img) )
If GetDIBits_(hDC, hBmp, 0, h, mem, bmi, #DIB_RGB_COLORS)
StopDrawing()
ProcedureReturn #True
Else
StopDrawing()
ProcedureReturn #False
EndIf
EndProcedure
Verfasst: 07.10.2008 17:01
von NicTheQuick
Wahrscheinlich sind Rot und Blau einfach nur vertauscht.
Außerdem nutzt du als Pointer besser '*mem', damit das Programm bei
64-Bit-Systemen auch funktoniert. Ein Long (.l) hat immer 32 Bit, während
sich Integer (.i) und Pointer (*) immer an das zugrunde liegende System
anpassen.
Verfasst: 07.10.2008 17:10
von Thomas_freak
Wie meinst du das mit *mem als Pointer?
Ich brauche das Bild nach dem Laden in einem Array, in dem ich auf Zeile und Spalte Zugriff habe.
Verfasst: 07.10.2008 18:04
von Fluid Byte
Poste mal den kompletten code und das Bild.
Verfasst: 07.10.2008 18:28
von Thomas_freak
Code: Alles auswählen
OpenWindow(fenster,10,10,500,900,"Kantendetektion RGB")
bild1=LoadImage(#PB_Any,"E:\Hobby\Programmieren\BlitzBasic\3DBild\rosen1.bmp")
breite=ImageWidth(bild1)
hoehe=ImageHeight(bild1)
Dim bildarray1.l(breite,hoehe)
Dim bildarray2.l(breite,hoehe)
Procedure CopyImageToMem(Img.l, *mem)
Protected bmi.BITMAPINFO
Protected w.l, h.l, hBmp.l, hDC.l
w = ImageWidth(Img)
h = ImageHeight(Img)
hBmp = ImageID(Img)
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiHeader\biWidth = w
bmi\bmiHeader\biHeight = h
bmi\bmiHeader\biPlanes = 1
bmi\bmiHeader\biBitCount = 32
bmi\bmiHeader\biCompression = #BI_RGB
hDC = StartDrawing( ImageOutput(Img) )
If GetDIBits_(hDC, hBmp, 0, h, *mem, bmi, #DIB_RGB_COLORS)
StopDrawing()
ProcedureReturn #True
Else
OpenConsole()
StopDrawing()
ProcedureReturn #False
EndIf
EndProcedure
ba1=@bildarray1()
CopyImageToMem(bild1,ba1)
StartDrawing(WindowOutput(fenster))
For y=1 To hoehe
For x=1 To breite
Plot(x,y,bildarray1(x,y))
Next x
Next y
Delay(4000)
End
Das Bild konnte ich leider nicht vom Bildschirm ins Clipboard bekommen, es sah so aus, als wäre das Programm gar nicht da.
Verfasst: 07.10.2008 19:17
von NicTheQuick
So funktionierts bei mir:
Code: Alles auswählen
#fenster = 1
UseJPEGImageDecoder()
bild1 = LoadImage(#PB_Any, "C:\Logorollo.jpg")
breite = ImageWidth(bild1)
hoehe = ImageHeight(bild1)
If OpenWindow(#fenster, 10, 10, breite, hoehe, "Kantendetektion RGB") = 0 : End : EndIf
Dim bildarray1.l(hoehe - 1, breite - 1)
Dim bildarray2.l(hoehe - 1, breite - 1)
Procedure CopyImageToMem(Img.l, *mem)
Protected bmi.BITMAPINFO
Protected w.l, h.l, hBmp.l, hDC.l
w = ImageWidth(Img)
h = ImageHeight(Img)
hBmp = ImageID(Img)
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiHeader\biWidth = w
bmi\bmiHeader\biHeight = h
bmi\bmiHeader\biPlanes = 1
bmi\bmiHeader\biBitCount = 32
bmi\bmiHeader\biCompression = #BI_RGB
hDC = StartDrawing(ImageOutput(Img))
If GetDIBits_(hDC, hBmp, 0, h, *mem, bmi, #DIB_RGB_COLORS)
StopDrawing()
ProcedureReturn #True
Else
OpenConsole()
StopDrawing()
ProcedureReturn #False
EndIf
EndProcedure
If CopyImageToMem(bild1, @bildArray1())
Repeat
Select WaitWindowEvent()
Case #PB_Event_Repaint
If StartDrawing(WindowOutput(#fenster))
For y = 0 To hoehe - 1
For x = 0 To breite - 1
Plot(x, y, bildarray1(y, x))
Next x
Next y
StopDrawing()
EndIf
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
Delay(4000)
EndIf
Verfasst: 07.10.2008 19:24
von LCD
Array ist langsamer als Memory access, das habe ich nämlich auch vor Jahren verwendet.
Code: Alles auswählen
Procedure FastColor(pccol)
ProcedureReturn (pccol&255)<<16|(pccol&65280)|(pccol>>16&255)
EndProcedure
und dann so etwas in der Art:
Code: Alles auswählen
*Buffer=*mem
For y = 0 To hoehe - 1
For x = 0 To breite - 1
Plot(x, y, FastColor(PeekL(*Buffer))):*Buffer+4
Next x
Next y
Habe ich aus dem Gedächtnis geschrieben, aber so sieht es in etwa in meinem Programm aus.
Verfasst: 08.10.2008 01:37
von Thomas_freak
Den Fehler habe ich gefunden. Für das Array(x,y) ist x=höhe, y=breite. Bei mir war es umgekehrt. Nun sind nur noch die Farbkanäle für Rot und Blau vertauscht.
Wenn ich memory access benutze, kann ich doch nicht auf einzele Pixel, sprich zeile und spalte (x und y) zugreifen, oder? Wie gehe ich das am besten an?
Verfasst: 08.10.2008 14:24
von NicTheQuick
Die Datenelemente eines beliebig dimensionalen Arrays sind im Speicher ja
auch nur linear angeordnet. Wenn du also nur den Pointer zum ersten
Eintrag eines Arrays hast, kannst du auch Zeile für Zeile durch das Array
laufen, indem du nach jedem Pixel den Pointer um 'SizeOf(Elementtyp)'
erhöhst.
Hier der Code, wie er bei mir annehmbar schnell unter Wine läuft
Code: Alles auswählen
#fenster = 1
UseJPEGImageDecoder()
bild1 = LoadImage(#PB_Any, "C:\Logorollo.jpg")
breite = ImageWidth(bild1)
hoehe = ImageHeight(bild1)
If OpenWindow(#fenster, 10, 10, breite, hoehe, "Kantendetektion RGB") = 0 : End : EndIf
Structure Color
r.b
g.b
b.b
reserved.b
EndStructure
Macro SwapRB(Color)
((Color & $FF) << 16) | (Color & $FF00) | (Color >> 16)
EndMacro
*bild1 = AllocateMemory(hoehe * breite * SizeOf(Color))
Procedure CopyImageToMem(Img.l, *mem)
Protected bmi.BITMAPINFO
Protected w.l, h.l, hBmp.l, hDC.l
w = ImageWidth(Img)
h = ImageHeight(Img)
hBmp = ImageID(Img)
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiHeader\biWidth = w
bmi\bmiHeader\biHeight = -h
bmi\bmiHeader\biPlanes = 1
bmi\bmiHeader\biBitCount = 32
bmi\bmiHeader\biCompression = #BI_RGB
hDC = StartDrawing(ImageOutput(Img))
If GetDIBits_(hDC, hBmp, 0, h, *mem, bmi, #DIB_RGB_COLORS)
StopDrawing()
ProcedureReturn #True
Else
OpenConsole()
StopDrawing()
ProcedureReturn #False
EndIf
EndProcedure
If CopyImageToMem(bild1, *bild1)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Repaint
If StartDrawing(WindowOutput(#fenster))
*Pixel.Long = *bild1
For y = 0 To hoehe - 1
For x = 0 To breite - 1
Plot(x, y, SwapRB(*Pixel\l))
*Pixel + SizeOf(Color)
Next x
Next y
StopDrawing()
EndIf
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
Delay(4000)
EndIf