2010-04-30 7 views
2

J'ai besoin d'une implémentation rapide des algorithmes d'interpolation courants. J'ai compris que C# dans de tels algorithmes simples serait beaucoup plus lent que C++ donc je pense à écrire du code natif et à l'utiliser dans mon interface graphique C#. Tout d'abord, j'ai effectué quelques tests et peu d'opérations sur la matrice 1024x1024x3 ont pris 32ms en C# et 4ms en C++ et c'est ce dont j'ai le plus besoin. Cependant, l'interpolation n'est pas un bon mot car je n'en ai besoin que pour la réduction d'échelle. Mais la question est: Est-il plus rapide que C# méthodes Drawing2DVitesse des algorithmes d'interpolation, C# et C++ travaillant ensemble

Image outputImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); 
Graphics grPhoto = Graphics.FromImage(outputImage); 

grPhoto.InterpolationMode = InterpolationMode.*; //all of them 

grPhoto.DrawImage(bmp, new Rectangle(0, 0, destWidth, destHeight), 
Rectangle(0, 0, sourceWidth, sourceHeight), GraphicsUnit.Pixel); 

grPhoto.Dispose(); 

Certains d'entre eux dans l'exécution de la méthode 20ms et certains en 80. Est-il possible de le faire plus vite?


EDIT 1:

Tout d'abord j'utilise XNA dans cette application, mais il semble y avoir aucun moyen de sélectionner la méthode d'interpolation différente. Bien sûr, cela fonctionne très vite.

Idéal serait de mettre en œuvre ces méthodes sur une carte graphique.


EDIT 2:

Voici ma méthode tout:

private unsafe Texture2D Scale(GraphicsDevice gd, Texture2D texture, float scale) 
    { 

     int sourceWidth = texture.Width; 
     int sourceHeight = texture.Height; 

     int destWidth = (int)(sourceWidth * scale); 
     int destHeight = (int)(sourceHeight * scale); 

     StopwatchEx sw = new StopwatchEx(); 
     sw.IntervalStart(); 
     //convert texture into bitmap 
     byte[] textureData = new byte[4 * sourceWidth * sourceHeight]; 
     texture.GetData<byte>(textureData); 

     System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(sourceWidth, sourceHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
     System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new System.Drawing.Rectangle(0, 0, sourceWidth, sourceHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly, 
         System.Drawing.Imaging.PixelFormat.Format32bppArgb); 

     IntPtr safePtr = bmpData.Scan0; 
     System.Runtime.InteropServices.Marshal.Copy(textureData, 0, safePtr, textureData.Length); 
     bmp.UnlockBits(bmpData); 


     //output bitmap 
     System.Drawing.Image outputImage = new System.Drawing.Bitmap(destWidth, destHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 
     System.Drawing.Graphics grPhoto = System.Drawing.Graphics.FromImage(outputImage); 

     grPhoto.InterpolationMode = (System.Drawing.Drawing2D.InterpolationMode)(interpolationMode); 
     grPhoto.SmoothingMode = (System.Drawing.Drawing2D.SmoothingMode)smoothingMode; 
     grPhoto.PixelOffsetMode = (System.Drawing.Drawing2D.PixelOffsetMode)pixelOffsetMode; 

     grPhoto.DrawImage((System.Drawing.Image)bmp, new System.Drawing.Rectangle(0, 0, destWidth, destHeight), 
      new System.Drawing.Rectangle(0, 0, sourceWidth, sourceHeight), System.Drawing.GraphicsUnit.Pixel); 

     grPhoto.Dispose(); 

     textureData = new byte[4 * sourceWidth * sourceHeight]; 

     MemoryStream ms = new MemoryStream(); 
     ((System.Drawing.Bitmap)outputImage).Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); 

     ms.Seek(0, SeekOrigin.Begin); 
     Texture2D result = Texture2D.FromFile(gd, ms); 
     ms.Dispose(); 
     sw.IntervalStop(); 
     sw.AppendResults("MEGS.txt");  

     return result; 
    } 

Le plus drôle est que HighQualityBicubic est beaucoup plus rapide que bicubique. (40ms vs 100ms)

+2

Comment avez-vous calculé la durée de ces opérations? Les fonctions GDI en C# appellent simplement l'API non managée; il ne devrait pas y avoir de différence de vitesse (généralement appréciable) entre C# et C++ en faisant la même chose. –

+0

@Adam Robinson 'Stopwatch' classe. Ne serait pas plus rapide d'écrire ces méthodes moi-même et d'appeler la méthode dlls non managée en donnant un pointeur vers l'image en mémoire retournant un autre pointeur? – Kaminari

+0

Pas très probable, puisque le travail n'est pas fait en code managé. –

Répondre

0

Avez-vous essayé ceci avec la méthode GetThumbnailImage?

Pour étendre davantage Adam Robinson's comment: J'espère que vous avez chronométré cela en utilisant le Stopwatch class?

+0

Bien sûr, j'ai utilisé chronomètre. Et dites-moi où placer la méthode d'interpolation dans 'GetThumbnailImage' – Kaminari

+0

' GetThumbnailImage' est très limité, et selon la documentation de MSDN il ne fonctionnera pas bien pour les plus grandes tailles d'image de vignette. – stakx

1

Comment avez-vous implémenté votre matrice en C#?

Dans votre cas, une grande partie de la vitesse pourrait être perdue en raison de .Net ayant à faire des contrôles de limites dans un tableau matriciel par défaut. Dans ce cas, vous pouvez rendre votre code beaucoup plus rapide en utilisant C# non sécurisé (et donc en supprimant toutes les vérifications de limites).

Mais si cela fonctionne déjà assez vite avec les méthodes externes, pourquoi ne pas les utiliser?

+0

Ça ne marche pas assez vite. Et je n'ai pas encore de méthodes externes - un autre problème. – Kaminari

+0

Eh bien, essayez la méthode C# dangereuse.Je l'ai fait avec l'écriture de filtres d'image personnalisés (niveaux de gris, edgedetect et flou) et la performance a été assez bonne. – Foxfire

+0

pouvez-vous poster un exemple? J'ai essayé dangereux dans cette méthode mais la performance était la même. – Kaminari

Questions connexes