Entwickler-Ecke

Basistechnologien - Bytemanipulation


schickmaster - Mo 02.08.10 10:44
Titel: Bytemanipulation
Hallo,
bin neu hier und weiss nicht, ob ich richtig bin in diesem thread mit meinem thema, aber ich versuchs mal;)

Also muss ein byte array so manipulieren, dass ich ein scheinbares "1bit +8bit" datenformat bekomme. also rutscht nach jedem
byte die ganze geschichte um 1 mehr nach hinten, was in einem weitern array aufgefangen wird. das amcht die
ganze sache mit dem shiftcommand etwas undurchsichtig.

Beispiel, wie es sein sollte:
die 8 bit nutzdaten:

1111011bin = 123dez
10000bin = 32dez
11110101bin = 245dez

mit einer 1 vorab für jedes Byte verschiebt sich das ganze system so:

10111101bin = 189dez
11000100bin = 196dez
111110bin = 62dez
10100000bin =160dez(3 ersten bit sind die lezten 3 bit von 245dez, quasi neues array wegen den zusätlichen einsen)

real hab ich ca 200byte nutzdaten im array, was sich mit ner führenden
1 auf 200byte plus 25 byte führende 1 vergrößert.

ich stehe da grade etwas aufm schlauch. vll hat einer einen tipp, wie
ich da ran gehen kann? Dafür wäre ich sehr dankbar.

grussa alex


Trashkid2000 - Mo 02.08.10 17:23

Hi,

also, so richtig verstehe ich das Problem nicht!
Aber ich versuche mal, das so zu deuten:

Du hast, sagen wir mal, ein bit[] mit 8 Bits (für den Anfang).
Diese wären denn z.B. 00110011

So, wenn Du jetzt ein DEFINIERTES Bit vorne ranhängst, kommst Du auf
000110011 oder
100110011. Wozu soll dazu irgend etwas geshiftet werden?

Du müsstest doch bloß Dein ursprüngliches bit[] in ein anderes kopieren, und halt immer Deine zusätzlichen Bits (ob nun 1 oder 0 ist ja egal) mit reinschmeißen. Oder meinst Du was anderes?


schickmaster - Di 03.08.10 13:30

hey Trashkid2000,

erstmal danke für die Antwort.
so in etwa hast du es richtig interpretiert. Aus den 8bits werden quasi 9bit, was aber nicht mehr in
ein Byte, was aber meine Hardware erwartet.

Vll ist das ein wenig besser verständlich:
Byte [01111011] [00010000] [11110101]


wird mit führender 1 alle 8 bit zu:

[1 0111101] [1 1 000100] [00 1 11110] [101 1 0000]

und das quasi für ca. 200byte. (fürenden 1 jweils alleine stehend)
ich bin be mycsharp.de etwas verärgert auf die shift funktion hingewiesen worden, kann mir aber damit
mein problem nicht lösen, weil die werte ausserhalb des bytes wegfallen, soweit ich das verstehe.
Dummerweise ist die Funktion, mit der der befehl gesendet wird ziemlich lahm beim aufruf, deswegen wäre es gut,

den befehl z.b. sendspi (array1[] ..... array150[]) mit oben beschriebener art und weise aufzurufen.

zur zeit denke ich da an eine schleife, alle 8 byte arrays ein neuntes einfügt und es jeweils mit den entsprechenden
1en auffüllt, bin aber zur zeit noch wegen mehrefacher hinweise auf den shift fixiert.

gruss alex


Trashkid2000 - Di 03.08.10 20:36

Hi,

ok, habe das Problem also richtig verstanden.
Hier erstmal der Link auf den Thread im myCSharp-Forum:
http://www.mycsharp.de/wbb2/thread.php?threadid=87261

Also, was ich mit dem bit[] geschrieben habe ist Quatsch. Gibt es nicht. Sorry.

Habe mir heute Abend mal ernsthaft Gedanken gemacht. Irgendein Algo muss es doch geben! Aber bin ehrlich gesagt zu keinem klaren Ergebnis gekommen. Aber nach der Arbeit ist das auch nicht einfach! Ist schon ziemlich kompliziert. Und ich glaube, dass Dir das mit dem shiften nicht weiterhilft.

Werde mal eine Nacht drüber schlafen und morgen mal schauen, was sich machen lässt.

MfG, Marko


Kha - Di 03.08.10 21:28

Erst einmal :welcome:

Wenn es nicht um Top-Performance geht, würde ich mir um Bitshifting keine Gedanken machen. Mit der BitArray-Klasse kannst du die einzelnen Bits in ein bool[] konvertieren (siehe CopyTo-Beispiel), dort fügst du fügst du an den Positionen 0, 9, ... ein true ein und schickst das ganze wieder durch BitArray, um das Byte-Array zu erhalten.


jaenicke - Di 03.08.10 22:25

user profile iconTrashkid2000 hat folgendes geschrieben Zum zitierten Posting springen:
Irgendein Algo muss es doch geben!
Naja, im Grunde eben einfach verschieben. Zu einem ähnlichen Problem habe ich hier einen optimierten Code in Assembler gepostet:
http://forum.delphi-treff.de/showthread.php?29093-7-Bytes-auf-8-Bytes-aufteilen#5

Bei 200 Byte sollte aber ein solcher Aufwand nicht nötig sein (übertragen auf C# dann ohne Assembler), es sei denn dies muss sehr oft ausgeführt werden. Insofern spare ich mir da jetzt erst einmal große Überlegungen dazu, denn ich denke einmal user profile iconKhas Lösung reicht bereits.


schickmaster - Mi 04.08.10 10:52

bisher sieht die ganze sache so aus:


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:
  private static bool _firstPicture5Z = true;

        private static void SendSinglePicture5Z(Bitmap bmp)
        {
    for (byte pageNr = 0; pageNr < 10; pageNr++)
            {
                proForm.UpdateProgress(pageNr);                          
              
                //bytearray aus bitmap erstellen
                byte[] pageArray = new byte[240];
                for (int colNr = 0; colNr < 240; colNr++)
                {
                    byte singleByte = 0;
                    for (int i = 0; i < 32; i++)
                    {
                        Color value = pic.GetPixel(colNr, (pageNr * 32) + i);
                        if (value.ToArgb() == Color.White.ToArgb())
                        {
                            singleByte += (byte)Math.Pow(2, i);
                        }
                    }
                    pageArray[colNr] = singleByte;
                   
                }
                      Funktionx(pageArray)
                      
            }
    }


bisher wurde pageArray so übergeben. leider finde ich nicht viel über byte arrays in netz oder in büchern. vll schaue ich auch falsch.
in meinem kopf sieht das ganze so aus:

1. konvertiere pageArray zu binären String
2. schiebe zwischen stelle 0 und 1 eine 1.

3.

C#-Quelltext
1:
2:
3:
for(n=0; n=240/8; n++){
schiebe zwischen stelle 0+8*n und 1+8*n eine 1. 
};

4. konvertiere String zu pageArray

Ich glaube das Problem ist, das ich in das array schieben muss, und keine werte an der jeweilige stelle ersetze.

Könnte das eventuell so funktionieren?

Gruss alex


Kha - Mi 04.08.10 18:07

Das ist eine umständliche Version meines Vorschlags, also ja ;) .


schickmaster - Do 05.08.10 11:43

hey kha,

stimmt, im prinzip isses das auch;)

hab jetzt sowas hier:

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:
   static void Main()
        {
            byte[] byteArray = new byte[] { 23123255123 }; //testarray

            foreach(byte i in byteArray)
            {
                Console.WriteLine(i);
            }
            ByteToString(byteArray);
            Console.WriteLine(ByteToString(byteArray)); 
//Ausgabe:
// 23
// 123
// 255
// 123
// 00010111011110111111111101111011
                                                                   
      } 


 private static string ByteToString(byte[] ByteArray)
        {
            System.Text.StringBuilder sb = new StringBuilder();
            foreach (byte b in ByteArray)
                sb.Append(Convert.ToString(b, 2).PadLeft(8'0'));
                 
                return sb.ToString();           
        }


Das passt auch soweit. jetzt friemel ich grade an nem regex rum, mit dem ich den string bearbeiten kann.
würdet ihr das mit nem regex machen. vll regex(ersetzte \d{8}=byte1 mit \d(1) + "byte1")?
oder gibts da vll andere sinnvollere möglichkeiten? bzw den regex direkt
ins PadLeft() zu schreiben, aber da heult der rum.

gruss alex


schickmaster - Do 05.08.10 15:16

hrhrhr, ein kleiner erfolg:


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:
static class Program
    {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            byte[] byteArray = new byte[] { 255415423 };

            foreach(byte i in byteArray)
            {
                Console.WriteLine("array: " + i);
            }
            string binstring = ByteToString(byteArray);
            Console.WriteLine("binstring D/XC: " + binstring);
                         
               
        }

        //Wandelt byte array in binären String
        private static string ByteToString(byte[] ByteArray)
        {
            System.Text.StringBuilder sb = new StringBuilder();
            int i = 0;
            foreach (byte b in ByteArray)
            {
                //erweitert array nach links mit 0en, bis auf 9 zeichen und setzt jeweils ersten zeichen auf string s.
                sb.Append(Convert.ToString(b, 2).PadLeft(9'0'));         
                string s = "5";    
                sb[9*i] = s[0]; 
                i++;    
            }
                return sb.ToString();
        }
  
    }
//Ausgabe: 511111111500000100500000001500000101500000100500010111


Also, der string ist soweit verwurstet, das er stimmt(5 ist dem fall die oben erwähnte 1 wegen der übersicht)
jetzt muss ich das teil nur noch in 8er string blöck zerlegen und zurück in ein byte array wandeln.
wenn jemand ne idee hat, nur her damit.
gruss alex


Trashkid2000 - Do 05.08.10 21:47

Na, das sieht doch schon gut aus!

Also, habe mir jetzt auch mal wieder Gedanken gemacht. Was auch nicht so einfach ist, wenn man schon auf Arbeit seine Problemchen hat. Aber na ja.

Also, die Idee bei der Lösung ist, dass ich bei dem Streamreader von Position 0 anfange zu lesen. Davor lege ich mir ein byte[] an, das alle Bits aufnehmen kann. Lesen tue ich dann immer in 8-er Blöcke und kopiere die Zeichen in ein char[].
Dieses muss ich noch umdrehen, da sonst die Wertigkeit der Bits verdreht ist. Danach laufe ich das Array durch und rechne also die entsprchende Wertigkeit aus.

Zum Schluss kommt dann das byte[] output raus. Weiss nicht, ob es vielleicht noch eine bessere Lösung gibt, aber ich finde das garnicht so schlecht.


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:
//nur für Testzwecke-----------
StringBuilder sb = new StringBuilder("0000001101");
//-----------------------------

byte[] output = new byte[sb.Length/8 + ((sb.Length % 8 > 0) ? 1 : 0)];
int currentByte = 0;
int currentIndex = 0;
while (currentIndex < sb.Length)
{
  char[] temp = new char[8];
  int currentReadingBits = 8;
  if (currentIndex + 8 > sb.Length)
    currentReadingBits = sb.Length - currentIndex;
  sb.CopyTo(currentIndex, temp, 0, currentReadingBits);
  byte rating = 1;
  byte value = 0;
  foreach (char item in temp.Reverse())
  {
    if (item.CompareTo('1') == 0)
      value += rating;
    rating *= 2;
  }
  output[currentByte] = value;    
  currentByte++;
  currentIndex += currentReadingBits;   
}


MFG, Marko

//edit hatte was vergessen zu schreiben


schickmaster - Mo 09.08.10 14:44

Jo, habs gelöst. warscheinlich nicht grade auf die sauberste art und weiste, aber es läuft.
,,...abgesehen davon bin ich kein vollblut-inf;-).
muss zugeben, hat mich ne menge nerven gekosten, aber man auch auch ne menge gelernt und man hat sogar
spass dran, wenn es am ende geht!!
Danke für euren support.
gruss alex





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:
static class Program
    {

        static void Main()
        
        {
            byte[] byteArray = new byte[] { 1255125512551255 };

           string binstring = ByteToString(byteArray);
           Console.WriteLine("binstring D/XC: " + binstring);
           bitstring(binstring);
                     
      
        }


        //Wandelt byte array in binären String 1 + 8bit
        private static string ByteToString(byte[] ByteArray)
        {
            System.Text.StringBuilder sb = new StringBuilder();
            int i = 0;
            foreach (byte b in ByteArray)
            {
                sb.Append(Convert.ToString(b, 2).PadLeft(9'0'));
                string s = "1";//wird dann 1  
                sb[9 * i] = s[0];
                i++;
            }
            return sb.ToString();
        }

        //zerlegt 9bit string(1+8bit) in 8 bitblöcke
        private static int bitstring(string str)
        {
           int i = 0;
           int s = 0;
           int count = 0;
           string bitstring = "0";
            //Array größe anpassen:!!
           byte[] newbyteArray = new byte[9];

           for (i = 0; i < str.Length; i = i + 8)
           {
               
               bitstring = "" + str[0 + i] + str[1 + i] + str[2 + i] + str[3 + i] + str[4 + i] + str[5 + i] + str[6 + i] + str[7 + i];
               s = bintodec(bitstring);
               byte b = (byte)s;
               Console.Write(b + "\n");
               newbyteArray [count] = b;
               count++;
           }                                               
           
           Console.WriteLine(newbyteArray.Length);
           foreach (byte val in newbyteArray) { Console.WriteLine("aus array" + val); }
           return s;
        }

        // Umerechung von 8bit bin in dec
        private static int bintodec(string str)
        {
            int a = 0int b = 0int c = 0int d = 0
            int e = 0int f = 0int g = 0int h = 0;
            string bin0 = "0";
           
            if (str[0] == bin0[0]) { a = 0; } else { a = 128; }
            if (str[1] == bin0[0]) { b = 0; } else { b = 64; } 
            if (str[2] == bin0[0]) { c = 0; } else { c = 32; } 
            if (str[3] == bin0[0]) { d = 0; } else { d = 16; }
            if (str[4] == bin0[0]) { e = 0; } else { e = 8; }
            if (str[5] == bin0[0]) { f = 0; } else { f = 4; } 
            if (str[6] == bin0[0]) { g = 0; } else { g = 2; }
            if (str[7] == bin0[0]) { h = 0;}  else { h = 1; }

            int val = (a + b + c + d + e + f + g + h);            
            return val;
       }
      
    }