Auf der Suche nach einer Funktion zum Rotieren von Bildern in C# bin ich auf folgenden Beitrag auf dotnet-snippets.de gestoßen: Bilder rotieren mit C#.
Neben der eigentlich vorgestellten Methode wurden in den Kommentaren noch 2 andere Methoden vorgestellt und die Frage in den Raum geworfen, welche Methode davon die schnellste sei. Da dies auch mein Interesse weckte, habe ich kurzerhand eine kleine Test-Applikation geschrieben, die die verschiedenen vorgestellten Funktionen auf Herz und Nieren ihre Geschwindigkeit überprüfen sollte.
Nach einigen Testläufen wurde klar, dass die eigentliche Funktion nicht geeignet war, da in ihr jedes Mal ein neues Bitmap Objekt erstellt wurde, was Unmengen an Speicher frisst. Somit wurde folgende Funktion aus den Tests ausgeschlossen.
public Bitmap rotateImage(Bitmap bitmap, float angle) { Bitmap returnBitmap = new Bitmap(bitmap.Width, bitmap.Height); Graphics graphics = Graphics.FromImage(returnBitmap); graphics.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2); graphics.RotateTransform(angle); graphics.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2); graphics.DrawImage(bitmap, new Point(0, 0)); return returnBitmap; }
Im Rennen blieb jedoch folgende, leicht veränderte, ebenfalls dem Graphics-Object basierende Funktion,
public Bitmap rotateImageUsi(Bitmap bitmap, float angle) { using (Graphics graphics = Graphics.FromImage(bitmap)) { graphics.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2); graphics.RotateTransform(angle); graphics.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2); graphics.DrawImage(bitmap, new Point(0, 0)); } return bitmap; }
sowie die Bitmap-Class eigene RotateFlip Funktion.
public Bitmap rotateInternalFunction(Bitmap bitmap) { bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); return bitmap; }
Zum Testen der Geschwindigkeit habe ich folgendes, komprimiertes Foto vom letzten Wochenende genommen.
(Anklicken um zum Bild in Originalgröße zu gelangen.)
Dann habe ich diese Bild mit beiden Funktionen jeweils 10, 100, 250, 500, 1000, 5000 und 10000 mal um 180° rotiert und die Zeit für Ausführung der Funktionen gemessen.
int[] testruns = new int[]{10,100,250,500,1000,5000,10000}; Bitmap bmp = (Bitmap)Bitmap.FromFile(pic); string result = string.Empty; foreach (int x in testruns) { DateTime s2 = DateTime.Now; for (int i = 0; i < x; i++) { rotateImageUsi(bmp, 180f); } DateTime e2 = DateTime.Now; DateTime s3 = DateTime.Now; for (int i = 0; i < x; i++) { rotateInternalFunction(bmp); } DateTime e3 = DateTime.Now; TimeSpan t2 = new TimeSpan(e2.Ticks - s2.Ticks); TimeSpan t3 = new TimeSpan(e3.Ticks - s3.Ticks); result += "Durchläufe: " + x.ToString() + "\r\n" + t2.TotalMilliseconds.ToString() + "\r\n" + t3.TotalMilliseconds.ToString() + "\r\n\r\n==========================\r\n"; }
Dabei kam ich zu folgenden Ergebnissen:
Testdurchläufe | Zeit in ms – Graphics-Object | Zeit in ms – Bitmap.RotateFlip |
10 | 640 | 23 |
100 | 5327 | 167 |
250 | 10955 | 409 |
500 | 18641 | 758 |
1000 | 35375 | 1343 |
5000 | 232421 | 7270 |
10000 | 448424 | 9734 |
Getestet habe ich das ganze auf meinem Laptop mit einem Intel Core i3 M330 Prozessor, 4GB Arbeitsspeicher, .Net-Framework 4 unter Windows 7.
Betrachtet man die Ergebnisse, so lässt sich sagen, dass die RotateFlip-Variante wesentlich schneller ist, was vor allem bei der Bearbeitung von vielen Bildern zu Buche schlägt.
Einen Grund gibt es dennoch auf die Graphics Variante zurückzugreifen: Der frei wählbare Winkel im Gegenteil zu RotateFlip.
Solltet ihr nun auch Lust bekommen haben, könnt ihr euch meine Testumgebung hier als Visual Studio Projekt herunterladen und eure eigenen Tests durchführen. Über Kommentare würde ich mich wie immer natürlich sehr freuen.
Viele Grüße,
Raffi
Not a game machine. Maybe in the future it’ll do even better in those areas, but for now it’s a fantastic way to organize and listen to your music and videos, and is without peer in that regard. The iPod’s strengths are its web browsing and apps. If those sound more compelling, perhaps it is your best choice.