Problème avec la mémoire, Point(), et Plot()

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Problème avec la mémoire, Point(), et Plot()

Message par Octavius »

Comme vous le savez, Point() et Plot() sont des fonctions extrêmement lentes. J'ai donc entrepris de les remplacer dans mes programmes avec des fonctions perso qui accèdent directement à la mémoire.

Seulement voilà, alors que je croyais enfin avoir réussi à y faire fonctionner, je m'aperçois que si on manipule les images (ResizeImage() dans mon exemple), mes fonctions perso ne fonctionnent plu.

Voici mon code :

Code : Tout sélectionner

Procedure.l ReverseRGB(Color.l)
  ProcedureReturn RGB(Blue(Color),Green(Color),Red(Color))
EndProcedure

Procedure.l PointMemory(Image.l,X.l,Y.l)
  Protected bmp.BITMAP,Color.l,Width.l,Height.l,Depth.b,*Address
  
  ;On initialise la taille de l'image
  Width=ImageWidth(Image)
  Height=ImageHeight(Image)
  Depth=ImageDepth(Image)/8
  
  ;On vérifie les coordonnées
  If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1
    ProcedureReturn -1
  EndIf
  
  ;Adresse de l'image
  GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits
  
  ;Récupération de la couleur du point
  If *Address
    CopyMemory(*Address+X*Depth+Y*Depth*(Width+1),@Color,Depth)
  EndIf
  
  ;Attention à bien inverser les conventions BGR et RGB
  ProcedureReturn ReverseRGB(Color)
  
EndProcedure

Procedure.b PlotMemory(Image.l,X.l,Y.l,Color.l)
  Protected bmp.BITMAP,Width.l,Height.l,Depth.b,*Address
  
  ;On initialise la taille de l'image
  Width=ImageWidth(Image)
  Height=ImageHeight(Image)
  Depth=ImageDepth(Image)/8
  
  ;On vérifie les coordonnées
  If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1
    ;Echec de l'opération
    ProcedureReturn #False
  EndIf
  
  ;Adresse de l'image
  GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits
  ;Inversion de la convention RGB et BGR
  Color=ReverseRGB(Color)
  ;Collage du point dans l'image
  If *Address
    CopyMemory(@Color,*Address+X*Depth+Y*Depth*(Width+1),Depth)
  EndIf
  ;Réussite de l'opération
  ProcedureReturn #True
  
EndProcedure

CreateImage(0,295,189,24)
CreateImage(1,295,189,24)
ResizeImage(1,590,398,#PB_Image_Raw)

PlotMemory(0,10,10,$FFFFFF)
PlotMemory(1,10,10,$FFFFFF)

SaveImage(0,"image1.bmp")
SaveImage(1,"image2.bmp")
Voilà, il vous suffit d'ouvrir les deux images générées pour vous apercevoir que dans l'une, il bien un point blanc en bas à gauche, et que dans l'autre il y a deux points de couleur. 8O

C'est un exemple avec PlotMemory() mais j'ai fait d'autres tests qui me montrent que PointMemory(), fonction très semblable, ne fonctionne pas non plu correctement.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

8O

Heu non, chez moi ça marche à merveille :
- 1 point blanc dans une petite image
- 1 point blanc dans une grande image

:?:
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Ben je viens de revérifier, moi j'ai un point jaune et un point bleu côte à côte dans la grande image...
Avatar de l’utilisateur
Eric
Messages : 79
Inscription : dim. 08/juil./2007 21:38
Localisation : Nord
Contact :

Message par Eric »

+1

point blanc dans les deux images.

je possède une CG 8800 GTS 512 sous XP pro

Cdt,

Eric
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Toujours deux points jaune et bleu. Idem si je suis créé un exécutable.

Ma config :
(ordinateur portable)
Carte graphique NVIDIA GeForce Go 7600
Processeur Genuine Intel(R) CPU T2400 1.83 GHz
Système d'exploitation Windows XP Edition Familiale
RAM de 2 Go
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

XP
Video NVidia GForce4 MX440
PB 4.10 B2
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Ah j'oubliais PB 4.10
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Rajoute un «+1» dans le 2 ème argument (*destination) de ta commande CopyMemory().

Sinon remplace «+1» par «-1». Un de ces 2 solutions doit être bonne. Le cas échéant, je ne peux pas t'expliquer pourquoi.
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

En rajoutant un «-1» j'obtiens effectivement un point blanc dans l'image agrandie (bien qu'en fait pas aux coordonnées attendues...), par contre j'ai maintenant un deux points rouge et vert dans l'image d'origine non agrandit... :?
Avatar de l’utilisateur
Eric
Messages : 79
Inscription : dim. 08/juil./2007 21:38
Localisation : Nord
Contact :

Message par Eric »

en passant les images en 32 bits
essaye le code suivant ...

Code : Tout sélectionner

Procedure.l ReverseRGB(Color.l) 
  ProcedureReturn RGB(Blue(Color),Green(Color),Red(Color)) 
EndProcedure 

Procedure.l PointMemory(Image.l,X.l,Y.l) 
  Protected bmp.BITMAP,Color.l,Width.l,Height.l,Depth.b,*Address 
  
  ;On initialise la taille de l'image 
  Width=ImageWidth(Image) 
  Height=ImageHeight(Image) 
  Depth=ImageDepth(Image)/8 
  
  ;On vérifie les coordonnées 
  If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1 
    ProcedureReturn -1 
  EndIf 
  
  ;Adresse de l'image 
  GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits 
  
  ;Récupération de la couleur du point 
  If *Address 
    CopyMemory(*Address+X*Depth+Y*Depth*(Width+1),@Color,Depth) 
  EndIf 
  
  ;Attention à bien inverser les conventions BGR et RGB 
  ProcedureReturn ReverseRGB(Color) 
  
EndProcedure 

Procedure.b PlotMemory(Image.l,X.l,Y.l,Color.l) 
  Protected bmp.BITMAP,Width.l,Height.l,Depth.b,*Address 
  
  ;On initialise la taille de l'image 
  Width=ImageWidth(Image) 
  Height=ImageHeight(Image) 
  Depth=ImageDepth(Image)/8 
  
  ;On vérifie les coordonnées 
  If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1 
    ;Echec de l'opération 
    ProcedureReturn #False 
  EndIf 
  
  ;Adresse de l'image 
  GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits 
  ;Inversion de la convention RGB et BGR 
  Color=ReverseRGB(Color) 
  ;Collage du point dans l'image 
  If *Address 
    CopyMemory(@Color,*Address+X*Depth+Y*Depth*Width,Depth) 
  EndIf 
  ;Réussite de l'opération 
  ProcedureReturn #True 
  
EndProcedure 

CreateImage(0,295,189,32) 
CreateImage(1,295,189,32) 
ResizeImage(1,590,398,#PB_Image_Smooth) 

PlotMemory(0,10,10,$FFFFFF) 
PlotMemory(1,10,10,$FFFFFF) 

SaveImage(0,"image1.bmp") 
SaveImage(1,"image2.bmp")
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Effectivement les deux images ont bel et bien un point blanc quand je passe en 32 bits...

Passer en 32 bits, c'est une drôle d'idée, mon calcul pour le PlotMemory() prend en compte la profondeur... Il y a qqch que je ne comprends pas... De plus j'ai vérifié, la fonction ResizeImage() conserve la profondeur de l'image d'origine.

Et ça n'explique pas pourquoi chez certains mon programme d'origine semble fonctionner...
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Ton lien décrit une méthode pour accéder plus rapidement à l'OutputID de l'image, apparemment ça ne fonctionne pas ou ne ça va pas plus vite sur les toutes dernières versions de PB. Un point intéressant c'est que eux semblent cantonnés au 32 bits pour avoir un résultat satisfaisant.

Je ne n'utilise pas du tout l'OutputID, j'accède directement à la mémoire de l'image avec une fonction API que j'ai trouvé.

Peut-être qu'il me manque un paramètre pour mes formules ? Je ne maîtrise pas vraiment l'API.
Avatar de l’utilisateur
Eric
Messages : 79
Inscription : dim. 08/juil./2007 21:38
Localisation : Nord
Contact :

Message par Eric »

je crois que j'ai trouvé mais cela ne marche qu'avec les image 32 bits

Code : Tout sélectionner

Procedure.l ReverseRGB(Color.l) 
  ProcedureReturn RGB(Blue(Color),Green(Color),Red(Color)) 
EndProcedure 

Procedure.l PointMemory(Image.l,X.l,Y.l) 
  Protected bmp.BITMAP,Color.l,Width.l,Height.l,Depth.b,*Address 
  
  ;On initialise la taille de l'image 
  Width=ImageWidth(Image) 
  Height=ImageHeight(Image) 
  Depth=ImageDepth(Image)/8 
  
  ;On vérifie les coordonnées 
  	If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1 
    	ProcedureReturn -1 
	Else
  
  	;Adresse de l'image 
  		GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits 
  
  	;Récupération de la couleur du point 
 		If *Address 
    		CopyMemory(*Address+X*Depth+(Height-Y)*Depth*Width,@Color,Depth) 
  		EndIf 
  
  	;Attention à bien inverser les conventions BGR et RGB 
  		ProcedureReturn ReverseRGB(Color) 
	EndIf 

  
EndProcedure 

Procedure.b PlotMemory(Image.l,X.l,Y.l,Color.l) 
  Protected bmp.BITMAP,Width.l,Height.l,Depth.b,*Address 
  
  ;On initialise la taille de l'image 
  Width=ImageWidth(Image) 
  Height=ImageHeight(Image) 
  Depth=ImageDepth(Image)/8 
  
  ;On vérifie les coordonnées 
  	If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1 
    ;Echec de l'opération 
    	ProcedureReturn #False 
	Else
		  
  	;Adresse de l'image 
  		GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) 
  		*Address=bmp\bmBits 
  	;Inversion de la convention RGB et BGR 
  		Color=ReverseRGB(Color) 
  	;Collage du point dans l'image 
  		If *Address 
    		CopyMemory(@Color,*Address+X*Depth+(Height-Y)*Depth*Width,Depth) 
  		EndIf 
  	;Réussite de l'opération 
  		ProcedureReturn #True 
  	EndIf 

  
EndProcedure 

CreateImage(0,295,189,32) 
CreateImage(1,295,189,32) 
ResizeImage(1,590,398,#PB_Image_Raw) 

PlotMemory(0,10,10,$FFFFFF) 
PlotMemory(1,10,10,$FFFFFF) 
Debug Hex(PointMemory(0,10,10))
Debug Hex(PointMemory(1,10,10))
SaveImage(0,"image1.bmp") 
SaveImage(1,"image2.bmp")
il y avait un problème de coordonnées ...

Cdt,

Eric
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Tu as changé Y par (Height-Y), ce qui a pour effet de changer l'origine du repère qui était dans le coin en bas à gauche vers le coin en haut à gauche. (cela correspond mieux aux coordonnées données par Paint, mais ce n'était pas un problème en soi)

Les coordonnées allant de 0 à Height-1 et non de 1 à Height il aurait fallu plutôt remplacer Y par (Height-Y-1). Voici le code correct :

Code : Tout sélectionner

Procedure.l ReverseRGB(Color.l)
  ProcedureReturn RGB(Blue(Color),Green(Color),Red(Color))
EndProcedure

Procedure.l PointMemory(Image.l,X.l,Y.l)
  Protected bmp.BITMAP,Color.l,Width.l,Height.l,Depth.b,*Address
  
  ;On initialise la taille de l'image
  Width=ImageWidth(Image)
  Height=ImageHeight(Image)
  Depth=ImageDepth(Image)/8
  
  ;On vérifie les coordonnées
  If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1
    ProcedureReturn -1
  EndIf
  
  ;Adresse de l'image
  GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits
  
  ;Récupération de la couleur du point
  If *Address
    CopyMemory(*Address+X*Depth+(Height-Y-1)*Depth*Width,@Color,Depth)
  EndIf
  
  ;Attention à bien inverser les conventions BGR et RGB
  ProcedureReturn ReverseRGB(Color)
  
EndProcedure

Procedure.b PlotMemory(Image.l,X.l,Y.l,Color.l)
  Protected bmp.BITMAP,Width.l,Height.l,Depth.b,*Address
  
  ;On initialise la taille de l'image
  Width=ImageWidth(Image)
  Height=ImageHeight(Image)
  Depth=ImageDepth(Image)/8
  
  Debug Depth
  
  ;On vérifie les coordonnées
  If X<0 Or X>Width-1 Or Y<0 Or Y>Height-1
    ;Echec de l'opération
    ProcedureReturn #False
  EndIf
  
  ;Adresse de l'image
  GetObject_(ImageID(Image),SizeOf(BITMAP),@bmp) : *Address=bmp\bmBits
  ;Inversion de la convention RGB et BGR
  Color=ReverseRGB(Color)
  ;Collage du point dans l'image
  If *Address
    CopyMemory(@Color,*Address+X*Depth+(Height-Y-1)*Depth*Width,Depth)
  EndIf
  ;Réussite de l'opération
  ProcedureReturn #True
  
EndProcedure

CreateImage(0,295,189,32)
CreateImage(1,295,189,32)
ResizeImage(1,590,398,#PB_Image_Raw)

PlotMemory(0,10,10,$FFFFFF)
PlotMemory(1,10,10,$FFFFFF)

SaveImage(0,"image1.bmp")
SaveImage(1,"image2.bmp")
Ceci dit, cela ne règle pas le problème de savoir pourquoi ça ne fonctionne que avec les images 32 bits, et pourquoi le premier code que j'ai donné fonctionne avec les images 24 bits que si on ne les a pas manipulé auparavant (avec ResizeImage() par exemple).

Se pourrait-il qu'il y ait un bug de PureBasic derrière cette histoire ?
Répondre