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
- O (exp1|exp2). Obtiene 1 cuando alguno de los dos operandos vale 1.
- Y (exp1&exp2). Obtiene 1 sólo si los dos operandos valen 1.
- 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.
- O exclusivo (exp1^exp2) bit a bit. Es decir, obtiene 1 cuando uno, y sólo uno de los operandos, vale 1.
- 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.
- Operador unario. La operación se realiza sobre todos y cada uno de los bits que contiene el operando.
- No (~exp1). Obtiene un nuevo valor con los bits cambiados, es decir, ceros por unos y unos por ceros.
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
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