La fonction point() a accelerer !!!

Vous avez une idée pour améliorer ou modifier PureBasic ? N'hésitez pas à la proposer.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

La fonction point() a accelerer !!!

Message par Backup »

ben oui Fred , ce serai tres cool de trouver un moyen d'acceler cette fonction

car avec un Point() (et un plot()) Turbo , on peut faire plein de truc
genre simulations, colorisations, jeux,retouche photo, ect ....

si tu passe par la , ..... :D
Polo
Messages : 612
Inscription : sam. 03/juil./2004 20:14

Message par Polo »

Pas possible, par contre, j'aimerai voir quelque chose du genre de Blitzbasic, c'est a dire un Point et un PointFast (en BB, c'est Write/ReadPixel Write/readPixelFast)
En "fermant" le buffer quand on utilise les commande en Fast.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Polo a écrit :Pas possible
comment ça pas possible ?
Polo
Messages : 612
Inscription : sam. 03/juil./2004 20:14

Message par Polo »

Dobro a écrit :
Polo a écrit :Pas possible
comment ça pas possible ?
Je sais je me suis mal exprimé :)
En fait, la fonction Point et Plot affiche (ou lit) un pixel "en temps réel", en gros, dès que tu fait plot, tu vois le pixel affiché.
Par contre, si on utilise le buffering, un PlotFast n'afficherait pas "directement" le pixel, ça le stockerai dans une zone mémoire, et ça l'afficherait quand on "relacherait" le buffer.
Ok, mon explication n'est toujours pas claire, en fait, va sur blitzbasic.com et cherche le manuel en ligne de Blitz3d, puis cherche la commande ReadPixel et ReadPixelFast, c'est mieux expliqué (mais en anglais).
En tout cas, j'espère que Fred compte ou a fait quelque chose parce que je suis entièrement d'accord avec toi, cette fonction est inutilisable quand on veut dessiner ou lire une quantité importante de pixels.
Avatar de l’utilisateur
cederavic
Messages : 1338
Inscription : lun. 09/févr./2004 23:38
Localisation : Bordeaux

Message par cederavic »

Il me semble que le mode Screen utilise le double buffering (ecrit dans un buffer l'image pendant que celle qui est dans l'autre buffers est affichée)..

Sinon pour aller un peut plus vite, il suffit de passer directement pas l'adresse du buffer avec DrawingBuffer()

Il me semble qu'on en avait dejas parlé sur le musée...
Polo
Messages : 612
Inscription : sam. 03/juil./2004 20:14

Message par Polo »

Le problème, c'est que cela ne marche qu'avec les sprites...
Avatar de l’utilisateur
cederavic
Messages : 1338
Inscription : lun. 09/févr./2004 23:38
Localisation : Bordeaux

Message par cederavic »

Ba non pas qu'avec les sprite...
Regarde ce qu'on avait fait avec FWeil : http://cederavic.serveurperso.com/x3d.rar

F1 / F2 / F3 / F4 / F5 pour changer de mode
ESC pour quiter
Les fleche pour se deplacer

Mais je n'ai plus les sources :s
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

cederavic a écrit :Il me semble que le mode Screen utilise le double buffering (ecrit dans un buffer l'image pendant que celle qui est dans l'autre buffers est affichée)..

Sinon pour aller un peut plus vite, il suffit de passer directement pas l'adresse du buffer avec DrawingBuffer()

Il me semble qu'on en avait dejas parlé sur le musée...
ce qui prouve bien que cette fonction peut etre , et Devrai etre accelleré !! :D
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

un debut de solution ;)

Procedure ImageToTable(Image, Table) ; Retourne 1 si l'image a été chargée dans le tableau ImageID=#Image : Table=@Tableau(), ex : Dim Tableau(ImageWidth(), ImageHeight()) -> @Tableau()
If Image>=0 And Table
UseImage (Image)
ImageID = ImageID ()
Hdc = CreateCompatibleDC_ ( GetDC_ ( ImageID ))
If HDC
bmi.BITMAPINFO
bm.BITMAP
GetObject_ ( ImageID , SizeOf(BITMAP), @bm.BITMAP)
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiheader\biWidth = bm\bmWidth
bmi\bmiheader\biHeight = bm\bmHeight
bmi\bmiheader\biPlanes = 1
bmi\bmiheader\biBitCount = 32
bmi\bmiheader\biCompression = #BI_RGB
HList = AllocateMemory (bm\bmWidth*bm\bmHeight*4)
GetDIBits_ (hDC, ImageID ,0,bm\bmHeight,HList,bmi, #DIB_RGB_COLORS )

For nn = 0 To bm\bmWidth - 1
For n = 0 To bm\bmHeight - 1
s = HList + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4
d = Table + n * 4 + nn * bm\bmHeight * 4
CopyMemory (s + 2, d, 1)
CopyMemory (s + 1, d + 1, 1)
CopyMemory (s, d + 2, 1)
Next n
Table+4
Next nn
FreeMemory (HList)
Else
ProcedureReturn
EndIf
ProcedureReturn 1
EndIf
EndProcedure

Procedure TableToImage(Image, Table) ; Crée une image à partir du tableau Image=#Image, Table=@Tableau(), ex : Dim Tableau(ImageWidth(),ImageHeight()) -> @Tableau()
If IsImage (Image) And Table
ImageID = UseImage (Image)
bm.BITMAP
GetObject_ ( ImageID , SizeOf(BITMAP), @bm.BITMAP)
bmi.BITMAPINFO
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiheader\biWidth = bm\bmWidth
bmi\bmiheader\biHeight = bm\bmHeight
bmi\bmiheader\biPlanes = 1
bmi\bmiheader\biBitCount = 32
bmi\bmiheader\biCompression = #BI_RGB
pixel= AllocateMemory (bm\bmHeight*bm\bmWidth*4)
For nn = 0 To bm\bmwidth - 1
For n = 0 To bm\bmheight - 1
s = Table + n * 4 + nn * bm\bmHeight * 4
d = pixel + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4
CopyMemory (s, d + 2, 1)
CopyMemory (s + 1, d + 1, 1)
CopyMemory (s + 2, d, 1)
Next
table + 4
Next
HDC= StartDrawing ( ImageOutput ())
SetDIBits_ (HDC, ImageID ,0, ImageHeight (), pixel, bmi, #DIB_RGB_COLORS )
StopDrawing ()
FreeMemory (pixel)
ProcedureReturn 1
EndIf
EndProcedure


Exemple (pour convertir une image en noir et blanc)

Procedure WBImage(Image, Threshold) ; le seuil correspond à la valeur limite de binarisation (ex : 256/2)
If IsImage (Image) And Threshold>=0 And Threshold<256
UseImage (Image)
WI= ImageWidth ()
HI= ImageHeight ()
Dim Image(WI,HI)
ImageToTable(Image,Image())
For y=0 To HI-1
For x=0 To WI-1
color=Image(x,y)
r= Red (color)
v= Green (color)
b= Blue (color)
moy.f=3/(1/r+1/v+1/b)
If moy>Threshold : wb=255 : Else : wb=0 : EndIf
Image(x,y)= RGB (wb,wb,wb)
Next
Next
TableToImage(Image,Image())
ProcedureReturn 1
EndIf
EndProcedure
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ce que j'aimerai c'est pas une solution , mais que ce soit le "point()"
en natif qui soit acceléré !!! :)

avec les apis, on peut effectivement se passer de quasiment toutes les commandes PureBasic , mais ,cela n'est plus du PureBasic

par ailleurs, si j'avais voulu une solution , je n'aurai pas posté dans les
"Suggestions et améliorations"


Merci quand meme , ... ton code est tres interressant ! :D

jespere que tu comprend ma démarche qui est de demander
une amélioration de certaines Commandes existantes, pas un remplacement... :D
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

Ok, il n'y a pas de problèmes :oops:

Mais je pense juste que Fred s'en ai aperçu, c'est en attendant la solution miracle :D . C'est bien de le répéter :wink:
Fred
Site Admin
Messages : 2848
Inscription : mer. 21/janv./2004 11:03

Message par Fred »

Les fonctions point/plot sont deja tres optimisées pour Sprite/ScreenOutput() donc j'imagine qu tu demandes ca pour les images. Je vais regarder ca de plus pres.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

dans cette exemple le but etaient de simuler la trajectoire des rayon du soleil
sur la terre et la lune

en ligne 130

Code : Tout sélectionner

coul= Point (RotationX(soleil(1)\X+32, i, distance) ,RotationY(soleil(1)\Y+32, i, distance))

je regarde si mon rayon va rencontrer la couleur de la terre ou la couleur de la lune pour stoper le "Plot" et ainsi simuler l'arret du rayon
et par la meme ressortir l'ombre

le prg fonctionne tres lentement

sauf si l'on met la ligne 130 en REM (désactivation de la comande Point() )
on voit bien par cet exemple que la commande est tres tres lente ! :D


  ; Code par Dobro !!
; system solaire
; avec raytracing pour l'affichage des parties éclairés


Declare.f RotationX(X, angle.f, dist)
Declare.f RotationY(Y, angle.f, dist)
Declare calcul()
#PI =3.1415926
Enumeration
     #dobro
     #Police
     #soleil
     #terre
     #lune
     #ecran
EndEnumeration

Structure soleil
    X.l
    Y.l
EndStructure
Dim soleil.soleil(1)

Structure lune
    X.l
    Y.l
EndStructure
Dim lune.lune(1)

Structure terre
    X.l
    Y.l
EndStructure
Dim terre.terre(1)

; ***********************************
Resultat = InitSprite ()
FontID = LoadFont ( #Police , "arial" , 18, #PB_Font_Bold )
EcranX = GetSystemMetrics_ ( #SM_CXSCREEN ): ;=largeur de l'ecran
EcranY = GetSystemMetrics_ ( #SM_CYSCREEN ): ;=hauteur de l'ecran
     WindowID = OpenWindow (1, 0, 0,EcranX, EcranY, #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered , "system solaire maintenir un appuis sur ESC pour quitter" )
    Result = OpenWindowedScreen ( WindowID (1) ,0,0,EcranX, EcranY, 1, 0,0)
    
    Resultat = InitMouse ()
    Resultat = InitKeyboard ()
    
     ; creation de notre ecran
     CreateSprite ( #ecran , EcranX, EcranY)
     StartDrawing ( SpriteOutput ( #ecran ) )
     For etoiles=1 To 1000
        x_etoile= Random (EcranX-10)+5
        y_etoile= Random (EcranY-10)+5
         Plot ( x_etoile, y_etoile, RGB ($B1,$CD,$FC))
     Next etoiles
     StopDrawing ()
    
     ; creation du soleil
     CreateSprite ( #soleil , 64,64)
     StartDrawing ( SpriteOutput ( #soleil ) ) ; on dessine dedans
     Circle (32, 32, 32 , RGB ($FF,$FF,$97))
     StopDrawing ()
    
     ; creation de la terre
     CreateSprite ( #terre , 32, 32)
     StartDrawing ( SpriteOutput ( #terre ) ) ; on dessine dedans
     Circle (16, 16, 16 , RGB ($71,$88,$F9))
     StopDrawing ()
    
     ; creation de la lune
     CreateSprite ( #lune , 16, 16)
     StartDrawing ( SpriteOutput ( #lune ) ) ; on dessine dedans
     Circle (8, 8, 8 , RGB ($A6,$A6,$A6))
     StopDrawing ()
    
    taille_du_cercle_terre=180
    taille_du_cercle_lune=50
    nombre_de_jour_terre=360 ; ceci determine la resolution (nombre de points)
    nombre_de_jour_lune=21 ; ceci determine la resolution (nombre de points)
    soleil(1)\X=EcranX/2-64
    soleil(1)\Y=EcranY/2-64
     Repeat
         ExamineMouse ()
         ExamineKeyboard ()
         WindowEvent ()
         Delay (2)
        
         If MouseButton (2)
             End
         EndIf
        
        compt_terre+1
        compt_lune+1
         If compt_terre=nombre_de_jour_terre :compt_terre=0: EndIf ; on a fait le tour ??
         If compt_lune=nombre_de_jour_lune :compt_lune=0: EndIf ; on a fait le tour ??
        
        
        terre(1)\X=taille_du_cercle_terre* Cos ( compt_terre*(2*3.1415926/nombre_de_jour_terre)) + (soleil(1)\X+8 ) ; la formule du cercle /360 = 360 points
        terre(1)\Y=taille_du_cercle_terre * Sin ( compt_terre*(2*3.1415926/nombre_de_jour_terre)) + (soleil(1)\Y+8 ) ; la formule du cercle
        
        lune(1)\X=taille_du_cercle_lune* Cos ( compt_lune*(2*3.1415926/nombre_de_jour_lune)) + (terre(1)\X) ; la formule du cercle /360 = 360 points
        lune(1)\Y=taille_du_cercle_lune * Sin ( compt_lune*(2*3.1415926/nombre_de_jour_lune)) + (terre(1)\Y) ; la formule du cercle
        
        
        calcul() ; saut vers le raytracing maison Smile
        
         FlipBuffers (): ; affiche l'ecran
         ClearScreen (0, 0, 0) : ;efface l'ecran
     Until Event= #PB_Event_CloseWindow
    
    
     Procedure.f RotationX(X, angle.f, dist)
         ProcedureReturn X + Cos (angle.f* #PI /180)*dist
     EndProcedure
    
    
     Procedure.f RotationY(Y, angle.f, dist)
         ProcedureReturn Y + Sin (angle.f* #PI /180)*dist
     EndProcedure
    
     Procedure calcul()
         DisplaySprite ( #ecran , 0, 0)
         DisplayTransparentSprite ( #soleil , soleil(1)\X, soleil(1)\Y)
         DisplayTransparentSprite ( #terre , terre(1)\X, terre(1)\Y)
         DisplayTransparentSprite ( #lune , lune(1)\X, lune(1)\Y)
        lumiere= RGB ($FF,$FF,$97) ; lumiere du soleil
         StartDrawing ( ScreenOutput ())
         For i=1 To 360
             For distance=100 To 250 Step 2
                coul= Point (RotationX(soleil(1)\X+32, i, distance) ,RotationY(soleil(1)\Y+32, i, distance))
                 If coul= RGB ($71,$88,$F9) ;la lumiere rencontre la terre
                    lumiere= RGB ($FF,$FF,$97) ; lumiere du soleil
                     Box (RotationX(soleil(1)\X+32, i, distance) , RotationY(soleil(1)\Y+32, i, distance),2,2,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+2) , RotationY(soleil(1)\Y+32, i, distance+2),2,2,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+4) , RotationY(soleil(1)\Y+32, i, distance+4),2,2,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+6) , RotationY(soleil(1)\Y+32, i, distance+6),2,2,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+8 ) , RotationY(soleil(1)\Y+32, i, distance+8 ),2,2,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+10) , RotationY(soleil(1)\Y+32, i, distance+10),2,2,lumiere)
                    Break 1
                 ElseIf coul= RGB ($A6,$A6,$A6) ;la lumiere rencontre la lune
                    lumiere= RGB ($FF,$FF,$97) ; lumiere du soleil
                    
                     Box (RotationX(soleil(1)\X+32, i, distance) , RotationY(soleil(1)\Y+32, i, distance),1,1,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+1) , RotationY(soleil(1)\Y+32, i, distance+1),1,1,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+2) , RotationY(soleil(1)\Y+32, i, distance+2),1,1,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+3) , RotationY(soleil(1)\Y+32, i, distance+3),1,1,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+4) , RotationY(soleil(1)\Y+32, i, distance+4),1,1,lumiere)
                     Box (RotationX(soleil(1)\X+32, i, distance+5) , RotationY(soleil(1)\Y+32, i, distance+5),1,1,lumiere)
                    Break 1
                 Else
                    lumiere= RGB ($FF,$FF,$97) ; lumiere du soleil
                     Plot (RotationX(soleil(1)\X+32, i, distance) , RotationY(soleil(1)\Y+32, i, distance),lumiere)
                 EndIf
                 If KeyboardPushed ( #PB_Key_All )
                     End
                 EndIf
                 While WindowEvent () : Wend
             Next distance
            flag=0
         Next i
         StopDrawing ()
     EndProcedure
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

dans ce listing le but est simple charger un image jpg
le prg va regarder tout les point de couleur de l'image et vas permuter
les couleurs entre elles

pour une image de 1024x768 cela prends plusieurs secondes (12) sur mon P4 a 3.2 Ghz carte graph FX57000 !!! :?

c'est pas tres rapide quand meme , lorsque je compare des soft de retouche ou l'effet se fait en temps reel !! :)

bon il utilient peut etre des algo plus performant , mais je pense qu'un plot et point() "Turbo" apporterai un vrais plus au Purebasic pour les traitements graphiques ....

d'autant plus que certain ici sont arriver a faire mieux en vitesse que le plot actuel (Le Soldat inconnu par exemple ...)


voici le listing du code expliqué ci-dessus (echange de couleurs)



  ; *********** initialisation *********
UseJPEGImageDecoder ()

; ******************************


InitMouse ()


   ; ******** ** pour le sprite *****************
InitSprite ()
; ***************************************



OpenWindow (1, 1,1, 800, 600, #PB_Window_SystemMenu , "quitter avec boutton droit !!" ) ; on ouvre une fenetre
OpenWindowedScreen ( WindowID (1) , 0, 0, 800, 600, 1, 1, 1) ; on met un ecran dedans !!
image$ = OpenFileRequester ( "Charge une image" , "" , "*.jpg" , "c:\" )
Resultat = LoadImage (1,image$ )
im_id= ImageID ()
Largeur = ImageWidth ()
Hauteur = ImageHeight ()
ResizeWindow (Largeur, Hauteur)
Resultat = StartDrawing ( ScreenOutput ())
DrawImage (im_id, 0,0)
StopDrawing ()
FlipBuffers () ;

StartDrawing ( ScreenOutput ())
For Y=0 To Largeur
     For X=0 To Hauteur
        coul= Point (X,Y)
         If coul>0
            rouge= Red (coul)
            vert= Green (coul)
            bleu= Blue (coul)
            seau=rouge
            rouge=vert
            vert=bleu
            bleu=seau
             Plot (X,Y, RGB (rouge,vert,bleu))
         EndIf
     Next X
Next Y
StopDrawing ()
FlipBuffers () ;



Repeat ; boucle principale
    
    Event= WaitWindowEvent () ; on regarde si quelqu'un a cliqué sur la croix pour quitter
    Resultat = MessageRequester ( "travail termine" , "ok j'ai fini le test" , #PB_MessageRequester_Ok )
     End
    
     ExamineMouse ()
     If MouseButton (2) ; le bouton de souris droit fait quitter !
         End
     EndIf
    
    
    
     ; ClearScreen(0, 0, 0);
Until Event= #PB_Event_CloseWindow
Return
Niffo
Messages : 108
Inscription : dim. 29/août/2004 15:51

Message par Niffo »

@Fred : J'ai également remarqué que la fonctoin "Point()" était extrêmement lente sur les sprites alors qu'elle est aussi rapide que l'API "GetPixel()_" sur les images.

A tel point, que dans une de mes applications, je suis obligé de faire mes "Points()" et mes "Plots()" sur une image avant de la recopier dans un sprite avec un DrawImage().
Répondre