Laden...

Performance von Blend-Effekt von einem Bild ins andere verbessern

Erstellt von kleinrechner vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.991 Views
K
kleinrechner Themenstarter:in
16 Beiträge seit 2018
vor 5 Jahren
Performance von Blend-Effekt von einem Bild ins andere verbessern

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

16.806 Beiträge seit 2008
vor 5 Jahren

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.

K
kleinrechner Themenstarter:in
16 Beiträge seit 2018
vor 5 Jahren

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

G
154 Beiträge seit 2015
vor 5 Jahren

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. 😁

5.657 Beiträge seit 2006
vor 5 Jahren

Ü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

K
kleinrechner Themenstarter:in
16 Beiträge seit 2018
vor 5 Jahren

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();
            }
        }

G
154 Beiträge seit 2015
vor 5 Jahren

Gute Sache, danke fürs Posten 👍