Solución sugerida: Recuperación de imagen

Para poder resolver este desafío se necesita entender bien cómo leer un archivo byte a byte. A continuación se presenta un programa en Java que lee un archivo de a un byte por vez:

import java.util.*;
import java.io.*;

public class LeerByte {

    private static String getBitsRepresentation(byte b) {
        return String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
    }

    public static void main(String args[]) throws IOException, FileNotFoundException{
        File archivo = new File(args[0]);
        FileInputStream fis1 = new FileInputStream(archivo);
        Scanner sc = new Scanner(System.in);

        int b;
        while ((b = fis1.read()) != -1) {
            String hexa = Integer.toHexString(b);
            System.out.println("Base decimal: " + 
                String.format("%3s", b) + "|Base hexa: " +
                String.format("%3s", hexa) + "|Bits: " +
                getBitsRepresentation((byte) b));
            System.out.println("Presione enter para leer el siguiente byte.");
            sc.nextLine();
        }
        fis1.close();
    }
}

Utilizando el código anterior y ejecutándolo así:

java LeerByte imagen_rota.png

El mismo permitirá leer byte a byte el archivo dañado. Podemos verificar que los primeros 10 bytes del archivo dañado en base decimal son: 137, 84, 78, 71, 13, 10, 26, 10, 0, 0. A partir de ahora, llamaremos palabra a la secuencia de 2 bytes, o sea, que la primera palabra estaría conformada por los bytes 137 y 84. Si vemos estos bytes (o palabras) en una tabla de bits quedaría:

Sin embargo, si uno analiza los bits de paridad que uno puede generar desde el programa que nos da el enunciado no coinciden: 00110 0001001111010000. Notar que los bits de paridad de las filas coinciden pero los de la columnas no.

Acá hay un detalle a tener en cuenta. El cálculo de los bits de paridad por palabra (o sea, 2 bytes) se está realizando en little endian (el byte menos significativo primero). Si uno analiza el código fuente se puede dar cuenta de esto.

Por ejemplo, los bytes 137 y 84 conforman la primera palabra, que en bits sería: 10001001-01010100 pero el algoritmo que genera los bits de paridad los está interpretando así: 01010100-10001001 (como si fuera 84 y 137). Entonces, si invertimos esto en los primeros 10 bytes, la tabla quedaría:

Ahora los bits de paridad calculados en nuestra tabla sí coinciden con los que calculamos: 00110 0001001111010000. Entonces procedemos a comparar los bits de paridad de la imagen dañada con los originales (10110 0001011111010000), y notamos que hay una diferencia en la primera fila y sexta columna (marcado en rojo en la imagen anterior). Cambiamos ese 1 a un 0, y con esto hemos solucionado el error del primer paquete.

Con esta idea en mente, se puede realizar un programa que resuelva todos los bits cambiados. Un programa en Java que hace esto, se lo puede descargar desde acá.

Comando od

Usando el comando en Linux: `od -An -tu1 imagen_rota.png` podrás ver los bytes en base decimal.

Creador de imagen rota

Se deja un programa en Java que cambia un bit al azar en 10 bytes: Descargar.