Page 1 sur 1

La fonction point() a accelerer !!!

Publié : dim. 25/déc./2005 12:37
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

Publié : dim. 25/déc./2005 22:08
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.

Publié : dim. 25/déc./2005 22:29
par Backup
Polo a écrit :Pas possible
comment ça pas possible ?

Publié : dim. 25/déc./2005 23:31
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.

Publié : lun. 26/déc./2005 0:43
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...

Publié : lun. 26/déc./2005 10:11
par Polo
Le problème, c'est que cela ne marche qu'avec les sprites...

Publié : lun. 26/déc./2005 11:02
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

Publié : lun. 26/déc./2005 11:06
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

Publié : jeu. 05/janv./2006 17:52
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

Publié : jeu. 05/janv./2006 19:01
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

Publié : ven. 06/janv./2006 9:59
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:

Publié : ven. 06/janv./2006 12:46
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.

Publié : ven. 06/janv./2006 22:47
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

Publié : ven. 06/janv./2006 23:53
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

Publié : lun. 23/janv./2006 15:44
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().