Bild nach und nach aufbauen ... funzt nur leider nich !

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
lassma-asma
Beiträge: 107
Registriert: 10.07.2007 09:14
Wohnort: Saarland

Bild nach und nach aufbauen ... funzt nur leider nich !

Beitrag von lassma-asma »

Hallo alle zusammen ,

ich wollte ein Programm schreiben , mit dem ein Image Pixel für Pixel ausgelesen wird , dieser Pixel dann als Object "erstellt" wird und Pixel für Pixel auf nen Screen ausgegeben wird !
Die Procedure zum "abarbeiten" des Bildes Pixel für Pixel sollte dann im Hintergrund als Thread laufen ...

naja ... es funzt nur leider nich unn ich steh im Moment ein bisschen auf der Leiter ..ähh.. auf der Leitung :oops:

vll könnt ihr mir ja sagen woran es hängt ..

Hier der Code (müsst noch ein Image laden ...)

Code: Alles auswählen

InitSprite()
InitKeyboard()
InitMouse()

UseJPEGImageDecoder()

LoadImage(0,"bf2.jpg")

Global counter.l
Global ib.l = ImageWidth(0)
Global ih.l = ImageHeight(0)
Global farbe
Global tn.l
Global tn2.l

OpenScreen(1600,1200,32,"Bild aufbauen")

Structure pixel
 x.l
 y.l
 r.l
 g.l
 b.l
EndStructure
Global NewList Pixel.Pixel()


Procedure AddPixel(x,y,red,green,blue)
  AddElement(Pixel())
   pixel()\x=x
   pixel()\y=y
   pixel()\r=red
   pixel()\g = green
   pixel()\b=blue
EndProcedure

Procedure Check()

            For x = 0 To ib
               For y = 0 To ih 
                  StartDrawing(ImageOutput(0))
                  farbe = Point(x,y)
                  StopDrawing()
                    
                   AddPixel(x,y,Red(farbe),Green(farbe),Blue(farbe))                     
              Next
            Next
            
EndProcedure

Repeat
  ClearScreen(0)
  ExamineKeyboard()
  ExamineMouse()

  tn = CreateThread(@Check(),0)

  ForEach Pixel()
      StartDrawing(ScreenOutput())
    Plot(pixel()\x,pixel()\y,RGB(pixel()\r,pixel()\g,pixel()\b))
      StopDrawing()
  Next
  
  ForEach pixel()
    counter + 1
  Next
  
  Debug counter
  counter = 0
  
  FlipBuffers()
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)
  end
Danke schon mal für alle Antworten :mrgreen: !
Gruß lassma-asma

MultiPONG
HANGMAN


PB 3.94 und PureBasic 4.51 !!!
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

StartDrawing() und StopDrawing() solltest du außerhalb der Schleifen machen.

Also

StartDrawing()
For ...
For ...
Next
Next
StopDrawing()

Und bei ForEach auch.

hast du es schon mal ohne Thread versucht?
Einfach nur das Bild geladen und in deine PixelObjekte umgewandelt.

Ich bin mal gespannt, welchen schicken Effekt du anschließend damit erzeugen willst. Wirst du die Pixel in einer Wellenbewegung verschieben?
Oder das Bild sprengen?

:roll:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Code: Alles auswählen

Sprite() 
InitKeyboard() 
InitMouse() 

UseJPEGImageDecoder() 

LoadImage(0,"C:\Share\Icons#\vista256[1].jpg") 

Global counter.l 
Global ib.l = 100; ImageWidth(0)  ; wegen der Geschwindigkeit
Global ih.l = 100; ImageHeight(0) 
Global farbe 
Global tn.l 
Global tn2.l 

OpenScreen(800,600,32,"Bild aufbauen") 

Structure pixel 
 x.l 
 y.l 
 r.l 
 g.l 
 b.l 
EndStructure 
Global NewList Pixel.Pixel() 


Procedure AddPixel(x,y,red,green,blue) 
  AddElement(Pixel()) 
   pixel()\x=x 
   pixel()\y=y 
   pixel()\r=red 
   pixel()\g = green 
   pixel()\b=blue 
EndProcedure 

Procedure Check() 
  StartDrawing(ImageOutput(0)) 
            For x = 0 To ib 
               For y = 0 To ih 
                  
                  farbe = Point(x,y) 
                   
                    
                   AddPixel(x,y,Red(farbe),Green(farbe),Blue(farbe))                      
              Next 
            Next 
            StopDrawing()
EndProcedure 


Check()

Repeat 
  ClearScreen(0) 
  ExamineKeyboard() 
  ExamineMouse() 

  
  StartDrawing(ScreenOutput()) 
  ForEach Pixel()     
    Plot(pixel()\x*2,pixel()\y*2,RGB(pixel()\r,pixel()\g,pixel()\b))   
  Next 
 ; DrawImage(ImageID(0),0,0)
  StopDrawing() 
;   
;   ForEach pixel() 
;     counter + 1 
;   Next 
;   
  counter=CountList(pixel()) ; Statt hochzuzählen
  ;Debug   counter 
  counter = 0 
  
  FlipBuffers() 
  Delay(1) 
Until KeyboardPushed(#PB_Key_Escape) 
  End 
Schnell mal überarbeitet. Zu mindest zeigt es bei mir jetzt ein Bild an.
Schau dir mal *Buffers an, wenn du mit vielen Pixeln arbeiten willst.
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
lassma-asma
Beiträge: 107
Registriert: 10.07.2007 09:14
Wohnort: Saarland

Beitrag von lassma-asma »

ahh .. danke schonma !
ok also es funzt jetzt soweit , das man das Bild anzeigen lassen kann , wenn es vorher berechnet wird ...
mit dem thread das klappt aber leider immer noch nich ..
ich wollte halt den effekt , das das Bild so Reihe für Reihe aufgebaut wird , und zwar genau in "Echtzeit" zur "Berechnung":
also wenn die erste Reihe in PixelObjects umgewandelt wurde sieht man auch schon die erste Reihe , ...

und das sich das Bild dann so nach und nach aufbaut ..
aber es scheint mit dem thread nicht so richtig zu funzen ... :cry:

(was meinst du mit den *buffers , denn ich hab grad ma ne animation gemacht und sehen , dass es doch vll ein bisschen viel Rechenarbeit is .. :wink: )
Gruß lassma-asma

MultiPONG
HANGMAN


PB 3.94 und PureBasic 4.51 !!!
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

1:1 PB-Hilfe:

Code: Alles auswählen

;
; ------------------------------------------------------------
;
;   PureBasic - Drawing via Direct Screen Access (DSA) 
;
;    (c) 2006 - Fantaisie Software
;
; ------------------------------------------------------------
;

; Start without debugger to see full speed!

#ScreenWidth  = 800  ; Feel free to change this to see the pixel filling speed !
#ScreenHeight = 600

If InitSprite() = 0 Or InitKeyboard()=0
  MessageRequester("Error","DirectX 7+ is needed.",0)
EndIf

Structure Pixel
  Pixel.l
EndStructure

Procedure.f GSin(angle.f)
  ProcedureReturn Sin(angle*(2*3.14/360))
EndProcedure

; Pre-calculated values are faster than realtime calculated ones...
; ... so we save them in an array before starting gfx operations
Dim CosTable(#ScreenWidth*2)
Dim ColorTable(255)

For i = 0 To #ScreenWidth*2
  CosTable(i) = GSin(360*i/320)* 32 + 32
Next


If OpenScreen(#ScreenWidth, #ScreenHeight, 32, "PB Plasma")

  Repeat

    Wave+6
    If Wave > 320 : Wave = 0 : EndIf
    
    If StartDrawing(ScreenOutput())
      Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
      Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
      PixelFormat = DrawingBufferPixelFormat()  ; Get the pixel format. 
      
      If PixelFormat = #PB_PixelFormat_32Bits_RGB
        For i = 0 To 255
          ColorTable(i) = i << 16 ; Blue is at the 3th pixel
        Next
      Else                        ; Else it's 32bits_BGR
        For i = 0 To 255
          ColorTable(i) = i       ; Blue is at the 1th pixel
        Next    
      EndIf
    
      For y = 0 To #ScreenHeight-1
        pos1 = CosTable(y+wave)
        
        *Line.Pixel = Buffer+Pitch*y
        
        For x = 0 To #ScreenWidth-1
          pos2 = (CosTable(x+Wave) + CosTable(x+y) + pos1)
          *Line\Pixel = ColorTable(pos2) ; Write the pixel directly to the memory !
          *Line+4
        Next
      Next
      
      StopDrawing()
    EndIf
    
    ExamineKeyboard()
    
    FlipBuffers()
     
  Until KeyboardPushed(#PB_Key_Escape)

Else
  MessageRequester("Error","Can't open the screen !",0)
EndIf

End

Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Wenn du es so wie so reihenweise machen möchtest,
schlage ich dir Sprites vor. Du schneidest mit GrabSprite()
dein Bild in SpriteStreifen. Und gibst diese dann aus.

Ich glaube, es gibt in der Überlegung einen kleinen Denkfehler.
Das Bild wird bei jedem ClearScreen() erneut ausgegeben.

aber so wie dein Code war, würdest du es auch bei jedem ClearScreen() einlesen. Wenn es einmal im Speicher ist, reicht das ja aus.

Was das gleichzeitige Auslesen und Ausgeben auf zwei verschiedenen OutPuts angeht, rate ich dir zeittechnisch auch von ab.

Ein Point() ist die langsamste Zeichenopperation, die es gibt.
Danach folgt Plot(). Du arbeitest also immer mit zwei der langsamsten
2D-Drawingbefehlen und willst das noch für vielleicht ein 1600 x 1200 Bild machen.

Ich will dir auch in deine Idee nicht reinreden, ich rate dir nur,
den Nutzen noch einmal zu überdenken.

Code: Alles auswählen

InitSprite() 
InitKeyboard() 
InitMouse() 

UseJPEGImageDecoder() 

LoadImage(0,"C:\Share\Icons#\vista256[1].jpg") 

Global counter.l 
Global ib.l = ImageWidth(0)  ; wegen der Geschwindigkeit
Global ih.l = ImageHeight(0) 
Global farbe 
Global tn.l 
Global tn2.l 

OpenScreen(800,600,32,"Bild aufbauen") 

Structure pixel 
 x.l 
 y.l 
 r.l 
 g.l 
 b.l 
EndStructure 
Global NewList Pixel.Pixel() 


Procedure AddPixel(x,y,red,green,blue) 
  AddElement(Pixel())
  With pixel() 
   \x=x 
   \y=y 
   \r=red 
   \g = green 
   \b=blue 
  EndWith ; Erspart Schreibarbeit 
EndProcedure 

Procedure Check() ; Nicht ganz richtig
  StartDrawing(ImageOutput(0)) 
            For x = 0 To ib 
               For y = 0 To ih 
                  
                  farbe = Point(x,y)         
                    
                   AddPixel(x,y,Red(farbe),Green(farbe),Blue(farbe))                      
              Next 
            Next 
            StopDrawing()
EndProcedure 


Global xT=0,yT=0
Procedure Check2()
    Zeit=ElapsedMilliseconds()
    StartDrawing(ImageOutput(0))   
    While ElapsedMilliseconds()-Zeit<2 And (xT*yT)<(ib*ih); verweilt hier 140 Millisekunden   
    
       While xT<ib And ElapsedMilliseconds()-Zeit<2
         farbe = Point(xT,yT)                                  
         AddPixel(xT,yT,Red(farbe),Green(farbe),Blue(farbe))                      
         xT+1
       Wend
       xA=xT-1
       If xT=ib       
         xT=0
         yT+1
       EndIf  
    Wend
    StopDrawing()
    xT=xA
EndProcedure 



Repeat 
  ClearScreen(0) 
  ExamineKeyboard() 
  ExamineMouse() 

  
  Check2()
  
  
  StartDrawing(ScreenOutput()) 
  ForEach Pixel() 
    With Pixel()
    If \x>=0 And \x<800 And \y>=0 And \y<600         
      Plot(\x,\y,RGB(\r,\g,\b))         
    EndIf
    

  Next 
  Box(\x+1,\y,16,5,RGB(255,0,0)) ; Zeichnet den letzten Pixel
      EndWith
; DrawImage(ImageID(0),0,0)
  StopDrawing() 
;   
;   ForEach pixel() 
;     counter + 1 
;   Next 
;   
  counter=CountList(pixel()) ; Statt hochzuzählen
  ;Debug   counter 
  counter = 0 
  
  FlipBuffers() 
  Delay(10) 
Until KeyboardPushed(#PB_Key_Escape) 
  End 
Haste dir das so vorgestellt? :allright:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
lassma-asma
Beiträge: 107
Registriert: 10.07.2007 09:14
Wohnort: Saarland

Beitrag von lassma-asma »

jo ! :allright: :allright: Genau so hab ich es mir eigentlich vorgestellt ...

aber leider check ich deinen Code noch nich ganz ... das mit dem xT und xA und xY ? könntest du mir das nochmal erklären ?

Und auch das beispiel von Andreas_S check ich nicht so ganz ... er manipuliert da direkt die Daten im Speicher , die ausgelesen werden oder wie !?

und wie könnte man damit jetzt zum Beispiel diesen "Effekt" beschleunigen ?
Code:

Code: Alles auswählen

InitSprite()
InitKeyboard()
InitMouse()

UseJPEGImageDecoder()

LoadImage(0,"bf2.jpg")

Global counter.l
Global ib.l =  ImageWidth(0)-600   ; wegen der Geschwindigkeit
Global ih.l =  ImageHeight(0) -600
Global farbe
Global tn.l
Global tn2.l
Global start.l

OpenScreen(1600,1200,32,"Bild aufbauen")

CreateSprite(1,2500,2500)

Structure pixel
 x.l
 y.l
 speedy.l
 speedx.l
 fall.l
 r.l
 g.l
 b.l
EndStructure
Global NewList Pixel.Pixel()


Procedure AddPixel(x,y,red,green,blue)
  AddElement(Pixel())
   pixel()\x=x
   pixel()\y=y
   pixel()\speedy=Random(20)+1
   pixel()\speedx = Random(10)+1
   pixel()\fall = 0
   pixel()\r=red
   pixel()\g = green
   pixel()\b=blue
EndProcedure

Procedure Check()
  StartDrawing(ImageOutput(0))
            For x = 0 To ib
               For y = 0 To ih
                 
                  farbe = Point(x,y)
                   
                   
                   AddPixel(x,y,Red(farbe),Green(farbe),Blue(farbe))                     
              Next
            Next
            StopDrawing()
EndProcedure


check()

Repeat
   counter = 0
   ClearScreen(0)
   ExamineKeyboard()
 ExamineMouse()
 
  StartDrawing(SpriteOutput(1))
  Box(0,0,2500,2500,$00000)
  
  ForEach Pixel()  
     
    If pixel()\x > 500 And pixel()\x < 520 And pixel()\fall = 0
       pixel()\fall = 1
    EndIf
    If pixel()\x > 120 And pixel()\x < 125 And pixel()\fall = 0
       pixel()\fall = 1
    EndIf
 If start = 1   
 If pixel()\fall = 1
       pixel()\y + pixel()\speedy
    If pixel()\y > 600
       pixel()\x + pixel()\speedx
    EndIf    
 EndIf
 EndIf

    If pixel()\y >= 1300 
      DeleteElement(pixel())
    EndIf
    If pixel()\x >= 1700 
      DeleteElement(pixel())
    EndIf
    
    Plot(pixel()\x,pixel()\y,RGB(pixel()\r,pixel()\g,pixel()\b))
       
  Next
  
 ; DrawImage(ImageID(0),0,0)
  StopDrawing()
;   
;    ForEach pixel()
;      counter + 1
   ;Next
   DisplaySprite(1,0,0)
  counter=CountList(pixel()) ; Statt hochzuzählen
  ;Debug   counter
 
 
  If KeyboardPushed(#PB_Key_Return)
    If start = 0 
       start = 1
    EndIf
  EndIf
 
  FlipBuffers()
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape) 
   Debug counter
  End 

Ansonsten danke für die Beispiele ! THX echt TOP ! :allright: :)
Gruß lassma-asma

MultiPONG
HANGMAN


PB 3.94 und PureBasic 4.51 !!!
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

xT und yT sind beide global, also auch außerhalb der Prozedur verwendbar.

Die Prozedur Check2()

Wird in der Hauptschleife aufgerufen.

Check2() beinhaltet WHILE-WEND Schleifen. Diese werden abgebrochen,
sobald eine bestimmte Zeit, oder aber eine bestimmte Position
überschritten ist.

Da xT und yT global sind, werden diese Variablen
beim nächsten Aufruf von Check2() immer noch ihre Werte
behalten haben. Die Prozedur macht also an der Stelle
weiter, wo sie aufgehört hat.

Und das halt so lange, bis die Prozedur schon abbricht,
weil xT und yT außerhalb des eigentlichen Bildes liegen würden.

:roll:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
lassma-asma
Beiträge: 107
Registriert: 10.07.2007 09:14
Wohnort: Saarland

Beitrag von lassma-asma »

ahh .. okok .. ich denke ich hätte es soweit verstanden !

THX nochmal und wenn ich noch fragen hab komm ich ma ganz dreist :wink: nochmal auf euch zurück ! :D
Gruß lassma-asma

MultiPONG
HANGMAN


PB 3.94 und PureBasic 4.51 !!!
Antworten