El proyecto de esta tarde ha sido crear un programa para recuperar imágenes jpeg borradas. El proceso es sencillo, se va examinado byte a byte el fichero que contiene una imagen del disco, buscando una secuencia característica ($FFD8FF), esta secuencia se encuentra al comienzo de todos los archivos Jpeg.
Si encontramos esa secuencia es muy posible que lo que venga a continuación sea una imagen jpeg. Además vamos a suponer que el archivo se ha guardado en cluster contiguos, algo también muy probable, aunque si el disco estaba muy fragmentado esta suposición puede ser equivocada y en ese caso no podremos recuperar el archivo (con este método).
Bueno, vamos a ponernos en lo mejor, y suponemos que lo que viene a continuación de la secuencia es la imagen. Entonces el programa va copiando cada uno de los segmentos que forman la imagen jpg hasta encontrar la marca que indica el final del fichero. Si hay suerte recuperaremos la imagen
Hasta aquí supongo que el proceso se entiende bien, examinamos un fichero en busca de imágenes y las extraemos. La cuestión ahora es como obtener ese fichero. Ese fichero puede ser "cualquier cosa" en la que sepamos que hay una imagen, la imagen de un disco o incluso una archivo jpeg con un thumbnail dentro (en ese caso el programa extraerá la imagen en miniatura).
Asi que, si lo que queremos es examinar un disco (una memoria usb por ejemplo) primero tenemos que crear una imagen, eso lo podemos hacer con muchos programas (incluso creo que hay algún código para eso en el foro), yo recomiendo por ejemplo
este programa
Una vez que tenemos la imagen solo tenemos que hacer algo como esto:
Código:
JpegRecover imagen.bin C:\%d.jpg
El comando anterior buscara imágenes en el archivo imagen.bin y las guardara en C:\ con los nombres 0.jpg, 1.jpg, 2.jpg, ...
Y si lo que queremos es extraer la imagen en miniatura de un archivo jpg:
Código:
JpegRecover imagen.jpg C:\%d.jpg
Bueno, creo que ya solté bastante rollo. Aquí va el código (es una aplicación de consola):
Código Delphi
[-]
program JpegRecover;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
procedure Recover(Origen: TStream; FormatStr: String; var Index: Integer);
var
Destino: TMemoryStream;
Buffer: array[0..$FFFF] of Byte;
Header: array[1..4] of Byte;
Size: Integer;
begin
Destino:= TMemoryStream.Create;
try
Header[1]:= $FF; Header[2]:= $D8;
Destino.WriteBuffer(Header,2);
Origen.Seek(-1,soFromCurrent);
while TRUE do
begin
Origen.ReadBuffer(Header,4);
Size:= ((Header[3] shl 8) + Header[4]) - 2;
case Header[2] of
$01,$D0..$D8: begin
Destino.WriteBuffer(Header,2);
Origen.Seek(-2,soFromCurrent);
end;
$D9: begin
Destino.WriteBuffer(Header,2);
Destino.SaveToFile(Format(FormatStr,[Index]));
Writeln('Recuperada: ' + Format(FormatStr,[Index]));
inc(Index);
Exit;
end;
$DA: begin
Destino.WriteBuffer(Header,2);
Origen.Seek(-2,soFromCurrent);
while TRUE do
begin
Origen.ReadBuffer(Buffer,1);
if Buffer[0] = $FF then
begin
Origen.ReadBuffer(Buffer,1);
if (Buffer[0] <> 0) and not (Buffer[0] in [$D0..$D7]) then
begin
Origen.Seek(-2,soFromCurrent);
break;
end else
begin
Header[1]:= $FF;
Header[2]:= Buffer[0];
Destino.WriteBuffer(Header,2);
end;
end else
Destino.WriteBuffer(Buffer,1);
end;
end
else
begin
Origen.ReadBuffer(Buffer,Size);
Destino.WriteBuffer(Header,4);
Destino.WriteBuffer(Buffer,Size);
end;
end;
end;
finally
Destino.Free;
end;
end;
procedure Scanfile(Stream: TStream; FormatStr: String; Index: Integer);
var
B: Byte;
Leidos: Integer;
Posicion: int64;
begin
Leidos:= Stream.Read(B,1);
while Leidos = 1 do
if B = $FF then
begin
Leidos:= Stream.Read(B,1);
if Leidos = 1 then
if B = $D8 then
begin
Leidos:= Stream.Read(B,1);
if Leidos = 1 then
if B = $FF then
begin
Writeln('Encontrada una posible imagen.');
Posicion:= Stream.Position;
try
Recover(Stream,FormatStr,Index);
except
On E: Exception do
Writeln('Error: ' + E.Message);
end;
Stream.Position:= Posicion;
end;
end;
end else
Leidos:= Stream.Read(B,1);
end;
var
Stream: TFileStream;
begin
if ParamCount >= 2 then
try
Format(ParamStr(2),[0]);
Stream:= TFileStream.Create(Paramstr(1),fmOpenRead);
try
Writeln('Explorando el archivo: ' + ParamStr(1));
if ParamCount = 3 then
Scanfile(Stream,ParamStr(2),StrToInt(ParamStr(3)))
else
Scanfile(Stream,ParamStr(2),0);
finally
Stream.Free;
end;
except
On E: Exception do
Writeln('Error: ' + E.Message);
end;
end.
PD: El siguiente proyecto sera crear un programa que cree de forma automática y oculta una imagen de todos los discos usb que se inserten en el ordenador, mas tarde le pasamos el recover a las imágenes y ....
es broma, eso además de ilegal, estaría muy feo.