Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

51

10.09.2015, 17:38

Wow, du bist super, vielen Dank! ^^
Mit der Zeile ist es jetzt ca. um den Faktor 15 schneller. Nur doch diese Zeile. Das sowas überhaupt möglich ist.
Von 10 Sekunden für ein 4 Megapixel Bild auf 700 Millisekunden.

C#-Quelltext

1
((uint*)ptr)[x + y * (stride / 4)] = ((uint*)ptrOriginal)[xO + yO * (strideOriginal / 4)]; //ABGR: alles aufeinmal

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

52

11.09.2015, 11:11

Mit deinem Parallel.For konnte ich nun noch mal von 700 Millisekunden für das Testbild auf 200 Millisekunden reduzieren.

Für das Archiv hier wieder die funktionierende und optimierte Methode:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
 public Bitmap quadDistort(Bitmap disortBitmap, Bitmap background, Vec2[] vectoren)
        {
            //Testen, ob ein Rechteck vorliegt, da diese mit dem BitmapDistortFast Algorithmus nicht gezeichnet werden können
            if (isRectangular(vectoren))
            {
                //Rechtecke können mit den GDI Funktionen gezeichnet werden
                using (Graphics gr = Graphics.FromImage(background))
                {
                    int x = (int)vectoren[0].x;
                    int y = (int)vectoren[0].y;
                    int imageWidth = (int)vectoren[1].x - x;
                    int imageHeight = (int)vectoren[3].y - y;

                    gr.DrawImage(disortBitmap, new Rectangle(x, y, imageWidth, imageHeight));
                }
                return background;
            }

            BitmapData dataNeu = background.LockBits(new Rectangle(0, 0, background.Width, background.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            int stride = dataNeu.Stride;

            BitmapData dataOriginal = disortBitmap.LockBits(new Rectangle(0, 0, disortBitmap.Width, disortBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            int strideOriginal = dataOriginal.Stride;

            int width = background.Width;
            int height = background.Height;

            int widthDistort = disortBitmap.Width;
            int heightDistort = disortBitmap.Height;

            Vec2 a = vectoren[0];
            Vec2 b = vectoren[1];
            Vec2 c = vectoren[2];
            Vec2 d = vectoren[3];

            unsafe
            {
                byte* ptr = (byte*)dataNeu.Scan0;
                byte* ptrOriginal = (byte*)dataOriginal.Scan0;

                //Code für Parallele Ausführung
                CancellationTokenSource cancellationSource = new CancellationTokenSource();
                ParallelOptions options = new ParallelOptions();
                options.CancellationToken = cancellationSource.Token;

                try
                {
                    ParallelLoopResult loopResult = Parallel.For(
                            0,
                            heightDistort,
                            options,
                            (y, loopState) =>
                            {
                                for (int x = 0; x < widthDistort; x++)
                                {

                                    Vec2 vecOriginalBild = invBilinear(new Vec2(x, y), a, b, c, d);
                                    vecOriginalBild.x = vecOriginalBild.x * widthDistort;
                                    vecOriginalBild.y = vecOriginalBild.y * heightDistort;
                                    if (vecOriginalBild.x >= 0 && vecOriginalBild.y >= 0 &&
                                        vecOriginalBild.x < widthDistort && vecOriginalBild.y < heightDistort)
                                    {
                                        int xO = (int)vecOriginalBild.x;
                                        int yO = (int)vecOriginalBild.y;

                                        ((uint*)ptr)[x + y * (stride / 4)] = ((uint*)ptrOriginal)[xO + yO * (strideOriginal / 4)]; //ABGR: alles aufeinmal
                                    }
                                }
                            });
                }
                catch (Exception e)
                {
                }
            }

            background.UnlockBits(dataNeu);
            disortBitmap.UnlockBits(dataOriginal);

            return background;
        }

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »MitgliedXYZ« (11.09.2015, 11:28) aus folgendem Grund: Tippfehler im Quellcode ausgebessert


MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

53

16.09.2015, 12:26

Gerade bin ich dabei die Funktionen mit LockBits in eine extra Klasse auszulagern, damit ich es leichter in anderen Projekten verwenden kann.
Mit den Pointern habe ich aber noch ein Verständnis-Problem.

Warum funktioniert das:

C#-Quelltext

1
2
 byte* ptr = (byte*)dataNeu.Scan0;
 ((uint*)ptr)[x + y * (stride / 4)] = ((uint*)ptrOriginal)[xO + yO * (strideOriginal / 4)];


Aber das hier führt zu einem Absturz:

C#-Quelltext

1
2
3
4
5
6
7
8
9
 public void setPixelPointer(int x, int y, uint* pointer)
        {
            ptr[x + y * (stride / 4)] = (byte)pointer;
        }

public uint* getPixelPointer(int x, int y)
        {
            return (uint*)ptr[x + y * (stride / 4)];
        }


Hier ist der Code der ganzen Klasse.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

54

16.09.2015, 12:56

Ich denke du hast in setPixelPointer die Dereferenzierung vergessen. Aktuell castest du die Adresse nach byte, nicht den Wert.

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

55

16.09.2015, 14:06

Den Begriff Dereferenzieren höre ich gerade zum ersten mal. Google spuckt da für C# auch nichts passsendes bei mir aus, hast du zufällig einen Link wo das erklärt wird? Mit Pointern und unsafe Code habe ich bis jetzt noch nicht viel Erfahrung.

Haben die äußeren Klammern hier eine Bedeutung

C#-Quelltext

1
((uint*)ptrOriginal)

oder ist diese Zeile damit identisch?

C#-Quelltext

1
(uint*)ptrOriginal

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

56

16.09.2015, 14:12

Dereferenzieren heißt einen Zeiger "aufzulösen".
Grob gesagt: Durch das Dereferenzieren eines Zeigers erhältst du den Wert, auf den er zeigt (zum Lesen oder Schreiben).
Infos: https://msdn.microsoft.com/en-us/library/z19tbbca.aspx (übrigens ganz einfach gefunden mit der Suchanfrage "c# dereference pointer", so viel also zum Thema "Google spuckt nichts Passendes aus" ...)

Und nein, die äußeren Klammern haben keine besondere Bedeutung, das sind einfach nur Klammern. Die haben die gleiche Wirkung wie bei (1+2)*3 vs. 1+2*3.

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

57

16.09.2015, 14:27

So kompliziert ist dereferenzieren dann ja garnicht. Ich teste mal, ob das der Fehler war.
Und wenn man den Begriff "Dereferenzieren C#" in Google eingibt, kommen wirklich keine brauchbaren Treffer. Auf Englisch hätte ich es noch versuchen können, war mir aber über die Schreibweise nicht sicher.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

58

16.09.2015, 14:32

Und wenn man den Begriff "Dereferenzieren C#" in Google eingibt, kommen wirklich keine brauchbaren Treffer.

Dritter Treffer: http://openbook.rheinwerk-verlag.de/visu…c29bfad762b66c1
Alles ausführlich erklärt ...

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

59

16.09.2015, 15:43

Der Link ist gut, wurde bei den Ergebnissen aber nicht angezeigt, Google generiert ja mittlerweile personalisierte Suchergebnisse...

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

60

16.09.2015, 16:10

In einem Incognito-Fenster kommt's sogar auf Platz 1 ... ;)

Werbeanzeige