Hallo,
würde von einem Bild in ein anderes Bild überblenden lassen,
habe dafür aktuell folgende Funktion entwickelt:
var stepCount = 75;
return Enumerable.Range(0, stepCount).Select(x => GetImage(x, stepCount, secondaryImageMedia, primaryImageMedia));
private Bitmap GetImage(int x, int stepCount, Bitmap sourceImage, Bitmap targetImage)
{
var destination = new Bitmap(Math.Max(sourceImage.Width, targetImage.Width), Math.Max(sourceImage.Height, targetImage.Height));
using (var graphics = Graphics.FromImage(destination))
{
using (var attributes = new ImageAttributes())
{
//create a color matrix object
var matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = 1 - ((float)x / (float)stepCount);
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(sourceImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), 0, 0, destination.Width, destination.Height, GraphicsUnit.Pixel, attributes);
}
using (var attributes = new ImageAttributes())
{
//create a color matrix object
var matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = (float)x / (float)stepCount;
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(targetImage, new Rectangle(0, 0, targetImage.Width, targetImage.Height), 0, 0, destination.Width, destination.Height, GraphicsUnit.Pixel, attributes);
}
graphics.Save();
}
return destination;
}
Es funktioniert zwar und gibt mir das gewünschte ergebnis zurück, benötigt aber dafür ca. 5 sek.
Da ich sonst auch eher BusinessAnwendung, hab ich von Grafik-Bearbeitung leider ziemlich wenig Erfahrung, evlt sieht die BestPractice ja auch ganz anders aus.
Oder einen Tipp geben, wie ich das schneller machen kann oder parallelisieren kann, ohne dass ich Fehler bekomme, dass das Bild bereits in Verwendung ist.
Vielen Dank
cu
Christian
Naja, dann mach das, was man in so einem Fall eben tut: schmeiss den Performance Profiler, der in Visual Studio integriert ist, an und lass Dir den Hot Path zeigen.
Dann siehst auch die Stelle, die Zeit frisst.
Ich vermute, dass Dein DrawImage langsam sein wird; GDI+ ist eben halt auch nicht gerade die performanteste Art und Weise - und das wird eben hier verwendet.
Letzten Endes kann aber jeder hier nur raten.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Ich vermute, dass Dein DrawImage langsam sein wird; GDI+ ist eben halt auch nicht gerade die performanteste Art und Weise - und das wird eben hier verwendet.
Letzten Endes kann aber jeder hier nur raten.
Deshalb hatte ich ja gefragt, weil ich, wie gesagt, nicht so viel Erfahrung in Bildbearbeitung hab, evlt hat jemand einen besser Methode, wie man das umsetzen kann.
cu
Christian
Schau mal hier für das Prinzip:
https://code.msdn.microsoft.com/windowsapps/Blending-Bitmap-2922c196
Wenn das Überblenden nach Schrittzahl gehen soll, könnte man die Schrittweite pro Pixel getrennt hinterlegen und so noch minimal Rechenzeit sparen, soll das Überblenden nach Zeit gehen, müsste man die Schrittweite zumindest nach dem ersten Schritt anpassen.
Ansonsten könnte man auch hier wieder ein bissl lügen und betrügen und z.B. nur jeden zweiten Pixel abwechselnd ändern. 😁
Überblendungen können auch auf den schwächsten Geräten in Echtzeit berechnet und angezeigt werden. Zur Not mit GPU-Unterstützung.
Das, was du da zeigst, kann ich aber nicht nachvollziehen. Schau dir doch mal Implementierungen von Bibliotheken an, die sowas schon machen.
Weeks of programming can save you hours of planning
Falls es jemanden interessiert, hab es aktuell wie folgt gelöst, das funktioniert auch, wie gewünscht:
private void Timer_Tick(object sender, EventArgs e)
{
if (alpha <= 1)
{
using (var oldImage = pictureBox1.Image)
{
var destinationImage = new Bitmap(sourceImage);
using (var graphics = Graphics.FromImage(destinationImage))
{
using (var attributes = new ImageAttributes())
{
//create a color matrix object
var matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = alpha;
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(targetImage, new Rectangle(0, 0, targetImage.Width, targetImage.Height), 0, 0, destinationImage.Width, destinationImage.Height, GraphicsUnit.Pixel, attributes);
}
}
pictureBox1.Image = destinationImage;
alpha += 1 / (float)75;
}
}
else
{
timer.Stop();
}
}