2017-03-12 10 views
0

Aufgrund der Anforderungen von dem, was ich versuche zu tun, muss ich meine eigene benutzerdefinierte Klasse für Pixel haben. Für jedes Pixel I haben:So erstellen Sie ein schnelles benutzerdefiniertes Pixelformat

byte red 
byte green 
byte blue 
int brightness 
int X 
int Y 

I die Koordinaten müssen, so kann ich Arrays bilden, die nur aus den Pixeln bestehen, die I zeichnen müssen. Wenn ich zum Beispiel eine Linie habe, die sich diagonal bewegt, möchte ich nur eine eindimensionale Anordnung der Pixel haben, die ich zeichnen muss; Ich möchte nicht den Rest der Pixel scannen müssen, damit ich unnötiges Scannen vermeiden kann. In meinem aktuellen Fall werde ich viele Polygone haben, die auf ein Bild in einer bestimmten Reihenfolge und auf spezifische Weise angewendet werden müssen. Dies wird für eine Spielengine sein, also muss ich versuchen, das Scannen durch Pixel zu vermeiden, die sowieso nicht verwendet werden.

Da die Daten in der Pixel-Klasse jedoch so sind, wird es langsam. Wirklich langsam. Vielleicht hundertmal langsamer als das Standard-Pixelformat, mit dem Bitmaps erstellt werden. Außerdem sind Änderungen an den Pixeln sehr langsam.

Wie kann ich die Erstellung und Bearbeitung von Pixeln beschleunigen und gleichzeitig alle Informationen für Farbe, Helligkeit und Koordinaten in jedem Pixel speichern? Eine Nebenfrage: Gibt es einen Ort, an dem erklärt wird, wie die Pixelformate in System.Drawing funktionieren?

Antwort

0

Sie können überlasten, um auf ein internes Array eines Singleton zuzugreifen, anstatt auf viele Klasseninstanzen zuzugreifen, die in einem schrittweisen Muster zugreifen. So pixels[n].X Zugriff auf "Pixel" Objekt interne Array oder Array von Strukturen, dann bekommen Sie das X daraus schnell.

Alle Pixelattribute in einer Struktur haben. Verwenden Sie die Indizierung aus der Pixelklasse, um auf diese Struktur zuzugreifen. Setzen Sie diese Struktur in ein struct-Array.

Verwenden Sie StructLayoutAttribute, um Struct in eine geeignete Größe (und Ausrichtung) für eine bessere Zugriffsleistung zu packen.

Ordnen Sie die Felder in struct neu an, um alle Daten in (wahrscheinlich) weniger Speicheroperationen lesen zu können.

Kann nützlich sein, wenn Sie alle Attribute in einer Funktion verwenden.


Statt Array von Strukturen, können Sie einen nicht verwalteten Speicherbereich (gegeben durch Spiel-Engine Allocator) für alle Pixel und lesen von größeren Brocken verwenden, um den Übergang Gemeinkosten elliminate. (In nur 1 eine ganze Struktur lesen oder 2 intrinsische Ladeanweisungen). Aktualisieren Sie in größeren Blöcken (oder sammeln Sie temporäre Ergebnisse in) mit Zeigern und unsicheren Kontexten.

int X 
int Y 
int brightness 
byte red 
byte green 
byte blue 
byte alpha 

sollte in der Lage sein, in eine 16-Byte-Strukturgrenze zu passen.


Wenn Sie verwenden werden koordiniert getrennt von Farben, oder einige Attribute nicht Gebrauch immer sein, sollten Sie sie lösen und als ein Array von Primitiven verwenden, so dass es ein kleinen Schritt Element macht für die nächste Pixel iterieren . Wenn Sie X und Y zusammen in einem Space-Suchalgorithmus, aber nicht in Farben verwenden, können Sie X und Y in einem anderen Array (nicht in Klasse, nur) von Strukturen mit jeweils X und Y umgruppieren, so dass Farbattribute nicht erhalten werden auf Ihre Weise leistungsorientiert.


Wenn Sie X zugreifen,

public class MyPixel{ 
    public float X{ 
       get{ /* access an array or 
         array of structs or 
         unmanaged memory */} 
       set{ /* same */} 
    } 

    // for unrolled loops 
    public static void BatchUpdateXY(float[] source,int pixelStart,int pixelEnd) 
    { /* copy from source */} 
} 

Auch wenn Setter Getter Kosten% 50 Leistung, damit Sie pixels.X[i] stattdessen versuchen kann und maximale Geschwindigkeit haben (mit Arrays oder nicht verwalteten Speicher).


ein neues Pixel Hinzufügen wird schwieriger mit reinem C++ Arrays in oberen Lösungen so Sie Vektoren oder ähnliche Behälter in C++ Seite benötigen.

0

Das ist eigentlich, was Zeichnungsfunktionen in einer optimierten Weise tun (und wahrscheinlich hardwarebeschleunigt). Nicht sicher, warum Sie Ihre eigenen Zeichenfunktionen benötigen (d. H., Sie berechnen jedes Pixel, um eine Diagonale oder ein Polygon zu bilden).

Vielleicht könnten Sie, anstatt jedes Pixel zu berechnen und zu speichern, nur die Punkte speichern, die verbunden werden müssen, und dann eine Zeichenfunktion aufrufen, um die Arbeit zu erledigen?

Wenn Sie dies wirklich selbst tun müssen, wäre wahrscheinlich der beste Weg, ein Array oder Vektor von 32-Bit-RGBA-Ganzzahlen der Größe width * height zu erstellen, die viel schneller zu handhaben wären.

Und das ist eigentlich eine Bitmap, also was Sie tun könnten, ist eine Bitmap im Speicher zu erstellen, verwenden Sie Standard-Zeichenfunktionen zum Zeichnen der Linien auf dieser Bitmap (das ist ein Array mit Ihren RGBA-Punkten). Einmal durch alle Pixel am Ende zu gehen, ist viel schneller als in einem 1D-Array, das durchsucht, sortiert und vergrößert werden müsste.

Sie können sogar TransparentBlt() verwenden, um alle "Nicht-Null" -Pixel in einem Schritt auf Ihr Bild zu verschieben.

Verwandte Themen