Datos personales

domingo, 29 de abril de 2012

Ocultar y Revelar Mensaje en imagenes



Ocultar/Revelar Mensaje



Introducción

Los objetivos de este guión de prácticas son los siguientes:
 
1. Practicar con el uso de “arrays”.
2. Usar tipos de datos “enum” (enumerados).
3. Practicar con operaciones a nivel de bit.

 
Los requisitos para poder realizar esta práctica son:

 
1. Saber manejar los arrays así como el caso particular de cadenas-C .
2. Conocer el diseño de programas en módulos independientes, así como la compilación separada, incluyendo la creación de bibliotecas.
3. Conocer el diseño de ficheros makefile.


Operadores a nivel de bit

El lenguaje C++ ofrece un conjunto de operadores lógicos a nivel de bit para operar con tipos integrales y enumerados, en particular, con tipos carácter y entero. Los operadores son:
  • Operadores binarios. La operación se realiza para cada par de bits que ocupan igual posición en ambos operandos 
    1. O (exp1|exp2). Obtiene 1 cuando alguno de los dos operandos vale 1.
    2.  Y (exp1&exp2). Obtiene 1 sólo si los dos operandos valen 1. 
    3.  Desplazamiento a la derecha (exp1>>exp2). Los bits del primer operando se desplazan a la derecha tantos lugares como indique el segundo operando. Por tanto, algunos bits se perderán por la derecha mientras se insertan nuevos bits cero por la izquierda.
    4. O exclusivo (exp1^exp2) bit a bit. Es decir, obtiene 1 cuando uno, y sólo uno de los operandos, vale 1.
    5. Desplazamiento a la izquierda (exp1<<exp2). Los bits del primer operando se desplazan a la izquierda tantos lugares como indique el segundo operando. Por tanto, algunos bits se perderán por la izquierda mientras se insertan nuevos bits cero por la derecha. 
    6. Operador unario. La operación se realiza sobre todos y cada uno de los bits que contiene el operando. 
    7. No (~exp1). Obtiene un nuevo valor con los bits cambiados, es decir, ceros por unos y unos por ceros.
En la siguiente figura se muestran algunos ejemplos con los operadores que hemos indicado.

 Con estos operadores, se pueden crear expresiones para consultar el valor de los bits que componen un dato, o para modificarlos.

 Imágenes

Desde un punto de vista práctico, una imagen se puede considerar como un conjunto de celdas que se organizan en posiciones que podemos hacer corresponder con una matriz bidimensional tal como muestra la siguiente figura.
matriz



 Imágenes en blanco y negro

Para representar las imágenes en blanco y negro podemos usar un rango de valores para indicar todas las tonalidades de gris que van desde el negro hasta el blanco. En nuestro caso,las imágenes almacenarán en cada píxel un valor de gris desde el 0 al 255. Por ejemplo, un píxel con valor 128 tendrá un gris intermedio entre blanco y negro.
En la siguiente figura se muestra un ejemplo de imagen 256x256 de niveles de gris. Observe el zoom de una región 10x10 para apreciar con detalle los grises que la componen.
Imagen Blanco/Negro


Imágenes en color

Para representar un color de forma numérica, no es fácil usar un único valor, sino que se deben incluir tres números. Existen múltiples propuestas sobre el rango de valores y el significado de cada una de esas componentes, generalmente adaptadas a diferentes objetivos y necesidades.

En una imagen en color, el contenido de cada píxel será una tripleta de valores según un determinado modelo de color. En esta práctica consideraremos el modelo RGB. Este modelo es muy conocido, ya que se usa en dispositivos como los monitores, donde cada color se representa como la suma de tres componentes: rojo, verde y azul
 
En la siguiente figura se muestra un ejemplo en el que se crea un color con los valores máximos de rojo y verde, con aportación nula del azul. El resultado es el color ( 255,255,0), que corresponde al amarillo.











 1. Si la imagen es PGM -de grises- será un vector que contenga todos los bytes consecutivos de la imagen. Así, la posición 0 del vector tendrá el píxel de la esquina superior izquierda, la posición 1 el de su derecha, etc.
2. Si la imagen es PPM -de color- será un vector similar. En este caso, la posición 0 tendrá la componente R de la esquina superior izquierda, la posición 1 tendrá la poción G, la posición 2 la B, la posición 3 la componente R del siguiente píxel, etc. Es decir,
añadiendo las tripletas RGB de cada píxel.

 Ocultar/Revelar un mensaje

La práctica va a consistir, en la inserción y extracción de un mensaje “oculto” en una imagen.
Para ello, modificaremos el valor de cada píxel para que contenga parte de la información a ocultar




 

Codificar


Este módulo contendrá dos funciones:

• Función “Ocultar”, que recibe como entrada dos parámetros, uno con la imagen (un vector de bytes) y otro con el mensaje a insertar (una cadena-C). Esta función insertará el mensaje en la imagen.


• Función “Revelar”. Recibe como parámetros la imagen (un vector) y una cadena (un vector de caracteres), que se modificará para contener el mensaje que se va a extraer  desde el vector.

Programas

El objetivo final de la práctica es crear dos programas, uno para ocultar un mensaje en una imagen y otro para revelarlo.

Ejemplos de ejecución :

  • Ocultar





visualmente las imagenes son iguales pero en la imagen salida.pgm esta oculto el mensaje.

  • Revelar



 codigo:

 
/**
  * @file codificar.cpp
  * @brief Fichero con funciones para ocultar/extraer un mensaje en imagenes
  *
  * Permite la ocultacion y extracción de un mensaje en imagenes de tipo PGM,PPM
  *
  */

#include <iostream>
#include <string>
#include <cstring>
#include "codificar.h"

using namespace std;
void imprimir( char m[])
{
    for (int i=0;m[i]!='\0';i++)
        cout <<m[i];
    cout<<endl;
}

bool cabe_mensaje(int tam,char mensaje[])
{
    int s=strlen(mensaje);
    return((s*8<tam)?1:0);
}

bool activo(int numero ,int nbit)
{
    return (numero&(1<<nbit)?1:0);
}
//_______________________________________________________________________________________
//
//                 Ocultar
//_____________________________________________________________________________________


bool ocultar( unsigned char buffer[],char mensaje[],int tam)
{
    int i=0;
    bool exito= false;

    int tamcadena=strlen(mensaje);
    if(tamcadena<=tam)
    {
        for(int j=0;j<=tamcadena;j++)
        {
            for(int k=7;k>=0;k--)//recorre los bits del caracter
            {
                if(activo(mensaje[j],k))
                    buffer[i]= buffer[i]|1;
                else
                    buffer[i]=buffer[i]&(~1);
                i++;
            }
            if(j==tamcadena)
            {
                 exito= true;
            }
        }
    }else exito=false;
        return exito;
}
bool comparaTipo(char nombre[],char tipo[])
{
    bool ok=false;
    int c=strlen(nombre);
    int cont=0;
    int d=strlen(tipo);

        for(int i=c-1,j=d-1;i>=c-4;i--,j--)
            if(nombre[i]==tipo[j])
                cont++;
        if (cont==d)
            ok=true;
        return ok;
}
void lee_linea(char c[], int tamanio)
{
    do{
        cin.getline(c,tamanio);
    }while (c[0]=='\0');
}
//___________________________________________________________________________________________
//
//                Revelar
//___________________________________________________________________________________________

bool  revelar (unsigned char buffer[],char mensaje[],int tam)
{
    int cont=0,j=0;
    char c=' ';
    bool exito=false;
    cout<<"Revelando...."<<endl;
    for(int i=0;c!='\0';i++)
    {
        c=0;
        cont=0;
            for(int nbits=7;nbits>=0;nbits--)
            {
                if(activo(buffer[j],0))
                {
                    c=c<<1;
                    c=c|1;
                }else
                    c=c<<1;

                if(cont==7)    mensaje[i]=c;

                if ((cont==7) && (c=='\0'))
                {                    
                    mensaje[i]='\0';
                    exito=true;
                }
                if(j==tam && c!='\0') exito= false;

                cont++;
                   j++;
            }
    }
    return exito;
}

No hay comentarios:

Publicar un comentario