Utilisateur anonyme
-
14 sept. 2007 à 05:48
Utilisateur anonyme -
18 sept. 2007 à 12:31
Bonjour,
Dans le but de faire une application plus étendue, je souhaite faire une rotation d'image sans utiliser Graphics.RotateTransform qui fait pourtant vite et bien les choses. Doncm je me suis lancé dans la réalisation d'une fonction de rotation de mon image, si la fonction est correcte, elle est particulièment lente, la faute aux fonctions GetPixel et SetPixel que je ne sais pas comment remplacer. Voici le bout de code où je procède à cette étape :
try
{
Color color = bmp.GetPixel(xk, yk);
rotate.SetPixel(x, y, color);
}
catch
{
rotate.SetPixel(x, y, Color.White);
}
C'est une simple rotation avec la technique tout simple du plus proche voisin. La technique n'est pas ici un problème mais je souhaite accélérer les temps de calcul qui sont affreusement longs. Si vous pouviez m'aider à réécrire ce bout de code de façon plus adéquate, je vous en serai reconnaissant.
Lutinore
Messages postés3246Date d'inscriptionlundi 25 avril 2005StatutMembreDernière intervention27 octobre 201241 17 sept. 2007 à 17:37
Salut, bien plus rapide que GetPixel/SetPixel j'imagine quand même ?
- Essayes de sortir un maximum de calculs de la boucle.
- Utilise des constantes à la place de variables quand c'est possible.
- Remplace l'appel à la propriété image.Width par un variable.
Si c'est encore très long c'est peut être que tu tombes dans ton catch.. une execption c'est très couteux en temps CPU.
Mais surtout, avec les pointeurs, à aucun moment tu ne dois écrire ou lire dans une plage mémoire en dehors de ton bitmap, ce try/catch n'est pas du tout une bonne solution.
Merci pour le lien, je connaissais la technique mais comme je ne suis pas très bon, je ne savais pas l'utiliser pour l'application (légèrement) plus compliquée que je développe ici. C'est très bien expliqué et ça me permet de comprendre, ce qui est tout de même très bien (en tout cas, mieux que le copier/coller que j'avais fait dans un de mes programmes précédents).
J'ai réussi à implémenter le code sans trop de difficultés, cependant, le temps de traitement reste long quand je procède au traitement de mes deux images, il est probable que j'ai mal codé ce qui ralentirait le processus, je vous montre mon bout de code et si vous pouviez le critiquer, et éventuellement trouver l'erreur (ou les erreurs) que j'ai faite(s), cela m'aiderait grandement. Pour la petite anecdote, ce code est censé faire ce que fait la fonction Graphics.RotateTransform mais avec une interpolation par la technique du plus proche voisin (donc encore moins bien que la fonction d'origine) :
// To work fast with the original image by using pointer and method LockBits
// This code works with images in PixelFormat.Format32bppArgb
BitmapData bmpOrigin = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadOnly, image.PixelFormat);
// Create the new rotated picture
Bitmap rotate = new Bitmap(image.Width, image.Height);
BitmapData bmpFinal = rotate.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.WriteOnly, image.PixelFormat);
for (int y = 0; y < image.Width; y++)
{
for (int x = 0; x < image.Width; x++)
{
// Calcute coordonates on original picture
int ox = (int)(x * cos - y * sin);
int oy = (int)(y * cos + x * sin);
// Calcute pixel number to proceed
int oldPos = ox + (150 * oy);
int newPos = x + (150 * y);
try
{
// Give the new pixel color which is the same as in the
// original picture with its old coordonates
newPixel[newPos] = oldPixel[oldPos];
}
catch
{
// If the old pixel doesn't exist, put a white background
newPixel[newPos] = 0xFFFFFFFF;
}
}
}
// Dispose resources
rotate.UnlockBits(bmpFinal);
image.UnlockBits(bmpOrigin);
Vous n’avez pas trouvé la réponse que vous recherchez ?
Avec le try catch, c'était presque aussi long que la méthode GetPixel/SetPixel !!! C'est vrai qu'en l'enlevant, on gagne beaucoup, j'ai remplacé par un if et la différence est énorme, je ne savais pas que cela était si couteux (ignorant que je suis). Ce n'est pas encore aussi rapide que la méthode Graphics.RotateTransform mais ça, c'est mon problème.
Merci pour l'aide apportée, les deux réponses répondent très bien à toutes mes questions.
Merci pour cette précision, j'avais déjà pris note de la remarque et c'est vrai que ça fait quelques instructions supplémentaires... par contre, les calculs de la boucle sont, je pense, impossible à sortir de là (sinon, ils ne seraient pas dans la boucle).
Je vais essayer de lui faire faire une interpolation bilinéaire pour que ça soit quand même plus joli et après, je pense aux rotations 3D, j'espère que ça sera assez rapide...