#include "rle.h"

/**
* komprimiert in 16 bit rle 
*/
  
void simpleRLE16(unsigned short *data,long len,struct RLE16_s *RLE16)
{

    unsigned short key,*outputbuffer,*outputbufferhold;
    long          keym[65536];
    long          i,j,k,l,m,n,cnt;
        
    outputbuffer     =  (void*)malloc(len*2);
    outputbufferhold = outputbuffer;
  
    //puts(".compress rle16");
    
    /* make Historgramm */
    
    for(i=0;i<65536;i++)    { keym[i]=0; }
    for(i=0;i<len;i++)      { keym[data[i]]++; }
    
    cnt=len+1;
    for(i=0;i<65536;i++)
    {    
        if(keym[i]<cnt)     { cnt = keym[i];key = i; }
    }
 
    //printf("  .rlekey = %d (%d counts)\n",key,keym[key]);
    
    for(i=0;i<len;i++)
    {   
        // wenn key, dann schreibe key 0 key      
        if(data[i]==key)
        {
                *outputbuffer++=key;
                *outputbuffer++=1-1;       //anzahl
                *outputbuffer++=key;
                continue; // weiter beim nächsten
        }  
        // wenn noch mindestens ein nachfolger 
        if(i<(len-1))
        {
         if(data[i]!=data[i+1]) // und der nächste nicht gleich
         {
                *outputbuffer++=data[i]; // dann speicher diesen und mach weiter
                continue;
         }
        }
        // wir sind beim letzten 
        if(i==(len-1))
        {
               *outputbuffer++=data[i]; // dann speicher und ende
               break; 
        }
        // mindestens 2 gleiche
        // zählen wir
        l=1;
        for(k=(i+1);k<(65536+i);k++)        // zähle anzahl wiederholungen
        {
           if(k==(len-1)) break;        // bis maximal arrayende
           
           if( data[i] != data[k] )       // nächste ungleich
           {
                      break;              // raus
           }          
           l++;                           // ++          
        }      
        // speichere lauflänge   
        if(l<=3)                           // zwei und drei so schreiben
        { 
                for(k=0;k<l;k++) { *outputbuffer++=data[i]; }  
        }
        else                                // bei mehr als drei
        {
                *outputbuffer++=key;        // keycode
                *outputbuffer++=l-1;        // anzahl - 1
                *outputbuffer++=data[i];    // char
        }
                
        i=i+l-1; // weiter nach lauf länge
    }
    
    RLE16->simpleRLE16len  = (outputbuffer - outputbufferhold)*sizeof(unsigned short); 
    RLE16->simpleRLE16key  = key;
    RLE16->simpleRLE16data = outputbufferhold;
    
    //printf("  .bufferlen = %d (%d comp: %d%%)\n",RLE16->simpleRLE16len,len*2,RLE16->simpleRLE16len*100/(len*2));

}
