Page 1 sur 3

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

Publié : lun. 02/juin/2008 12:26
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.

Publié : lun. 02/juin/2008 12:41
par Ollivier
8O

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

:?:

Publié : lun. 02/juin/2008 12:44
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...

Publié : lun. 02/juin/2008 13:26
par Eric
+1

point blanc dans les deux images.

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

Cdt,

Eric

Publié : lun. 02/juin/2008 13:43
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

Publié : lun. 02/juin/2008 13:43
par Ollivier
XP
Video NVidia GForce4 MX440
PB 4.10 B2

Publié : lun. 02/juin/2008 13:45
par Octavius
Ah j'oubliais PB 4.10

Publié : lun. 02/juin/2008 13:49
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.

Publié : lun. 02/juin/2008 14:01
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... :?

Publié : lun. 02/juin/2008 14:32
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")

Publié : lun. 02/juin/2008 14:37
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...

Publié : lun. 02/juin/2008 14:52
par djes

Publié : lun. 02/juin/2008 15:35
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.

Publié : lun. 02/juin/2008 17:50
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

Publié : lun. 02/juin/2008 19:05
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 ?