Image in Speicherbereich kopieren, aber ohne API

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Image in Speicherbereich kopieren, aber ohne API

Beitrag von NicTheQuick »

Hi Jungs!

Wer hat denn gerade mal eine entsprechende Routine auf Lager, mit der ich ein mit [c]LoadImage()[/c] geladenes Image in einen Speicherbereich kopieren kann, aus dem ich dann später Pixel für Pixel die Farben wieder auslesen kann?

Ich will dafür aber unbedingt keine API verwenden, weil das Programm auch unter Linux laufen sollte.
Benutzeravatar
Franky
Beiträge: 1132
Registriert: 29.08.2004 16:31
Wohnort: Münsterland
Kontaktdaten:

Beitrag von Franky »

Zuerstmal:Ich hab keine Lösung gefunden
(nich, dat jetzt alle aufhören zu denken ;))

Ich hab allerdings mal ein bisschen rumprobiert und kann euch nun zusichern, dass folgende 9 Versionen NICHT funktionieren.

Code: Alles auswählen

Structure THEBITMAPINFO 
    bmiHeader.BITMAPINFOHEADER 
    bmiColors.RGBQUAD[1] 
EndStructure 


Structure color
  blue.b
  green.b
  red.b
  leer.b
EndStructure 


Global State.l
Global bildlang.l
Global bildhoch.l

Dim Punkt1.color(300,300)

Dim Punkt2.color(300,300)

Dim Adressen.l(1)

Procedure RealRound(zahl.f);Rundet den Wert nach der nächsten ganzzahl
    If zahl=>0
        If zahl-Round(zahl,0)>0.5
            Endzahl.l=Round(zahl,1)
        Else 
            Endzahl.l=Round(zahl,0)
        EndIf
    Else 
        If zahl-Round(zahl,0)>0.5
            Endzahl.l=Round(zahl,0)
        Else 
            Endzahl.l=Round(zahl,1)
        EndIf         
    EndIf 
    ProcedureReturn Endzahl
EndProcedure 


Procedure SetDIBits(image.l,buffer.l,laenge)
;1. Version geht nicht
                ; bild=UseImage(image)
                ; CopyMemory(buffer,bild,laenge)
                
;2. Version geht nicht
                ; bild=UseImage(image)
                ; CopyMemory(buffer,bild+SizeOf(TheBitmapInfo),laenge) 
                
;3. Version geht nicht                
                ; UseImage(image)
                ; bild=StartDrawing(ImageOutput())
                ; CopyMemory(buffer,bild,laenge)
                ; StopDrawing()
                
;4. Version geht nicht
                ; UseImage(image)
                ; StartDrawing(ImageOutput())
                    ; bild=ImageOutput()
                    ; CopyMemory(buffer,bild,laenge)
                ; StopDrawing()

;5. Version  geht nicht
                ; UseImage(image)
                ; bild=ImageOutput()
                ; CopyMemory(buffer, bild, laenge)

;6. Version geht nicht
               ; UseImage(image)
               ; bild=DrawingBuffer()
               ; CopyMemory(buffer, bild, laenge)

;7. Version geht nicht
               ; UseImage(image)
               ; StartDrawing(ImageOutput())
               ; bild=DrawingBuffer()
               ; CopyMemory(buffer, bild, laenge)
               ; StopDrawing()

;8. Version geht nicht
                ; bild=UseImage(image)
                ; StartDrawing(ImageOutput())
                ; CopyMemory(buffer,bild+SizeOf(THEBITMAPINFO),laenge) 
                ; StopDrawing()

;9. Version geht nicht
                ; UseImage(image)
                ; bild=GetDC_(UseImage(image))
                ; CopyMemory(buffer,bild,laenge)
EndProcedure

Procedure Array_to_image_norm(usedimage.l,array.l,laenge.l,hoehe.l);Überträgt das array ins #usedimage
    If State=0
                 bild=UseImage(usedimage) 
                 paint=StartDrawing(ImageOutput())
                 If paint
                 areapicture.THEBITMAPINFO
                  areapicture\bmiHeader\biSize =SizeOf(THEBITMAPINFO)
                  areapicture\bmiHeader\biWidth=laenge
                  areapicture\bmiHeader\biHeight=hoehe
                  areapicture\bmiHeader\biPlanes=1
                  areapicture\bmiHeader\biBitCount=32
                  If SetDIBits_(paint,bild,0,hoehe,array,areapicture,#DIB_RGB_COLORS)<>0
                  EndIf 
                 EndIf 
                 StopDrawing()     
     Else 
                  Debug "HI"
                  If SetDIBits(usedimage,array,(laenge+1)*(hoehe+1)*4)<>0
                 EndIf  
     EndIf
EndProcedure 




Adressen(0)=Punkt1()
Adressen(1)=Punkt2()


For a=0 To 300
    For b=0 To 300
             Punkt1(a,b)\red=0
             Punkt1(a,b)\green=0
             Punkt1(a,b)\blue=255
             
             Punkt2(a,b)\red=220
             Punkt2(a,b)\green=0
             Punkt2(a,b)\blue=0
    Next 
Next    

bildlang=300
bildhoch=300

CreateImage(1,301,301)

State=0
Array_to_image_norm(1,Punkt1(),301,301)
If OpenWindow(1,100,100,301,321,#PB_Window_SystemMenu,"Titel")
       CreateGadgetList(WindowID())
            TextGadget(#PB_Any,0,0,300,20,"Button klicken :)")
            ButtonImageGadget(1,0,20,301,301,UseImage(1))
            Repeat 
                 event=WaitWindowEvent()
                 If event=#PB_EventGadget And EventGadgetID()=1
                        INC State
                        If State>1
                            State=0
                            Debug "hi"
                        EndIf
                        Array_to_image_norm(1,Adressen(State),301,301)
                        SetGadgetState(1,UseImage(1))
                 EndIf
           Until event=#WM_CLOSE
           CloseWindow(1)
EndIf
End            

Wenn einige Beispiele jeglicher Logik entsagen bitte nicht wundern, manche waren Verzweiflungsversuche (ich brauch das nämlich auch gerade ganz dringend)

Achja, meine Version versucht es genau andersrum (schreiben statt lesen), das sollte aber ja eigentlich auch funktionieren, wenn das lesen funktioniert.
Falsch zugeordnetes Zitat des Tages: "O'zapft is" - Edward Snowden :)
Benutzeravatar
Lebostein
Beiträge: 674
Registriert: 13.09.2004 11:31
Wohnort: Erzgebirge

Beitrag von Lebostein »

Und wenn du eine einfache Bitmap direkt mit ReadFile() und ReadData() in einen AllocateMemory()-Bereich lädst, kannst du ihn ja einfach Pixel für Pixel durchlaufen....
Benutzeravatar
SDX
Beiträge: 95
Registriert: 14.01.2005 18:37
Wohnort: Bremen
Kontaktdaten:

Beitrag von SDX »

@NicTheQuick: Was willst Du überhaupt damit machen? Ich hab vor kurzem mal ein Sprite Byte-weise kopiert (und dabei alle "roten" Pixel in andersfarbige umgerechnet)
.oO SDX Oo.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Hier ist der Code, den ich entsprechend schneller machen will.
Er liest Zeile für Zeile, Pixel für Pixel aus einem Image aus, rechnet die Farbwerte zwischen 0 und 255 in Werte zwischen 0 und 1 um und speichert sie in einem Speicherbereich. Das Bild braucht danach 3 mal mehr Speicher als vorher. Aber das ist nicht das Problem.

Code: Alles auswählen

Structure RTColor3F
  r.f
  g.f
  b.f
EndStructure

Structure RTSize
  x.l
  y.l
EndStructure

Structure RTTexture
  Size.RTSize
  Gamma.f
  *Img 
EndStructure

NewList RTTexture.RTTexture()


Procedure.l RTLoadTexture(File.s)
  Protected ID.l, *mem, Width.l, Height.l, *ImgPos, x.l, y.l, *Pixel.RTColor3F, RGB.l
  
  ID = LoadImage(#PB_Any, File)
  If ID
    Width = ImageWidth()
    Height = ImageHeight()
    
    *mem = AllocateMemory(Width * Height * SizeOf(RTColor3F))
    If *mem = 0 : FreeImage(ID) : ProcedureReturn #False : EndIf
    
    If AddElement(RTTexture())
      RTTexture()\Size\x = Width
      RTTexture()\Size\y = Height
      RTTexture()\Img    = *mem
      
      ;================== ||
      ;= WICHTIGER TEIL = ||
      ;================== \/
      
      UseImage(ID)
      If StartDrawing(ImageOutput())
        *Pixel = *mem
        For y = 1 To Height
          For x = 1 To Width
            RGB = Point(x, y)
            
            *Pixel\r = Red(RGB) / 255
            *Pixel\g = Green(RGB) / 255
            *Pixel\b = Blue(RGB) / 255
            
            *Pixel + SizeOf(RTColor3F)
          Next
        Next
        StopDrawing()
      EndIf
      
      ;================== /\
      ;= WICHTIGER TEIL = ||
      ;================== ||
      
      ProcedureReturn @RTTexture()
    
    Else
      FreeMemory(*mem)
      FreeImage(ID)
    EndIf
    
    FreeImage(ID)
  EndIf
  
  ProcedureReturn #False
EndProcedure

UseJPEGImageDecoder()

RTLoadTexture("f:\avatar.jpg")
Antworten