Frage

Ich lese Teile aus einer monochromen Bitmap. Ich speichere alle 16 Bit in a short in umgekehrter Reihenfolge. Wenn das Bit in der Bitmap schwarz ist, lagern Sie eine 1. Wenn Sie weiß, lagern Sie eine 0.

EG: Für Bitmap: BBBW BBBW BBBW wwww
Mein Kurzfilm ist: 0000 0111 0111 0111

Der erste Weg, den ich versucht habe, war:

short m;
// ...
Color c = bmp.GetPixel(j, i);
if (c.R == Color.Black)
    m |= short.MinValue;
m >>= 1;
// ...

Nach einem Auftrag und einer Schicht bekam ich die erwarteten -32768 (1000 0000 0000 0000).
Nach dem zweiten Mal bekam ich -16384 (1100 0000 0000 0000).

Ich habe meinen Code geändert, um sie zu verwenden ushort und veränderte die if Linie zu s |= (ushort)Math.Pow(2, 15); Und jetzt funktioniert es.

Meine Frage ist: Warum verschiebt sich das Zeichen nicht in .NET? Gibt es eine Möglichkeit, das Zeichenbit zu verschieben?

War es hilfreich?

Lösung

In C#sind Verschiebungen Arithmetik Verschiebungen (im Gegensatz zu logischen Verschiebungen). In einer rechten arithmetischen Verschiebung wird das Vorzeichenbit links eingeschaltet, sodass das Zeichen der Anzahl erhalten bleibt. Eine rechte Verschiebung entspricht der Dividierung durch 2:

alt text

Wenn Sie eine wollen logisch Verschiebung (keine Vorzeichenverlängerung), Verwenden Sie unsignierte Zahlen:

alt text

Andere Tipps

http://msdn.microsoft.com/en-us/library/k2ay192e.aspx

"Der >> Operator verschiebt die Bits von Expression1 nach rechts nach der Anzahl der in Expression2 angegebenen Bit Der von diesem Bediener zurückgegebene Datentyp. "

Rechte Verschiebung unterzeichnet Ganzzahlen in C# füllen die linken Teile mit dem Zeichenbit. Effektiv ist das Ergebnis des rechten Verschiebung einer signierten Ganzzahl durch ein einzelnes Bit gleichbedeutend mit der Teilen durch 2.

Sie können sich auch an anderen Orten verändern. Zum Beispiel enthält die X86 -Baugruppe zwei unterschiedliche Anweisungen. sar (was die linken Bits mit Schildbit füllt) und shr (die linke Bits mit Null füllt).

Wenn Sie dieses Verhalten in C#nicht möchten, müssen Sie beim Verlagerung nicht signierte Typen verwenden.

pro http://www.blackwasp.co.uk/csharpshiftoperators.aspx

... Signierte Ganzzahlen verwenden das Bit mit höchstem Ordnung, um festzustellen, ob der Wert einer Variablen positiv oder negativ ist und dass die verbleibenden Bits die Komplementnotation von zwei Neglements für negative Werte verwenden. Das höchste Ordnung wird normalerweise als Überlaufbit für eine Verschiebung links angesehen Betrieb. Um dies zuzulassen, versteht C#, dass dieses Bit nicht für signierte Datentypen angepasst werden sollte und dass negative Zahlen entsprechend verschoben werden sollten. So funktioniert das Verschieben sowohl für negative als auch für positive Werte.

int value = -240;
int halved = value >> 1;      // Result = -120

Die kurze Antwort auf Ihre Frage ist, wie Sie herausgefunden haben, dass Sie die unsignierte Ganzzahl verwenden, um das Schildbit zu vermeiden, und das ist alles in Ordnung. Betrachten Sie jedoch Folgendes

Optimierungshinweise

Angenommen, Sie müssen viele solche Konvertierungen durchführen (normalerweise gibt es in einer Bitmap viele Pixel), sollten Sie in Betracht ziehen, ein Array von 256 Bytes zu verwenden, die direkt die umgekehrte Version des Bitmusters liefern (oder was auch immer die Konvertierung kann für ein komplettes Byte sein. Wenn Sie dieses Array direkt mit dem HI- oder niedrigen Bytewert des 16 -Bit -Wortes direkt indizieren, erhalten Sie die Ergebnisse für alle 8 Bit. In einigen Fällen, in denen Zeit/Leistung eine Prämie ist (und Platz verfügbar ist ...), können Sie sogar eine 64 -km -Arraygröße verwenden und jeweils ein volles Wort verarbeiten.

Angesichts der in Ihrem Beispiel angegebenen Konvertierung haben Sie das vorbereitete Wertearray so etwas wie:

    byte[] mirror = { 
       0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
       0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
       0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x78, 0xF8,
       // etc..
       0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
    };
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top