Daten komprimieren



  • Hallo Leute ich möchte Messdaren komprimiert überragen .
    Ein Sample der Messdaren besteht aus 1000 zahlen mit einer Bereich von (0-1000) d.h. Ich brauche Mund. 1000 mal 10bit (1024) . Momentan werden Dior 10bit in einer 2byte (Word) kodiert.

    Gibt es ne Möglichkeit so ein (bisher) 2kb Frame anders zu kodieren damit es kleiner wird ? (Das es sich um eine SPS Plattform handelt gibt es da keine Komprimierung libs)


  • Global Moderator |  Mod

    @krishan80 sagte in Daten komprimieren:

    (Das es sich um eine SPS Plattform handelt gibt es da keine Komprimierung libs)

    Das hält einen ja nicht davon ab, so etwas selber zu implementieren. Ist nicht schwer.

    Das bringt natürlich nur etwas, wenn die Daten auch Redundanzen haben (und diese Redundanzen nicht zu komplex sind: Wenn dir Redundanzen höherer Ordnung schon bekannt sind (z.B. Zusammenhänge zwischen einer Zahl und der 4. Zahl danach), dann musst du die selber einen Algorithmus dafür ausdenken). Wenn das praktisch zufällig verteilte Messwerte sind, dann kann der beste Komprimierungsalgorithmus der Welt nichts machen. In dem Fall sind 10 Bit pro Zahl das beste, was geht. Was mich zur Frage bringt: Wenn eine Zahl 10 Bit hat, warum dann als 16 Bit Zahl übertragen? Offensichtlicherweise könnte man doch mit 1000 * 10Bit = 1250 Byte auskommen. Man braucht sich ja schließlich nicht an Bytegrenzen halten. Dann geht die zweite Zahl eben bei Bit 3 der zweiten Zahl los, usw.



  • Angenommen die Änderung zwischen zwei Messwerten sind üblicherweise (viel) kleiner als 500:

    Erstmal die absoluten Werte in Deltas verwandeln. Danach Huffman kodieren. Der Einfachkeit halber vermutlich am Besten mit einem fixen Frequency-Table den du anhand von ein paar Testläufen bestimmst.



  • Hey Danke für die Beiträge,

    das mit den 1000*10Bit = 1250Byte is ne gute Idee:) Ein Komprimierungs- Algorithmus zu implememtieren wäre möglich aber die SPS ist Performance technisch Nich dafür ausgelegt.

    Aber immer Nur das Delta zwischen den Messwerten Frames zu übertragen wäre auch ne Möglichkeit:) Da "meistens" nur ein teile der 1000 Messdaten ändert , und nicht alles auf einmal.. in seltenen Fällen kann es aber auch vor kommen.
    Somit könnte ich die Packetgröße abhäng des Deltas variieren und ich müsste nich immer die 1250kB übertragen.



  • @krishan80
    du kannst ja erstmal einfach anfangen und 3*10 Bit in 32 Bit packen..



  • Danke für den hinweis:) Aber ob ich die Daten nun als byte array im 10bit raster kodiere oder in 32 bit Typen mach vom Aufwand her keinen unterschied.. denk ich



  • @krishan80

    Erstmal musst du schauen, was das für Zahlen sind, bzw. in welchem Verhältnis x(t) zu x(t-1) steht.

    Sind das immer nur schrittweise Änderungen der einzelnen Messwerte?

    Wievele Werte eines Samples ändern sich wirklich und wieviele bleiben unverändert?

    Ändern sich immer nur wenige Messwerte innerhalb eines Samples, macht eine Übertragung der geänderten Messwerte Sinn. Ändern sich die einzelnen Messwerte nur gering oder sogar immer nur um eine festgelegte Schrittweite lässt sich auch die einzelne Änderung mit wenigen Bits erschlagen. Dann macht es sogar Sinn, die eigentliche Differenz ( x(t)-x(t-1) ) zu übertragen.



  • @dirkb sagte in Daten komprimieren:

    @krishan80
    du kannst ja erstmal einfach anfangen und 3*10 Bit in 32 Bit packen..

    Das ist ja öde. Interessant wird es erst, wenn man für 3*10 Bits weniger als 30 Bits braucht.



  • Hi,

    wenn du einfach Daten Komprimieren willst kannst du das PCX Line Pack verwenden:

     ... Code ... 
    
    //lädt komprimierte Daten nach dem PCX-Decodierverfahren map= adresse anz=menge fp=filestream 
    void pcx_readmap(unsigned long map,unsigned long anz,FILE *fp)
    {
      unsigned char c,press;               
      unsigned long  j=0;                 
     
      while(j < anz)           //j noch kleiner als Datenmenge ?                        
      {
        c = fgetc(fp);          //lade ein Datenbyte                     
        press=1;                //Länge der Datenmenge vorerst 1                
                                      
        if((c&192) > 128)      //ist dieses Datenbyte ein Kompress-schlüssel?               
        { 
           press = (c & 63);    //neue Länge der Daten = kompressschlüssel&63             
           c = fgetc(fp);       //lade tatsächliches Datenbyte (nextbyte)             
        }
    
        //schreibe das Datenbyte in den Speicher bis press abgelaufen ist
        while(press--) *((unsigned char *) (j+++map))=c;            
      }
    }
    
    
    //öffnet eine PCX Datei namens fname und ließt die Colordaten nach *colmem
    FILE *pcx_open(unsigned char *fname,unsigned char *colmem)
    {
     FILE *fp=0;                    
     short j=(SCOL*3)*(SBPP>>3); //so viele Farbbytes werden gelesen                   
    
     if((fp=fopen(fname,"rb")))   //open PCX  
     {
       fseek(fp,-(SCOL*3)*(SBPP>>3),2); //zum ende der Datei minus Farbbyteanzahl          
       while(j--) *colmem++ = (unsigned char)(fgetc(fp)); //Farben einlesen
       fseek(fp,128,0);                    //Re.Positionieren 128byes unter Dateibeginn
     } 
     return(fp);
    }
    
    
    short pcx_close(FILE *fp) 
    {
      return((short)fclose(fp));
    }
    
    
    //lädt eine beliebige Anzahl von PCX Bildern in den Speicher adr ,die Bilder müssen
    //die Namen 0.pcx 1.pcx 2.pcx ...usw. heißen, sie müssen im aktiven Verz. zu finden sein
    short pcx_loadanz(short anz,unsigned long mapadr,unsigned long coladr)
    {
     FILE *fp;
     short i;                     
     char ftxt[10];             //Dateinamenshalter
     unsigned long offset=0;   //offset des nächsten Bildes im Speicher
                          
     for(i=0; i<anz; i++)      //lese BitMapDaten der menge Anzahl             
     {
       sprintf(&ftxt[0],"%d",i); //erzeuge Dateinamen aus Nummer                       
       strcat(&ftxt[0],".pcx");  //Dateiendung .PCX anketten                              
    
       if( (fp = pcx_open(&ftxt[0],(char *)coladr)) ) //open PcxFile
       {
         pcx_readmap((unsigned long) mapadr+offset,POS(PCXW,PCXH),fp); //lese Kompressmap
         pcx_close(fp);                                         
       }else return(0);                                     
    
       offset+=POS(PCXW,(PCXH-1));  //nächstes bild an diese adresse  +mapadr                           
     }
    
      return(i);
    }
    
    

    Und wenn Du es richtig machen willst lohnt es sich ultimativ die ADLER PackLib selber zu kompilieren : https://github.com/madler/zlib

    Gruß
    Karsten