• Jueves 2 de Mayo de 2024, 02:04

Autor Tema:  compresion - cifrado con huffman - duda  (Leído 4152 veces)

ryan parker

  • Nuevo Miembro
  • *
  • Mensajes: 1
  • Nacionalidad: 00
    • Ver Perfil
compresion - cifrado con huffman - duda
« en: Martes 10 de Julio de 2012, 14:01 »
0
Hola a todos estoy analizando un codigo que consegui sobre este algoritmo de huffman, me intereso el tema de compresion, y despues de seguir  esta lectura pues observe que tambien era posible el cifrado de datos, asi que los puse en marcha y algunas pequeñas modificaciones que realize, aunque sigue siendo el mismo code.

Código: C++
  1. #include <iostream>
  2. #include <cstdio>
  3.  
  4. using namespace std;
  5.  
  6. typedef struct _nodo{
  7.    char letra;
  8.    int frecuencia;
  9.  
  10.    _nodo *sig;
  11.    _nodo *cero;
  12.    _nodo *uno;
  13. } tipoNodo;
  14.  
  15.  
  16. typedef struct _tabla{
  17.    char letra;
  18.    unsigned long int bits;
  19.    char nbits;
  20.    _tabla *sig;
  21. } tipoTabla;
  22.  
  23. tipoTabla *Tabla;
  24.  
  25. void Cuenta(tipoNodo* &Lista, char c);
  26. void Ordenar(tipoNodo* &Lista);
  27. void InsertarOrden(tipoNodo* &Cabeza, tipoNodo *e);
  28. void BorrarArbol(tipoNodo *n);
  29. void CrearTabla(tipoNodo *n, int l, int v);
  30. void InsertarTabla(char c, int l, int v);
  31. tipoTabla *BuscaCaracter(tipoTabla *Tabla, char c);
  32.  
  33. int main(int argc, char *argv[]){
  34.    tipoNodo *Lista;
  35.    tipoNodo *Arbol;
  36.  
  37.    FILE *fe, *fs;
  38.    char c;
  39.    tipoNodo *p;
  40.    tipoTabla *t;
  41.    int nElementos;
  42.    long int Longitud = 0;
  43.  
  44.    unsigned long int dWORD;
  45.    int nBits;
  46.  
  47.    if(argc < 3)
  48.    {
  49.       cout<<"\n\tUsar:\n\t"<<argv[0]<<" <fichero_entrada> <fichero_salida>\n";
  50.       return 1;
  51.    }
  52.  
  53.    Lista = NULL;
  54.  
  55.    fe = fopen(argv[1], "r");
  56.    while((c = fgetc(fe)) != EOF){
  57.       Longitud++;
  58.       Cuenta(Lista, c);
  59.    }
  60.    fclose(fe);
  61.  
  62.    Ordenar(Lista);
  63.  
  64.    Arbol = Lista;
  65.    while(Arbol && Arbol->sig){
  66.       p = new(tipoNodo);
  67.       p->letra = 0;
  68.       p->uno = Arbol;
  69.       Arbol = Arbol->sig;
  70.       p->cero = Arbol;
  71.       Arbol = Arbol->sig;
  72.       p->frecuencia = p->uno->frecuencia + p->cero->frecuencia;
  73.       InsertarOrden(Arbol, p);
  74.    }
  75.  
  76.    Tabla = NULL;
  77.    CrearTabla(Arbol, 0, 0);
  78.  
  79.    fs = fopen(argv[2], "wb");
  80.  
  81.    fwrite(&Longitud, sizeof(long int), 1, fs);
  82.  
  83.    nElementos = 0;
  84.    t = Tabla;
  85.    while(t){
  86.       nElementos++;
  87.       t = t->sig;
  88.    }
  89.  
  90.    fwrite(&nElementos, sizeof(int), 1, fs);
  91.  
  92.    t = Tabla;
  93.    while(t)
  94.    {
  95.       fwrite(&t->letra, sizeof(char), 1, fs);
  96.       fwrite(&t->bits, sizeof(unsigned long int), 1, fs);
  97.       fwrite(&t->nbits, sizeof(char), 1, fs);
  98.       t = t->sig;
  99.    }
  100.  
  101.  
  102.    fe = fopen(argv[1], "r");
  103.    dWORD = 0;
  104.    nBits = 0;
  105.    while((c = fgetc(fe)) != EOF)
  106.    {
  107.  
  108.       t = BuscaCaracter(Tabla, c);
  109.  
  110.       while(nBits + t->nbits > 32){
  111.          c = dWORD >> (nBits-8);
  112.          fwrite(&c, sizeof(char), 1, fs);
  113.          nBits -= 8;
  114.       }
  115.       dWORD <<= t->nbits;
  116.       dWORD |= t->bits;
  117.       nBits += t->nbits;
  118.    }
  119.  
  120.    while(nBits>0){
  121.       if(nBits>=8) c = dWORD >> (nBits-8);
  122.       else c = dWORD << (8-nBits);
  123.       fwrite(&c, sizeof(char), 1, fs);
  124.       nBits -= 8;
  125.    }
  126.  
  127.    fclose(fe);
  128.    fclose(fs);
  129.  
  130.  
  131.    BorrarArbol(Arbol);
  132.  
  133.    while(Tabla){
  134.       t = Tabla;
  135.       Tabla = t->sig;
  136.       delete(t);
  137.    }
  138.  
  139.    return 0;
  140. }
  141.  
  142. void Cuenta(tipoNodo* &Lista, char c){
  143.    tipoNodo *p, *a, *q;
  144.  
  145.    if(!Lista){
  146.       Lista = new(tipoNodo);
  147.       Lista->letra = c;
  148.       Lista->frecuencia = 1;
  149.       Lista->sig = Lista->cero = Lista->uno = NULL;
  150.    }
  151.    else{
  152.       p = Lista;
  153.       a = NULL;
  154.       while(p && p->letra < c){
  155.          a = p;
  156.          p = p->sig;
  157.       }
  158.  
  159.       if(p && p->letra == c) p->frecuencia++;
  160.       else{
  161.          q = new(tipoNodo);
  162.          q->letra = c;
  163.          q->frecuencia = 1;
  164.          q->cero = q->uno = NULL;
  165.          q->sig = p;
  166.          if(a) a->sig = q;
  167.          else Lista = q;
  168.       }
  169.    }
  170. }
  171.  
  172. void Ordenar(tipoNodo* &Lista){
  173.    tipoNodo *Lista2, *a;
  174.  
  175.    if(!Lista) return;
  176.    Lista2 = Lista;
  177.    Lista = NULL;
  178.    while(Lista2){
  179.       a = Lista2;
  180.       Lista2 = a->sig;
  181.       InsertarOrden(Lista, a);
  182.    }
  183. }
  184.  
  185. void InsertarOrden(tipoNodo* &Cabeza, tipoNodo *e)
  186. {
  187.    tipoNodo *p, *a;
  188.  
  189.    if(!Cabeza){
  190.       Cabeza = e;
  191.       Cabeza->sig = NULL;
  192.    }
  193.    else{
  194.        p = Cabeza;
  195.        a = NULL;
  196.        while(p && p->frecuencia < e->frecuencia){
  197.           a = p;
  198.           p = p->sig;
  199.        }
  200.  
  201.        e->sig = p;
  202.        if(a) a->sig = e;
  203.        else Cabeza = e;
  204.     }
  205. }
  206.  
  207. void CrearTabla(tipoNodo *n, int l, int v){
  208.    if(n->uno)  CrearTabla(n->uno, l+1, (v<<1)|1);
  209.    if(n->cero) CrearTabla(n->cero, l+1, v<<1);
  210.    if(!n->uno && !n->cero) InsertarTabla(n->letra, l, v);
  211. }
  212.  
  213. void InsertarTabla(char c, int l, int v){
  214.    tipoTabla *t, *p, *a;
  215.  
  216.    t = new(tipoTabla);
  217.    t->letra = c;
  218.    t->bits = v;
  219.    t->nbits = l;
  220.  
  221.    if(!Tabla){
  222.       Tabla = t;
  223.       Tabla->sig = NULL;
  224.    }
  225.    else{
  226.        p = Tabla;
  227.        a = NULL;
  228.        while(p && p->letra < t->letra){
  229.           a = p;
  230.           p = p->sig;
  231.        }
  232.  
  233.        t->sig = p;
  234.        if(a) a->sig = t;
  235.        else Tabla = t;
  236.     }
  237. }
  238.  
  239. tipoTabla *BuscaCaracter(tipoTabla *Tabla, char c){
  240.    tipoTabla *t;
  241.  
  242.    t = Tabla;
  243.    while(t && t->letra != c) t = t->sig;
  244.    return t;
  245. }
  246.  
  247. void BorrarArbol(tipoNodo *n){
  248.    if(n->cero) BorrarArbol(n->cero);
  249.    if(n->uno)  BorrarArbol(n->uno);
  250.    delete(n);
  251. }

Ahora estuve viendo que la logica era comprimir por que coge solo un digito y si se repite a esta le aumenta la cantidad de veces en un apartado de frecuencias, entonces seguido seria pasarle al arbol, para que reduzca el tamanño en Bits.

Pero note que en una frase de 15 bits, esta llegaba a 72 Bits. (nom comprime ...)
Luego observe que el texto guardado ya no es legible, no se si esto se deba a las funciones archivos:
Código: C++
  1.    fs = fopen(argv[2], "wb");
Lo asumi que tal vez este cifrado pero recorde que en archivos la escritura tambien se puede hacer en binario, cosa que aun no me queda, si deberia cifrar comprimir ?

Me da entender que con este algoritmo puedo comprimir el tamaño de la frase en texto plano y dicho sea de paso pueda comprimir/cifrar la informacion.

Ahora luego de encriptarlo vi que si era posible leer  al supuesto archivo cifrado asi que decidi usar una forma de leer el archivo asi que use hexdump
Código: Bash
  1. hexdump -C cifrado

y pude ver en el siquiete resultado:
Código: Bash
  1. 00000000  0f 00 00 00 0c 00 00 00  0a 02 00 00 00 04 31 03  |..............1.|
  2. 00000010  00 00 00 04 61 00 00 00  00 04 62 01 00 00 00 04  |....a.....b.....|
  3. 00000020  64 06 00 00 00 04 65 03  00 00 00 02 6f 07 00 00  |d.....e.....o...|
  4. 00000030  00 04 70 04 00 00 00 04  72 05 00 00 00 04 74 04  |..p.....r.....t.|
  5. 00000040  00 00 00 03 75 0a 00 00  00 04 78 0b 00 00 00 04  |....u.....x.....|
  6. 00000050  9d c7 6d 16 b1 03 20                              |..m... |
  7. 00000057

como se puede ver es posible la lectura de los caracteres usados en la supuesta encriptacion.
la frase usada fue: pruebadetexto1

la duda es:
. en realidad esto esta cifrado?
. por que puedo el texto si la idea de huffman es convertilo a binario?

lo digo por que con usando archivos en C,  los textos usados para guardarlos en texto plano se guardan en binario y son ilegibles al leerlo.

Saludos.

ProfesorX

  • Moderador
  • ******
  • Mensajes: 796
  • Nacionalidad: mx
    • Ver Perfil
Re:compresion - cifrado con huffman - duda
« Respuesta #1 en: Martes 10 de Julio de 2012, 19:06 »
0
Me parece que estas un poco confundido respecto a como funcionan estos algoritmos.

Para empezar, tenemos dos tipos de algoritmo de compresion, con perdida y sin perdida.

En la compresion con perdida se reduce el tamaño de los datos de tal manera que si descomprimimos los datos se obtiene una secuencia de datos que es muy parecida a la secuencia original, pero no es exactamente igual a la secuencia original. Un ejemplo de este tipo de compresion son los archivos de imagenes jpg, los de musica mp3 y los de video mpg. Es por esta razon que por ejemplo cuando comprimes y descomprimes por ejemplo un archivo de musica, no suena como el original, ya que siempre habra perdida de informacion.

En la compresion sin perdida se reduce el tamaño de los datos de tal manera que si descomprimimos los datos obtenemos EXACTAMENTE la secuencia de datos original. Un ejemplo de este tipo de compresion son los archivos ZIP y RAR.

Acalarado esto vamos a los puntos.

Citar
Pero note que en una frase de 15 bits, esta llegaba a 72 Bits. (nom comprime ...)

Respecto a esto, parece que crees que cuando comprimes informacion, siempre deberia disminuir su tamaño. Pero esto no funciona asi. Este tipo de algoritmo es un algoritmo sin perdida, o sea que debes ser capaz de obtener la secuencia original de datos.

Supongamos que de 15 bits se reduce a 1 bit. Ahora un bit solo representa 0 y 1, entonces piensalo, solo tengo 2 valores a elegir, es imposible que de esos 2 valores pueda "reconstuir" la secuencia original de 15 bits. Recuerda que en realidad el algoritmo funciona elaborando una tabla de frecuencias con los valores contenidos en la secuencia de datos, y cuantas veces se repite cada dato. Entonces el tamaño "adicional" que aparece cuando comprimes una frase pequeña es donde esta contenida esta tabla de frecuencias.

Esto significa en realidad que el algoritmo es mas eficiente (o sea, comprime mas) entre mas grande sea la secuencia de datos, y tenga mayor cantidad de datos "repetidos", o sea mayor sera su porcentaje de compresion. Esta es la razon por la que por ejemplo un archvo de mapa de bits (BMP) se comprime en un porcentaje mayor que un archivo de imagen JPG cuando las comprimes en un archivo zip. (nota que hablo de porcentajes de compresion y no de tamaño en si).


Citar
como se puede ver es posible la lectura de los caracteres usados en la supuesta encriptacion.
la frase usada fue: pruebadetexto1

la duda es:
. en realidad esto esta cifrado?
. por que puedo el texto si la idea de huffman es convertilo a binario?

Ahora, recuerda que todo caracter tiene una representacion en codigo ASCII, y este codigo en realidad es un numero en binario y viceversa. Esto significa tambien que CUALQUIER numero en binario se puede representar como un caracter ASCII.

Por ejemplo, la letra A mayuscula se representa con el numero 01000001 en binario, 41 en hexadecimal y 65 en decimal, esto tambien significa que si tu guardaras el numero 65 en binario en un archivo, y lo ves con el Hexdump, tu lo verias como si fuera la A mayuscula y no como el numero 65.

Entonces lo que tu ves en el hexdump es la representacion en ASCII de los numeros en binario, y pareciera que puedes ver el texto original, pero no es asi, si te fijas bien tambien aparecen la letra m y x, que no estan en tu texto original, ademas que las letras no aparecen en el orden de tu frase, recuerda tambien que este no es un algoritimo de cifrado, es un algoritmo de compresion, y aunque pareciera que cifrar y comprimir es lo mismo no es asi.

Espero que con esto te haya aclarado un poco las dudas.

Saludos :)

NOTA:
==================================================================
Este foro es para ayudar, aprender, compartir... usenlo para eso,
NO SE RESUELVEN DUDAS POR MENSAJE PRIVADO Y MENOS POR CORREO
==================================================================