InicioHazlo Tu Mismoshrr - Codifica texto a imagen y viceversa

shrr - Codifica texto a imagen y viceversa

Hazlo Tu Mismo4/16/2014
shrr - Codifica texto a imagen y viceversa

Hola.

Antes de nada, me presentaré ante todos aquellos que no me conozcan.
Soy @anpep na persona n̶o̶r̶m̶a̶l que tiene como hobbie escribir una cosa rara que los nerds llamamos código.

Hoy en día, gran parte de la tecnología que conocemos y usamos diariamente en nuestra vida cotidiana funciona gracias al código, es la base de la tecnología moderna: celulares, PlayStation, televisores, cadenas de música, ordenadores, páginas web e incluso microondas.

En este post, voy a mostrar una especie de algoritmo hecho con código (que en este caso, sirve para páginas web y recibe el nombre de PHP) que tiene como utilidad codificar texto en una imagen, y tras hacerlo ser capaz de decodificar esta imagen y obtener de vuelta el texto.

PHP


Lo primero es lo primero: tengo que buscar una forma de lograr lo que quiero.

Los colores de los ordenadores van representados por un número. Este número tiene dentro tres valores que son combinados para formar un color: rojo, verde y azul, así que lo primero que pensé fue
en convertir cada letra o número a un número que represente un color determinado y luego éste
se decodifique a la letra partiendo de ese número, pero me di cuenta de que en algúna parte
del proceso, el color varía (aunque varíe en uno o dos números por abajo). Esa falta de
precisión es la que me hizo pensar un poco "más allá" y me llevó a tener otra idea, que fue definitiva.

Al igual que los colores, los ordenadores representan las letras con un número. Estos
números que utilizan el orden decimal (base 10), pueden ser convertidos a un número de base 2,
conocido como binario.

La notación binaria consta de una serie de dígitos consecutivos en los que sólo se distinguen dos valores posibles: el 0 y el 1, al igual que en la notación decimal se distinguen 10 (del 0 al 9).

Un número en un ordenador puede tener distintos tamaños. Los tres valores de un color son números enteros sin signo (es decir, que no pueden ser menores que cero) de 8 bits. Es decir, que si los codificamos a binario, obtendríamos exactamente 8 dígitos consecutivos. Pondré un breve ejemplo:

41 (base 10) = 0 0 1 0 1 0 0 1 (base 2)


Como dije antes, la primera idea no pudo ser posible debido a que la profundidad del color variaba cuando se codificaba/decodificaba la imagen, entonces el color era distinto y su correspondiente decodificación no era correcta. Pero si comparas el blanco con el negro, nunca vas a obtener un resultado incorrecto.

Sabiendo que las letras, al igual que los colores, también son representadas por un número, se me ocurrió utilizar su valor binario como manera de codificar el texto.

Pondré otro breve ejemplo.

'A' (letra mayúscula) = 65 (base 10, número que identifica la letra) = 1000001 (base 2/binario)

'B' (letra mayúscula) = 66 (base 10, número que identifica la letra) = 1000010 (base 2/binario)


Entonces, una cadena de texto compuesta de estas dos letras:

'AB' = {65, 66} = 10000011000010


Ese es el valor binario del texto "AB". Como dije antes, si comparamos el blanco y el negro no vamos a obtener un valor incorrecto, así que decidí asignar el color blanco al número 1 y el negro al número 0. De esta forma, la cadena anterior se convertiría en algo como...



Imagina que los cuadrados azules son 0 y los rojos 1. Esto es lo que yo voy a hacer, pero con el blanco y el negro en una cuadrícula.

Para ello, el número de cuadraditos que va a tener la imagen. Sabiendo que cada letra está representada por un número, y que este número tiene 8 dígitos en binario, puedo hallar el número de puntitos con esta sencilla operación:

binario


Donde x es el número de letras del texto que se va a codificar.

Una vez hallado el numero de bits (es decir, el número de cuadraditos), vamos a ver cuál es el ancho y alto ideal para la imagen.

algoritmo


Eso es, nada más ni nada menos que lo siguiente en PHP:

ceil(sqrt(8 * strlen($datos)));

Una vez hallado el ancho y alto ideal, vamos pasando de bit en bit y lo vamos añadiendo a la imagen. Aquí se presenta un nuevo problema: tenemos que convertir una coordenada monodimensional a una coordenada bidimensional teniendo anchura y altura s y sabiendo que la coordenada de una dimensión es i:

codificar
imagen


Entonces, basándonos en estos puntos, vamos añadiendo los pixels a la imagen.

En el caso de shrr, también detecto si el texto es muy largo. En ese caso, lo comprimo con ZLIB para reducir su tamaño y, como consiguiente, el tamaño de la imagen final.
Por motivos que explicaré ahora después en el proceso de decodificación, voy a añadir 4 bytes (que yo llamo "footer" al contenido (tras ser comprimido, en caso de ser necesario, lo que hará que estos últimos 4 ytes no se compriman y puedan ser legibles "a primera vista":

SHR{¿está comprimido?}

El último byte, que de hecho será el último byte de los datos, me permite saber durante el proceso de decodificación si el contenido fue comprimido o no, para saber si tengo que descomprimir los datos antes de devolverlos al cliente. Si los datos se comprimieron, el footer será: "SHR1", de lo contrario será "SHR0".

shrr


Ahora que el algoritmo para codificar ya está listo, vamos ahora con el algoritmo para decodificar. Esto fue para mí lo más engorroso, ahora diré por qué.

Lo primero que haré es obtener el tamaño de la imagen, y una vez obtenido, multiplico el ancho por el alto (que equivale a hallar el cuadrado de cualquiera de los dos, pues la imagen es cuadrada y el ancho es igual que el alto).

shrr - Codifica texto a imagen y viceversa


Una vez que sé cuántos píxeles tienen la imagen (mostrado en la operación de arriba), voy obteniendo todos los píxeles y determino si son negros o no. Si el pixel es negro, añado '0' a una cadena, de lo contrario añado '1'.

Ahora, separo esta cadena en bloques de 8 caracteres (ya que cada número binario tiene 8 dígitos).

Una vez tengo todos los bloques de 8 caracteres, voy pasando por cada uno de ellos y los convierto a decimal (base 10). Acto seguido convierto ese número decimal a una letra y la añado a una cadena.

¡Genial! Ahora tengo los datos de la imagen. Ahora se presenta un nuevo problema (vaya...): la imagen es un cuadrado, y es posible que sobren algunos huecos. El proceso de decodificación trata estos huecos como datos también, así que me salen cosas raras como "ÿÿÿÿÿÿ" (0xFFFFFFFFFFFF) al final del contenido.

Esto me provocó un gran dolor de cabeza, hasta que me acordé de que al final de los datos se encontraba el footer, que era como "SHR{un número}", así que inicio un bucle que vaya leyendo el último caracter de los datos y lo elimina mientras éste no sea un número. Cuando llega al número (0 o 1, dependiendo de si fue comprimido cuando lo codificamos) se detiene.

Ahora obtiene los datos quitándoles los últimos cuatro bytes (el footer), y obtiene también los últimos 4 bytes.

Primero, comprueba que los primeros 3 bytes del footer sean "SHR". Si lo son, mira el último byte y si éste es '1', descomprime el contenido.

¡Y eso es todo! Algo que al principio parecía tan complicado resulta ser lo suficiente sencillo como para que yo lo entienda

Aquí dejo algunos ejemplos de imágenes con sus respectivos textos:

PHP
Hola, no esoy comprimida.

Texto
Hey, mírame! ¡Yo sí que estoy comprimida, utilizando GZ! Eso hace que el tamaño final de la imagen sea diminuto, y por consiguiente, pese menos.

binario
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Aquí dejo el sitio final que utiliza AJAX para codificar/decodificar los datos descargando la imagen desde la URL especificada o subiéndola a imgur:

shrr.ml *


Y, cómo no, aquí dejo el código fuente para los scripts de codificación (encode.php) y decodificación (decode.php):

algoritmo encode.php
codificar decode.php


Saludos, y espero que hayan aprendido algo útil en este post
Cualquier duda consultar en los comentarios o directamente, mándame un MP

* Este sitio es sólo para mostrar el funcionamiento de la codificación/decodificación de datos, con fines educativos. De ninguna manera me hago cargo del contenido codificado en este sitio ni de cómo la gente lo usa para fines que no tengan que ver con educación.

Datos archivados del Taringa! original
162puntos
323visitas
0comentarios
Actividad nueva en Posteamelo
0puntos
3visitas
0comentarios
Dar puntos:

Dejá tu comentario

0/2000

Autor del Post

a
anpep🇦🇷
Usuario
Puntos0
Posts14
Ver perfil →
PosteameloArchivo Histórico de Taringa! (2004-2017). Preservando la inteligencia colectiva de la internet hispanohablante.

CONTACTO

18 de Septiembre 455, Casilla 52

Chillán, Región de Ñuble, Chile

Solo correo postal

© 2026 Posteamelo.com. No afiliado con Taringa! ni sus sucesores.

Contenido preservado con fines históricos y culturales.