martedì 14 gennaio 2014

Compressione SMS in Android (2)

Riprendendo dalla puntata precedente, in questo caso la compressione non e' orientata ai caratteri ma si basa sull'ottimizzare il numero di bit per comprimere il dato. Come gia' detto l'obbiettivo e' trasferire informazioni geografiche quindi coordinate lat/long che possono essere descritte come numeri in virgola mobile (non e' previsto avere segni di separazione perche' sara' solo la posizione a determinare la distinzione tra un dato ed il successivo)

Una coordinata in gradi decimali (se non ho sbagliato) necessita' di almeno 5 decimali per avere una precisione al secondo di arco in grado sessagesimali.
La logica e' piu' o meno questa:
1) si prende il numero in virgola mobile e lo si converte nella sua rappresentazione binaria (come stringa)
2) si divide la stringa in pezzi da 7 bit (per il formato SMS)
3) si prendono solo i primi 5 gruppi di 7 bit (il resto dell'informazione e' ridondante)
4) i 7 bit vengono convertiti in un intero (0-127) e quindi nel corrispondente caratttere della tabella SMS
5) il percorso inverso per la riconversione in float

il vantaggio non e' drammatico. Si descrive un numero che puo' essere scritto con 8 caratteri in 5 gruppi da 7 bit (quindi il messaggio occupa circa 0.62 dell'originale, ovvero 1.6 dipende da punto si vede)
Questi sono i passaggi

-------------------------------------------------------------------
Messaggio originale :43.26432
100000001000101101000011101010100111100110111011101011011100000
Messaggio compresso : ¡"h:S
100000001000101101000011101010100110000000000000000000000000000
Messaggio decompresso : 43.26431846618652
-------------------------------------------------------------------
ed ecco il codice

--------------------------------------------------------------

package sms_compr;

import java.math.BigInteger;

/**
 *
 * @author l.innocenti
 */
public class Sms_compr {
    private static int valore;
    private static String reverse = "";
    private static String passaggio = "";
    
    

     static private int converti_sms(char carattere)
    {
       int codice=0;
       switch (carattere)
            {
             case '@': codice=0;break;
             case '£': codice=1;break;
             case '$': codice=2;break;
             case '¥': codice=3;break;
             case 'è': codice=4;break;
             case 'é': codice=5;break;
             case 'ù': codice=6;break;
             case 'ì': codice=7;break;
             case 'ò': codice=8;break;
             case 'Ç': codice=9;break;
             case '\n': codice=10;break;
             case 'Ø': codice=11;break;
             case 'ø': codice=12;break;
             case '\r': codice=13;break;
             case 'Å': codice=14;break;
             case 'å': codice=15;break;
             case 'Δ': codice=16;break;
             case '_': codice=17;break;
             case 'Φ': codice=18;break;
             case 'Γ': codice=19;break;
             case 'Λ': codice=20;break;
             case 'Ω': codice=21;break;
             case 'Π': codice=22;break;
             case 'Ψ': codice=23;break;
             case 'Σ': codice=24;break;
             case 'Θ': codice=25;break;
             case 'Ξ': codice=26;break;
             //case '': codice=27;break;
             case 'Æ': codice=28;break;
             case 'æ': codice=29;break;
             case 'ß': codice=30;break;
             case 'É': codice=31;break;
             case ' ': codice=32;break;
             case '!': codice=33;break;
             case '"': codice=34;break;
             case '#': codice=35;break;
             case '¤': codice=36;break;
             case '%': codice=37;break;
             case '&': codice=38;break;
             case '\'': codice=39;break;
             case '(': codice=40;break;
             case ')': codice=41;break;
             case '*': codice=42;break;
             case '+': codice=43;break;
             case ',': codice=44;break;
             case '-': codice=45;break;
             case '.': codice=46;break;
             case '/': codice=47;break;
             case '0': codice=48;break;
             case '1': codice=49;break;
             case '2': codice=50;break;
             case '3': codice=51;break;
             case '4': codice=52;break;
             case '5': codice=53;break;
             case '6': codice=54;break;
             case '7': codice=55;break;
             case '8': codice=56;break;
             case '9': codice=57;break;
             case ':': codice=58;break;
             case ';': codice=59;break;
             case '<': codice=60;break;
             case '=': codice=61;break;
             case '>': codice=62;break;
             case '?': codice=63;break;
             case '¡': codice=64;break;
             case 'A': codice=65;break;
             case 'B': codice=66;break;
             case 'C': codice=67;break;
             case 'D': codice=68;break;
             case 'E': codice=69;break;
             case 'F': codice=70;break;
             case 'G': codice=71;break;
             case 'H': codice=72;break;
             case 'I': codice=73;break;
             case 'J': codice=74;break;
             case 'K': codice=75;break;
             case 'L': codice=76;break;
             case 'M': codice=77;break;
             case 'N': codice=78;break;
             case 'O': codice=79;break;
             case 'P': codice=80;break;
             case 'Q': codice=81;break;
             case 'R': codice=82;break;
             case 'S': codice=83;break;
             case 'T': codice=84;break;
             case 'U': codice=85;break;
             case 'V': codice=86;break;
             case 'W': codice=87;break;
             case 'X': codice=88;break;
             case 'Y': codice=89;break;
             case 'Z': codice=90;break;
             case 'Ä': codice=91;break;
             case 'Ö': codice=92;break;
             case 'Ñ': codice=93;break;
             case 'Ü': codice=94;break;
             case '§': codice=95;break;
             case '¿': codice=96;break;
             case 'a': codice=97;break;
             case 'b': codice=98;break;
             case 'c': codice=99;break;
             case 'd': codice=100;break;
             case 'e': codice=101;break;
             case 'f': codice=102;break;
             case 'g': codice=103;break;
             case 'h': codice=104;break;
             case 'i': codice=105;break;
             case 'j': codice=106;break;
             case 'k': codice=107;break;
             case 'l': codice=108;break;
             case 'm': codice=109;break;
             case 'n': codice=110;break;
             case 'o': codice=111;break;
             case 'p': codice=112;break;
             case 'q': codice=113;break;
             case 'r': codice=114;break;
             case 's': codice=115;break;
             case 't': codice=116;break;
             case 'u': codice=117;break;
             case 'v': codice=118;break;
             case 'w': codice=119;break;
             case 'x': codice=120;break;
             case 'y': codice=121;break;
             case 'z': codice=122;break;
             case 'ä': codice=123;break;
             case 'ö': codice=124;break;
             case 'ñ': codice=125;break;
             case 'ü': codice=126;break;
             case 'à': codice=127;break;
       }
       return codice;
    }

    public static void main(String[] args) {
         char[] sms = new char[128];
        

        sms[0] = '@';
        sms[1] = '£';
        sms[2] = '$';
        sms[3] = '¥';
        sms[4] = 'è';
        sms[5] = 'é';
        sms[6] = 'ù';
        sms[7] = 'ì';
        sms[8] = 'ò';
        sms[9] = 'Ç';
        sms[10] = '\n';
        sms[11] = 'Ø';
        sms[12] = 'ø';
        sms[13] = '\r';
        sms[14] = 'Å';
        sms[15] = 'å';
        sms[16] = 'Δ';
        sms[17] = '_';
        sms[18] = 'Φ';
        sms[19] = 'Γ';
        sms[20] = 'Λ';
        sms[21] = 'Ω';
        sms[22] = 'Π';
        sms[23] = 'Ψ';
        sms[24] = 'Σ';
        sms[25] = 'Θ';
        sms[26] = 'Ξ';
        //sms[27] = '';
        sms[28] = 'Æ';
        sms[29] = 'æ';
        sms[30] = 'ß';
        sms[31] = 'É';
        sms[32] = ' ';
        sms[33] = '!';
        sms[34] = '"';
        sms[35] = '#';
        sms[36] = '¤';
        sms[37] = '%';
        sms[38] = '&';
        sms[39] = '\'';
        sms[40] = '(';
        sms[41] = ')';
        sms[42] = '*';
        sms[43] = '+';
        sms[44] = ',';
        sms[45] = '-';
        sms[46] = '.';
        sms[47] = '/';
        sms[48] = '0';
        sms[49] = '1';
        sms[50] = '2';
        sms[51] = '3';
        sms[52] = '4';
        sms[53] = '5';
        sms[54] = '6';
        sms[55] = '7';
        sms[56] = '8';
        sms[57] = '9';
        sms[58] = ':';
        sms[59] = ';';
        sms[60] = '<';
        sms[61] = '=';
        sms[62] = '>';
        sms[63] = '?';
        sms[64] = '¡';
        sms[65] = 'A';
        sms[66] = 'B';
        sms[67] = 'C';
        sms[68] = 'D';
        sms[69] = 'E';
        sms[70] = 'F';
        sms[71] = 'G';
        sms[72] = 'H';
        sms[73] = 'I';
        sms[74] = 'J';
        sms[75] = 'K';
        sms[76] = 'L';
        sms[77] = 'M';
        sms[78] = 'N';
        sms[79] = 'O';
        sms[80] = 'P';
        sms[81] = 'Q';
        sms[82] = 'R';
        sms[83] = 'S';
        sms[84] = 'T';
        sms[85] = 'U';
        sms[86] = 'V';
        sms[87] = 'W';
        sms[88] = 'X';
        sms[89] = 'Y';
        sms[90] = 'Z';
        sms[91] = 'Ä';
        sms[92] = 'Ö';
        sms[93] = 'Ñ';
        sms[94] = 'Ü';
        sms[95] = '§';
        sms[96] = '¿';
        sms[97] = 'a';
        sms[98] = 'b';
        sms[99] = 'c';
        sms[100] = 'd';
        sms[101] = 'e';
        sms[102] = 'f';
        sms[103] = 'g';
        sms[104] = 'h';
        sms[105] = 'i';
        sms[106] = 'j';
        sms[107] = 'k';
        sms[108] = 'l';
        sms[109] = 'm';
        sms[110] = 'n';
        sms[111] = 'o';
        sms[112] = 'p';
        sms[113] = 'q';
        sms[114] = 'r';
        sms[115] = 's';
        sms[116] = 't';
        sms[117] = 'u';
        sms[118] = 'v';
        sms[119] = 'w';
        sms[120] = 'x';
        sms[121] = 'y';
        sms[122] = 'z';
        sms[123] = 'ä';
        sms[124] = 'ö';
        sms[125] = 'ñ';
        sms[126] = 'ü';
        sms[127] = 'à';
        double lat = 43.26432; //64 bit
        String stringa;
        String compressa = "";
        
        System.out.println("Messaggio originale :"+ lat);

        //convert il double in una stringa con la conversione binaria del dato
        stringa = Long.toBinaryString(Double.doubleToRawLongBits(lat));
        System.out.println(stringa);
        
        //divide il dato in pezzi da 7 bit
        //per mandare il dato via SMS con la tabella caratteri SMS
        String b1 = stringa.substring(0, 7);
        String b2 = stringa.substring(7, 14);
        String b3 = stringa.substring(14, 21);
        String b4 = stringa.substring(21, 28);
        String b5 = stringa.substring(28, 35);
        //String b6 = stringa.substring(35, 42);
        //String b7 = stringa.substring(42, 49);
        //String b8 = stringa.substring(49, 56);
      
        //convert il valore binario a base 7 in intero
        int d1 = Integer.parseInt(b1, 2);
        int d2 = Integer.parseInt(b2, 2);
        int d3 = Integer.parseInt(b3, 2);
        int d4 = Integer.parseInt(b4, 2);
        int d5 = Integer.parseInt(b5, 2);
        //int d6 = Integer.parseInt(b6, 2);
        //int d7 = Integer.parseInt(b7, 2);
        //int d8 = Integer.parseInt(b8, 2);
        
        //usando la tabella di compressione prende i primi 5 gruppi di 7 bit
        //e li codifica come SMS
        //compressa = compressa + sms[d1]+sms[d2]+sms[d3]+sms[d4]+sms[d5]+sms[d6]+sms[d7]+sms[d8];
        compressa = compressa + sms[d1]+sms[d2]+sms[d3]+sms[d4]+sms[d5];
        System.out.println("Messaggio compresso : "+compressa);
        
        for (int t=0; t<compressa.length();t++)
            {
            valore = converti_sms(compressa.charAt(t));
            String v = Integer.toBinaryString(valore);
           reverse = new StringBuffer(v).toString();
           //System.out.println(reverse);


        

            while ((reverse.length() %7) != 0)
                {
                reverse = "0"+reverse ;
                }
            passaggio = passaggio + reverse;
            //System.out.println("a "+reverse);

            }
        

        
        passaggio = passaggio + "0000000000000000000000000000";
        System.out.println(passaggio);

        
        double doubleVal = Double.longBitsToDouble(new BigInteger(passaggio, 2).longValue());
        System.out.println("Messaggio decompresso : "+doubleVal);
        
        
        
    }
    
}