Frage

In meiner App speichere ich Bitmap Daten in einem zweidimensionalen Ganzzahlarray (int[,]). Um auf die Werte r, g und b zugreifen zu können, verwende ich so etwas:

// read:
int i = _data[x, y];
byte B = (byte)(i >> 0);
byte G = (byte)(i >> 8);
byte R = (byte)(i >> 16);
// write:
_data[x, y] = BitConverter.ToInt32(new byte[] { B, G, R, 0 }, 0);

Ich benutze Integer -Arrays anstelle eines tatsächlichen System.Drawing.Bitmap Da meine App unter Windows Mobile -Geräten ausgeführt wird, auf denen der Speicher zum Erstellen von Bitmaps stark eingeschränkt ist.

Ich frage mich jedoch, ob es sinnvoller wäre, eine solche Struktur zu deklarieren:

public struct RGB
{
    public byte R;
    public byte G;
    public byte B;
}

... und dann eine Reihe von einer Reihe von RGB anstelle einer Reihe von int. Auf diese Weise konnte ich leicht die separaten R-, G- und B-Werte lesen und schreiben, ohne Bit-Verschiebung und Bitconverter-Ing durchführen zu müssen. Ich erinnere mich vage an etwas aus Tagen von früher byte Variablen, die auf 32-Bit-Systemen blockiert werden, so dass a byte Nimmt tatsächlich 4 Bytes Erinnerung anstelle von nur 1 auf (aber vielleicht war dies nur eine visuelle Basis).

Würde eine Reihe von Strukturen verwenden (wie die RGB Beispiel "oben) schneller sein als ein Array von INTs, und würde es 3/4 oder das dreifache Speicher von INTs verwenden?

War es hilfreich?

Lösung

Wenn Sie auf sind Geschwindigkeit, dann technisch Ich würde das erwarten int[] Version, um schneller zu sein, da es eine bestimmte IL -Anweisung gibt int aus einem Array (siehe OpCodes.Ldelem_I4). Um eine benutzerdefinierte Struktur durchzuführen, muss die Adresse erhalten (OpCodes.Ldelema) und dann die Struktur kopieren (OpCodes.Ldobj) - Verarbeitung der Typmetadaten für beide Schritte.

Kurz gesagt - die int Der Ansatz sollte bessere Optimierungen haben. Aber das ist Mikrooptimierung - in Allgemeines Bevorzugen Sie die Version, die Ihren Code lesbarer macht. Was du könnte Betrachten int zu Ihrer Struktur - dann können Sie das haben int[] Und immer noch:

MyColor col = intArr[12];

(Es wird natürlich einen statischen Anruf in der Mitte machen)

Sie können auch in Betracht ziehen, a zu verwenden Union Sie müssen also nicht viel verschieben:

WICHTIG Ich habe die Endiantheit nicht überprüft. Ändern Sie einfach die Offsets von R/G/B, um sie zu ändern.

class Program
{
    static void Main()
    {
        int[] i = { -1 };
        RGB rgb = i[0];
    }
}
[StructLayout( LayoutKind.Explicit)]
public struct RGB
{
    public RGB(int value) {
        this.R = this.G = this.B = 0; this.Value = value;
    }
    [FieldOffset(0)]
    public int Value;
    [FieldOffset(2)]
    public byte R;
    [FieldOffset(1)]
    public byte G;
    [FieldOffset(0)]
    public byte B;

    public static implicit operator RGB(int value) {
        return new RGB(value);
    }
    public static implicit operator int(RGB value) {
        return value.Value;
    }
}

Andere Tipps

Warum nicht einfach das verwenden Color Struktur in System.Drawing? Es ist einfacher zu handhaben und zu referenzieren. Zugegeben, es hat 4 Bytes (ein anderer Wert repräsentiert Alpha), aber auch Ihre erste Implementierung, und wenn ich mich richtig erinnere, werden 3 Bytes ohnehin an einem 4-Byte-Block ausgerichtet. Schauen Sie sich die Probe an hier.

Ein einsamer Byte allein würde wahrscheinlich blockig ausgerichtet werden, aber mehrere Bytes in einer Struktur können gepackt werden. Und laut Marshal.sizeof belegt Ihre RGB -Struktur tatsächlich nur drei Gedächtnisbytes. (Technisch gesehen ist dies die Größe, wenn sie zu einem nicht verwalteten Gedächtnis unterwegs ist, und die CLR könnte sich dafür entscheiden, es anders auszulegen. In der Praxis denke ich, dass dies richtig sein wird.)

Die CLR könnte jedoch weiterhin die Polsterung zwischen RGBS und anderen Strukturen einfügen, und dieses Verhalten kann von der Prozessor, der CLR -Version usw. abhängen Die Zuweisung einer Reihe von 300 Millionen INTs führte zu 1200 MB. Es sieht also so aus, als ob der 2.0 CLR auf X86 Ihnen 25% sparen. (Ich muss zugeben, dass ich das überrascht habe. Als Tech-Typ mit reisenden Tech erwartete ich, dass die 3-Byte-Strukturen an einer 4-Byte-Grenze ausgerichtet sein werden. Also fehlt mir vielleicht etwas.) Aber der CF kann anders sein: Sie werden wirklich wirklich Kennen Sie es nur, indem Sie es auf Ihrer Zielplattform testen.

Ich denke, ID hängt davon ab, was Sie erreichen möchten. Es ist sicherlich mesbarer, strukturiert zu verwenden, und Sie können es sicher mit verwenden

unsafe { }

Das wird Bitmap Access wirklich beschleunigen. (Wenn Sie wissen, was zu tun ist - keine Überprüfung der Randbedingungen und ähnliches) und auf jeden Fall, wenn Sie die Betreiber für Bitmap -Multiplikation, Maskierung, Graukalierung, Filtern der üblichen Grafik -Dinge, dann in IND in Bezug auf Geschwindigkeit machen möchten, dann ist INT Ihr Freund. Aber Unglücklicherweise nicht im Falle einer Lesbarkeit. Matrixfilter multipliziert nur die INTs (es kann so geschrieben werden) nicht die RGB -Werte unabhängig, sondern mit der Struktur der Markierungen, die sowieso nicht das Problem sein sollte. Ich hoffe es hilft

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top