Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Gráficos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

 
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 06-05-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Recuperar imagenes jpeg

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
    // Escribimos los 2 primeros bytes del archivo
    Header[1]:= $FF;  Header[2]:= $D8;
    Destino.WriteBuffer(Header,2);
    Origen.Seek(-1,soFromCurrent);
    // En este bucle vamos copiando segmento a segmento
    while TRUE do
    begin
      Origen.ReadBuffer(Header,4);
      Size:= ((Header[3] shl 8) + Header[4]) - 2;
      case Header[2] of
        $01,$D0..$D8: begin
                        // Estos segmentos solo miden dos bytes,
                        // asi que escribimos 2 bytes y
                        Destino.WriteBuffer(Header,2);
                        // retrocedemos otros dos hacia atras.
                        Origen.Seek(-2,soFromCurrent);
                      end;
        $D9: begin
               // Este indica que llegamos al final del archivo jpeg
               Destino.WriteBuffer(Header,2);
               // Guardamos el archivo usando la plantilla
               Destino.SaveToFile(Format(FormatStr,[Index]));
               Writeln('Recuperada: ' + Format(FormatStr,[Index]));
               // Incrementamos el indice
               inc(Index);
               // Salimos del procedure
               Exit;
             end;
        $DA: begin
               // Este segmento no tiene tamaño
               Destino.WriteBuffer(Header,2);
               Origen.Seek(-2,soFromCurrent);
               // Buscamos el final byte a byte
               while TRUE do
               begin
                 Origen.ReadBuffer(Buffer,1);
                 // Posible comienzo de otro segmento
                 if Buffer[0] = $FF then
                 begin
                   Origen.ReadBuffer(Buffer,1);
                   // $FF00 = Secuencia de escape
                   // $FFD0 .. $FFD7 = Se deben de ignorar
                   if (Buffer[0] <> 0) and not (Buffer[0] in [$D0..$D7]) then
                   begin
                     // Si encontramos el comienzo de otro segmento,
                     // retrocedemos dos bytes, y volvemos al bucle principal
                     Origen.Seek(-2,soFromCurrent);
                     break;
                   end else
                   begin
                     // Si no es el comienzo de otro segmento, escribimos
                     // y continuamos
                     Header[1]:= $FF;
                     Header[2]:= Buffer[0];
                     Destino.WriteBuffer(Header,2);
                   end;  
                 end else
                   Destino.WriteBuffer(Buffer,1);
               end;
             end
        else
        begin
          // Cualquier otro segmento lo copiamos directamente
          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
  // Vamos leyendo byte a byte el archivo
  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
              // Hasta encontrar la combinacion $FFD8FF
              Writeln('Encontrada una posible imagen.');
              // Guardamos la posicion
              Posicion:= Stream.Position;
              try
                // Intentamos recuperar la imagen
                Recover(Stream,FormatStr,Index);
              except
                // Si se produce un error lo mostramos, pero no salimos del bucle
                On E: Exception do
                   Writeln('Error: ' + E.Message);
              end;
              // Volvemos a la posicion en la que estabamos
              Stream.Position:= Posicion;
            end;
        end;
    end else
      Leidos:= Stream.Read(B,1);
end;

var
  Stream: TFileStream;

begin
  // Al menos necesitamos 2 parametros para trabajar
  if ParamCount >= 2 then
  try
    // El segundo parametro esla plantilla para guardar la imagenes
    // recuperadas, asi que comprobamos que su formato es correcto.
    Format(ParamStr(2),[0]);
    // Abrimos el archivo
    Stream:= TFileStream.Create(Paramstr(1),fmOpenRead);
    try
      Writeln('Explorando el archivo: ' + ParamStr(1));
      // El nombre de las imagenes recuperadas es la combinacion de la plantilla
      // y un indice que se va incrementando. Si no lo pasamos en la liena
      // de comandos el indice es cero.
      if ParamCount = 3 then
        Scanfile(Stream,ParamStr(2),StrToInt(ParamStr(3)))
      else
        Scanfile(Stream,ParamStr(2),0);
    finally
      Stream.Free;
    end;
  except
    // Si se produce un error, lo mostramos
    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.
Responder Con Cita
 



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Incluir imagenes JPEG en paradox 7 rsantosr Gráficos 3 06-12-2005 01:12:25
cabecera de imagenes jpeg samantha jones Gráficos 1 19-08-2004 03:35:29
Problemas alguardar imagenes jpeg y gif en un campo blob Flycket Firebird e Interbase 3 20-02-2004 09:29:02
TMysql imagenes jpeg xobius Conexión con bases de datos 0 11-02-2004 16:21:16
Visualizar Imagenes Jpeg Legolas Gráficos 1 17-11-2003 21:14:23


La franja horaria es GMT +2. Ahora son las 11:20:03.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi