Seite 2 von 5

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 12:33
von super_castle
Deinfach n Drawing starten DrawingBuffer ausgeben lasen mit DrawingBufferPixelFormat()
checken welches Format vorliegt.
"Diese kann sich direkt im Videospeicher befinden, wenn die Ausgabe auf ScreenOutput() oder SpriteOutput() erfolgt, und erlaubt sehr schnelle Pixel-Manipulation. Mit ImageOutput() ermöglicht dieser Befehl direkten Zugriff auf die Pixel des Ziel-Bildes."
Soweit war ich auch schon.
Mir ging es darum jeden Pixel den ich gesetzt habe sofort zu sehen und nicht erst in das Zeitintensive ScreenOutput() einzusteigen.

Danke für deine Hilfe trotzdem.


Gruss

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 12:41
von super_castle
verdammt, jetzt hast du es schon vor 2 1/2 jahren versprochen, dass du auf dein gfa umsteigst. warum landest dann immer wieder bei purebasic, wenn hier alles nur scheisse ist.
Weil sich die Purebasicprograme noch verkaufen lassen.

Gruss

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 14:53
von STARGÅTE
super_castle hat geschrieben: Soweit war ich auch schon.
Mir ging es darum jeden Pixel den ich gesetzt habe sofort zu sehen und nicht erst in das Zeitintensive ScreenOutput() einzusteigen.
Du "siehst" ein geänderten Pixel doch eh erst wenn du FlipBuffers() ausgeführt hast.
Denn dadurch werden die beiden Buffer getauscht und erst dann "die Änerungen sichtbar".

Außerdem recht es ein einziges mal ScreenOutput() davor packen und kannst dann für immer drin rumschreiben, und bei einem FlipBuffer wirds sichtbar

Hier ein Beispielcode wo ich dne Buffer ermittle und danach mittels Thread "wild" in den Speicher schreiben kann.

Code: Alles auswählen

InitSprite()

OpenWindow(0, 0, 0, 800, 600, "SCREEN", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)
 
Global *Buffer, Pitch

Procedure PixelMuell(Null=#Null)
  Repeat
    z.f + 0.0005 : Delay(1)
    For n = 1 To 1000
      x = Random(799)
      y = Random(599)
      Color = RGB(128+Cos(x/800+z*#PI*2/3)*127, 128+Cos(y/600+z*#PI*4/3)*127, 128+Cos((x-y)/(800+600)+z*#PI*2)*127)
      PokeL(*Buffer+x*4+y*Pitch, Color) 
    Next
  ForEver
EndProcedure

StartDrawing(ScreenOutput())
  *Buffer = DrawingBuffer()
  Pitch = DrawingBufferPitch()
  If Not *Buffer
    End
  EndIf
StopDrawing()

Pixel = CreateThread(@PixelMuell(), #Null)

Repeat

  Event = WindowEvent()
  Delay(10)
  FlipBuffers()

Until Event = #PB_Event_CloseWindow

KillThread(Pixel)

End
Ich finde das ist schnell genug ^^

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 14:59
von ralle
STARGÅTE hat geschrieben:Hier ein Beispielcode wo ich dne Buffer ermittle und danach mittels Thread "wild" in den Speicher schreiben kann.
Bei mir wird das Fenster direkt nach dem Start wieder geschlossen, ohne das irgendwas nennenswertes passiert. Per Debug schon getestet, dass das Fenster und der Screen tatsächlich geöffnet werden, aber dennoch endet das Programm direkt wieder.

Muss ich ein anderes Subsystem nutzen? Auf Threadsicher im compiler stellen reicht anscheinend nicht :S

mfG
Ralle

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 15:06
von STARGÅTE
Jo ist n Sicherheit, wenn das Pixelformat nicht stimmt.

Kommentiere mal dies Zeile aus:

Code: Alles auswählen

If DrawingBufferPixelFormat() < #PB_PixelFormat_32Bits_RGB Or Not *Buffer
   End ; falsches Pixelformat (nicht 4 Bytes)
EndIf
Einstellungen sind Standard, kein ThreadSafe, kein Subsystem.

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 15:14
von ralle
Ok, damit klappt es, teilweise. Malt jetzt in einer schicken Geschwindigkeit bunte Pixel auf den Screen, jedoch bleibt die untere Rechte Ecke immer Schwarz.
Bild
Ansonsten ein Spitzenbeispiel für die möglichen Anwendungen und die Geschwindigkeit der Bildschirmmanipulation.

mfG
Ralle

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 15:22
von STARGÅTE
hm, unten leer ist seltsam,

vorallem sehe die farebn auch anders aus ...

debug mal bei dir bitte das
debug DrawingBufferPixelFormat()

einfach mit in den DrawingBlock,

zumindest läufts bei mir unter BGR 32Bit
Gibt das Pixel-Format des aktuellen Ausgabekanals zurück. Das Ergebnis kann eine Kombination (mit bitweisem 'OR') der folgenden Werte sein:
#PB_PixelFormat_8Bits ; 1 Byte pro Pixel, mit Palette ("palettised")
#PB_PixelFormat_15Bits ; 2 Byte pro Pixel
#PB_PixelFormat_16Bits ; 2 Byte pro Pixel
#PB_PixelFormat_24Bits_RGB ; 3 Byte pro Pixel (RRGGBB)
#PB_PixelFormat_24Bits_BGR ; 3 Byte pro Pixel (BBGGRR)
#PB_PixelFormat_32Bits_RGB ; 4 Byte pro Pixel (RRGGBB)
#PB_PixelFormat_32Bits_BGR ; 4 Byte pro Pixel (BBGGRR)
#PB_PixelFormat_ReversedY ; Die Y-Koordinate der Ausgabe ist umgekehrt im Speicher (die untere Reihe ist zuerst gespeichert).
könnte sein, das du n anders Format hast ...
dann würde sich oben im Thread die multiplikation ändern:
PokeL(*Buffer+x*4+y*Pitch, Color)

die 4 steht ja für 32Bit (4Bytes/px) bei 24Bit wäre es dann nur n *3 ...
der Pitch sorgt auf jedenfall schon mal dafür, das eine Reihe genau bestimmt werden kann,
somit sollte es zu meinem schreibfehler kommen ...

Klar ist es etwas komplizierter, dahinter zu kommen, welches Format im Buffer schlummert, was sonst Plot() usw. alles alleine macht,
aber daür ist es halt unglaublcih schnell, vorallem wenn man dann noch mit einer fertigen Structure arbeitet, statt PokeL()

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 15:33
von ralle
Laut Debug ist es #PB_PixelFormat_32Bits_BGR (Wert war 64 vom Debug)

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 24.06.2010 19:54
von Fluid Byte
Ich glaub du hast noch nicht ganz begriffen STARGÅTE ...

Mal abgesehen davon das er wiederholt die gesamte PureBasic-Community mit seinen Stammtischparolen
bepöbelt, hat er gerade PureBasic komplett zerrissen. Das hast du schon mitbekommen oder?
In Zukunft will er alles mit GFA Basic umsetzten (lasst uns beten das er's ernst meint) weil diese Sprache haushoch überlegen ist.

Also bitte, nicht mehr füttern!

Re: Adresse suchen um ein Pixel zusetzen.

Verfasst: 25.06.2010 13:41
von SoS
ralle hat geschrieben:Ok, damit klappt es, teilweise. Malt jetzt in einer schicken Geschwindigkeit bunte Pixel auf den Screen, jedoch bleibt die untere Rechte Ecke immer Schwarz.
Ralle
Teste mal folgenden Code,weiss zwar nich mehr genau wo ich ihn herhab,ist ein sehr schönes Beispiel.Hab ihn an PB 4.50 angepasst.

Code: Alles auswählen

;=========================================; 
;                                         ; 
;            C I N T A M A N I            ; 
;                                         ; 
;       Directdraw Graphics Library       ; 
;                                         ; 
;_________________________________________; 
;                                         ; 
;               CC : A + SA               ; 
;      jayagopal.das -- May 15, 2009      ; 
;                                         ; 
;=========================================; 

;-Constants 
;#screenW  =1600: #screenH = 900 
;#screenW  =1024: #screenH = 768 
;#screenW  = 800: #screenH = 600 
#screenW  = 640: #screenH = 480 
;#screenW  = 320: #screenH = 240 

#RD=0 
#GR=1 
#BL=2 

#Background=-2 
#Foreground=-1 

;-Procedure Declarations 
;Graphics 
Declare redraw()                                                     ; draw the virtual-screen on the real one 
Declare clear(x1=0,y1=0,x2=#screenW-1,y2=#screenH-1)                 ; restore the background (or a portion of it) 
Declare addPage()                                                    ; add a screen page 
Declare deletePage(pageNumber) ;NOT TESTED YET!!! 
Declare copyPageFore(pageNumber)                                     ; copy a screen page to the foreground 
Declare copyPageBack(pageNumber)                                     ; copy a screen page to the background 
Declare.c virtualScreen(x,y,channel,intensity=-1)                    ; read/write the appropriate screen page 
Declare mLine(x1,y1,x2,y2,r=255,g=255,b=255,a=255,antialias=0)       ; manual line drawing routine 
Declare mCircle(x,y,rad,r=255,g=255,b=255,a=255,antialias=0)         ; manual circle drawing routine 
Declare pixel(x,y,r=255,g=255,b=255,a=255)                                       ; write a pixel to the virtual screen 

;Calculation 
Declare.f frac(num.f)                                                ; return the fractional part of a number 
Declare.f radius(dx,dy)                                              ; return a value from the radius table 
; Declare Sign(n)                                                      ; return the sign of a number 

;-Global arrays and variables 
Global Dim radiusTable.f(#screenW,#screenH)                          ; to speed up distance calculations 
Global *foreground=AllocateMemory(#screenW*#screenH*4)               ; the foreground screen page 
Global *background=AllocateMemory(#screenW*#screenH*4)               ; the background screen page 
Global Dim *page(0)                                                  ; used for storing additional screen pages 
Global pageCount=0 
Global Buffer                                                        ; starting address for screen memory 
Global Pitch                                                         ; bytes in one screen-line 
Global drawPage                                                      ; the page to draw to 



;==========STARTING FROM HERE, this can be in another file================== 
;-Initialization 
If InitSprite()=0 Or InitKeyboard()=0 Or InitMouse()=0: End: EndIf 
If OpenScreen(#screenW, #screenH, 32, "PB DirectGraphics Library Example") 
  
  ;- Main Loop 
  ;{ contains examples of drawing using these procedures 
  
  ;draw some static on a gradient on 4 different pages 
  For i=1 To 4 
    addPage() 
    drawPage=i ;this is the page-number to draw to (index starts from 1) 
    For y=0 To #screenH-1: For x=0 To #screenW-1 
        pixel(x,y,Int(x/#screenW*255),Int(y/#screenH*255),Int((x+y)/(#screenW+#screenH)*255)): pixel(x,y,Random(64),Random(64),Random(64),128) 
    Next: Next 
  Next 
  
  ;some variables for drawing the thingy 
  rad=#screenH*0.14: circumference=rad*2*#PI: t.f: ti.f 
  
  Repeat 
    ExamineKeyboard() 
    ExamineMouse() 
    
    drawPage=#Foreground 
    ;draw a weird thingy that spins And follows the mouse 
    ;mx=MouseX(): my=MouseY() 
    mx=DesktopMouseX(): my=DesktopMouseY() 
    mLine(#screenW/2,#screenH/2,mx,my,255,255,255,155,1) 
    t=ti: ti+0.05 
    For i=0 To 23 
      t+(#PI/12): px=mx+rad*Cos(t): py=my+rad*Sin(t) 
      mLine(mx,my,px,py,255,255,255,155,1) 
      mCircle(px,py,#screenH*0.02,255,255,255,155,1) 
    Next 
    
    ;draw some random lines, circles and pixels 
    For i=1 To 3000: pixel(Random(#screenW),Random(#screenH), Random(255),Random(255),Random(255), Random(155)): Next 
    For i=1 To 10 
      mLine(Random(#screenW),Random(#screenH), Random(#screenW),Random(#screenH), Random(255),Random(255),Random(255), Random(55),1) 
      mCircle(Random(#screenW),Random(#screenH), Random(#screenW), Random(255),Random(255),Random(255), Random(55),1) 
    Next 
    mCircle(#screenW/2,#screenH/2,#screenH*0.3, 255,255,255,155,0) ;standing circle 
    mCircle(#screenW/2,#screenH/2,#screenH*0.4, 255,255,255,155,1) ;standing antialiased circle 
    
    mLine(#screenW*0.375,#screenH,#screenW,#screenH*0.375, 255,255,255,155,0) ;standing line 
    mLine(0,#screenH/2,#screenW/2,0, 255,255,255,155,1)                       ;standing antialiased line 
    
    ;cycle the background through all the extra pages (this will not effect the foreground, but WILL overwrite the background) 
    If q=pageCount: q=1: EndIf: copyPageBack(q): q+1 
    
    drawPage=#Background 
    ;draw directly onto the background (even after the foreground is drawn) -- this will be updated after clear() is called 
    For r =1 To 50: mCircle(100,100, r, Random(255),Random(255),Random(255), Random(55),1): Next          
    
    redraw() 
    clear() ;full clear 
    ;halfDim=rad+#screenH*0.02+1: clear(mx-halfDim,my-halfDim,mx+halfDim,my+halfDim) ;example of clearing just a portion 
    
  Until KeyboardPushed(#PB_Key_Escape) ;}  
  
Else 
  MessageRequester("Error","Sorry, some problem drawing the screen?",0) 
EndIf 

End 
;==========AND ENDING HERE, this can be in another file================== 



;-Graphics procedures      
Procedure redraw() 
  restoredrawPage=drawPage 
  drawPage=#Foreground 
  If StartDrawing(ScreenOutput()) 
      Buffer = DrawingBuffer()                                     ; Get the start address of the screen buffer. 
      Pitch  = DrawingBufferPitch()                                ; Get the length (in bytes) of one horizontal line.  
      
      For y=0 To #screenH-1 
        *Line.l = Buffer+Pitch*y 
        For x=0 To #screenW-1 
          PokeC(*Line, virtualScreen(x,y,#BL)): *Line+1 
          PokeC(*Line, virtualScreen(x,y,#GR)): *Line+1 
          PokeC(*Line, virtualScreen(x,y,#RD)): *Line+2 
        Next 
      Next 
    StopDrawing() 
    FlipBuffers() ; Page flipping 
  EndIf 
  drawPage=restoredrawPage 
EndProcedure 
Procedure clear(x1=0,y1=0,x2=#screenW-1,y2=#screenH-1) 
  If x1=0 And y1=0 And x2=#screenW-1 And y2=#screenH-1 
    CopyMemory(*background,*foreground,#screenW*#screenH*4) 
  Else 
    ;restore the specified portion 
    If x1>x2: Swap x1, x2: EndIf 
    If y1>y2: Swap y1, y2: EndIf 
    If x1<0: x1=0: EndIf: If x2>#screenW-1: x2=#screenW-1: EndIf 
    If y1<0: y1=0: EndIf: If y2>#screenH-1: y2=#screenH-1: EndIf 
    
    width=(x2-x1)*4 
    For y=y1 To y2 
      offset=y*#screenW*4+x1*4 
      CopyMemory(*background+offset,*foreground+offset,width) 
    Next 
  EndIf 
EndProcedure 
Procedure addPage() 
  pageCount=ArraySize(*page())+1 
  ReDim *page(pageCount) 
  *page(pageCount)=AllocateMemory(#screenW*#screenH*4) 
EndProcedure 
Procedure deletePage(pageNumber) 
  FreeMemory(*page(pageNumber)) 
  For i=pageNumber To pageCount: *page(i)=*page(i+1): Next 
  pageCount-1 
EndProcedure 
Procedure copyPageFore(pageNumber) 
  If pageNumber>0 And pageNumber<=pageCount 
    CopyMemory(*page(pageNumber),*foreground,#screenW*#screenH*4) 
  EndIf 
EndProcedure 
Procedure copyPageBack(pageNumber) 
  If pageNumber>0 And pageNumber<=pageCount 
    CopyMemory(*page(pageNumber),*background,#screenW*#screenH*4) 
  EndIf 
EndProcedure 
Procedure.c virtualScreen(x,y,channel,intensity=-1) 
  Select drawPage 
    Case #Foreground: *pageAddress=*foreground 
    Case #Background: *pageAddress=*background 
    Default: *pageAddress=*page(drawPage) 
  EndSelect  
  
  If intensity=-1 
    intensity=PeekC(*pageAddress+y*#screenW*4+x*4+channel) 
    ProcedureReturn intensity 
  Else 
    PokeC(*pageAddress+y*#screenW*4+x*4+channel,intensity) 
    ProcedureReturn 1 
  EndIf 
EndProcedure 
Procedure mLine(x1,y1,x2,y2,r=255,g=255,b=255,a=255,antialias=0) 
  If antialias: gradient.f: y.f: C1.f: C2.f: xend.f: yend.f: xgap.f: deltax.f: deltay.f: EndIf        ;initialize floats 
  
  If Abs(y2-y1) > Abs(x2-x1): steep=1: EndIf  ;detect slopes>.5 
  If steep: Swap x1, y1: Swap x2, y2: EndIf 
  If x1>x2: Swap x1, x2: Swap y1, y2: EndIf 
  
  ;ix1=x1:ix2=x2 
  deltax=x2-x1 
  deltay=Abs(y2-y1) 
  error=deltax/2 
  y=y1 
  
  If antialias And deltax<>0 
    gradient=deltay/deltax+0.0010001 ;get slope    
    
    ;generate antialiased endpoints 
    xend=Int(x1+0.5) 
    yend=y1+gradient*(xend-x1) 
    xgap=1-frac(x1) 
    ix1=Int(xend) 
    iy1=Int(yend) 
    C2=frac(yend+0.5)*xgap 
    C1=1-C2 
    ;If steep: pixel(iy1,ix1,r,g,b,a*C1): pixel(iy1+1,ix1,r,g,b,a*C2) 
    ;Else: pixel(ix1,iy1,r,g,b,a*C1): pixel(ix1,iy1+1,r,g,b,a*C2): EndIf 
    
    ;y=yend+gradient 
    
    xend=Int(x2+0.5) 
    yend=y2+gradient*(xend-x2) 
    xgap=1-frac(x2) 
    ix2=Int(xend) 
    iy2=Int(yend) 
    C2=frac(yend+0.5)*xgap 
    C1=1-C2 
    ;If steep: pixel(iy2,ix2,r,g,b,a*C1): pixel(iy2+1,ix2,r,g,b,a*C2) 
    ;Else: pixel(ix2,iy2,r,g,b,a*C1): pixel(ix2,iy2+1,r,g,b,a*C2): EndIf 
  EndIf 
  
  If y1<y2: ystep = 1: Else: ystep = -1: gradient*-1: EndIf 
  For x=x1 To x2 
    If Not antialias ;bresenham's algorithm 
      If steep: pixel(y,x,r,g,b,a): Else: pixel(x,y,r,g,b,a): EndIf 
      error-deltay 
      If error<0: y+ystep: error+deltax: EndIf 
    Else ;wu's algorithm 
      C2=frac(y+0.5) 
      C1=1-C2 
      If steep: pixel(y+0,x,r,g,b,a*C1): Else: pixel(x,y+0,r,g,b,a*C1): EndIf 
      If steep: pixel(y+1,x,r,g,b,a*C2): Else: pixel(x,y+1,r,g,b,a*C2): EndIf      
      y+gradient 
    EndIf 
  Next 
EndProcedure 
Procedure mCircle(x,y,rad,r=255,g=255,b=255,a=255,antialias=0) 
  If rad>0 
    ys.f 
    If antialias: C1.f: C2.f: Else: C1=1: EndIf 
    For xs = -rad*0.7071 To -1 
      ys=Sqr(rad*rad-xs*xs) 
      If antialias: C2=frac(ys+0.5): C1=1-C2: EndIf 
      pixel(x+xs,y+ys,r,g,b,a*C1) 
      pixel(x-xs,y+ys,r,g,b,a*C1) 
      pixel(x+xs,y-ys,r,g,b,a*C1) 
      pixel(x-xs,y-ys,r,g,b,a*C1) 
      
      pixel(x+ys,y+xs,r,g,b,a*C1) 
      pixel(x-ys,y+xs,r,g,b,a*C1) 
      pixel(x+ys,y-xs,r,g,b,a*C1) 
      pixel(x-ys,y-xs,r,g,b,a*C1) 
      
      If antialias 
        pixel(x+xs,y+ys+1,r,g,b,a*C2) 
        pixel(x-xs,y+ys+1,r,g,b,a*C2) 
        pixel(x+xs,y-ys-1,r,g,b,a*C2) 
        pixel(x-xs,y-ys-1,r,g,b,a*C2) 
        
        pixel(x+ys+1,y+xs,r,g,b,a*C2) 
        pixel(x-ys-1,y+xs,r,g,b,a*C2) 
        pixel(x+ys+1,y-xs,r,g,b,a*C2) 
        pixel(x-ys-1,y-xs,r,g,b,a*C2) 
      EndIf 
    Next 
    If antialias: C2=frac(rad+0.5): C1=1-C2: Else: C1=1: EndIf 
    pixel(x,y+rad,r,g,b,a*C1) 
    pixel(x,y-rad,r,g,b,a*C1) 
    pixel(x+rad,y,r,g,b,a*C1) 
    pixel(x-rad,y,r,g,b,a*C1) 
    
    If antialias 
      pixel(x,y+rad+1,r,g,b,a*C2) 
      pixel(x,y-rad-1,r,g,b,a*C2) 
      pixel(x+rad+1,y,r,g,b,a*C2) 
      pixel(x-rad-1,y,r,g,b,a*C2) 
    EndIf 
    
    ;circumference=rad*2*#PI  
    ;;generic calculation: 
    ;t.f 
    ;For i = 1 To circumference 
    ;  t+2*#PI/circumference 
    ;  pixel(x+rad*Cos(t), y+rad*Sin(t), r,g,b,a) 
    ;Next 
  EndIf 
EndProcedure 
Procedure pixel(x,y,r=255,g=255,b=255,a=255) 
  If r<0 : r=0 : EndIf 
  If g<0 : g=0 : EndIf 
  If b<0 : b=0 : EndIf 
  If a<0 : a=0 : EndIf  
  
  If r>255 : r=255 : EndIf 
  If g>255 : g=255 : EndIf 
  If b>255 : b=255 : EndIf 
  If a>255 : a=255 : EndIf 
  
  If x>=0 And x<#screenW And y>=0 And y<#screenH 
    If a<255 
      ar=255-a 
      r=virtualScreen(x,y,#RD)*ar/255+b*a/255 
      g=virtualScreen(x,y,#GR)*ar/255+g*a/255 
      b=virtualScreen(x,y,#BL)*ar/255+r*a/255 
    EndIf 
    virtualScreen(x,y,#RD,r) 
    virtualScreen(x,y,#GR,g) 
    virtualScreen(x,y,#BL,b) 
  EndIf 
EndProcedure 

;-Calculation procedures 
Procedure.f frac(num.f) 
  num=num-Int(num) 
  ProcedureReturn num 
EndProcedure 
Procedure.f radius(dx,dy)  
  ProcedureReturn radiusTable(Int(Abs(dx)),Int(Abs(dy))) 
EndProcedure 
; Procedure Sign(n) 
;   ProcedureReturn n/Abs(n) 
; EndProcedure