Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Trucos (https://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   Determinar el tipo de imagen a nivel de dato (https://www.clubdelphi.com/foros/showthread.php?t=80857)

Chris 12-02-2008 19:50:14

Determinar el tipo de imagen a nivel de dato
 
Seguramente, todos los que hemos trabajado con campos Blob para guardar imágenes nos hemos querido "modernizar" y en vez de guardar BMPs intentamos guardar JPEGs o PNGs, las razones están fuera del alcance de este trick, así que no las quiero mencionar.

Pero que pasa si quieres recuperar esas imágenes para guardarlas en un archivo? Tendrás problemas, a menos que las guardes en *.BMP (archivos enormes). Desde este punto tomo en cuenta que conocen como cargar en un objeto TBitmap el contenido de un campo Blob.

Fijándome en el código fuente de la unidad Graphics de Delphi, leí que la forma de determinar el tipo de imagen que hace el objecto TImage es cabernicola, lo hace por medio de la extensión del nombre de archivo. Esta unidad no implementa algún recurso para determinar el formato de la imagen a nivel binario. Por esta razón es que me dispuse a escribir el siguiente código, que quiero compartirlo con ustedes.
Código Delphi [-]
Function GetGraphicClass(Source:TStream):TGraphicClass;
var
FStreamHeader : TStringStream;
StartPosition : Int64;
CONST
PNGFILE_HEADER = '‰PNG';
BMPFILE_HEADER = 'BM';
JPGFILE_HEADER = 'ÿØÿà';
Begin
try
  StartPosition := Source.Position;
  IF Source.Size > 0 Then
      Source.Position := 0
  else // Stream vacío
    Raise Exception.Create('El stream no tiene datos');
    
  FStreamHeader := TStringStream.Create('');

    with FStreamHeader do
    begin
    CopyFrom(Source,512);   // Copiamos el header del Stream
    if pos(PNGFILE_HEADER,DataString) > 0 Then
      Result := TPNGObject
    else if pos(BMPFILE_HEADER,DataString) > 0 Then
      Result := TBitmap
    else if pos(JPGFILE_HEADER,DataString) > 0 Then
      Result := TJPEGImage
    else
      Result := TGraphic; // no quiero producir una excepción a este nivel
    end;
finally
  Source.Position := StartPosition;
end;
end;
A como se ve, esta función está también lejos de ser perfecta, pero a su vez es mucho más segura que la forma en que lo hace Delphi.

En mi caso, en el sistema que me encuentro desarrollando, solo espero manejar imágenes BMP, JPG y PNG, es por esa razón que el código solamente soporta este tipo de imágenes, pero muy facimente se puede escalar.

¿Cómo utilizarlo?
Código Delphi [-]
procedure GuardarImagen;
var
imgStream : TStream;
imgObject : TGraphic;
begin
// cargamos el contenido del campo en el stream
imgStream := TStream.Create;
imgStream := MiTabla.CreateBlobField(miTabla.FieldByName('campoblob'),bmRead);

//determinamos el tipo de imagen
imgObject := GetGraphicClass(imgStream).Create;
imgObject.LoadFromStream(imgStream);
imgObject.SavetoFile(...);
// ... Liberamos el imgObject y imgStream en las siguientes lineas ....
De esta forma tendrás una forma segura de cargar imágenes en un objecto TGraphic y salvarlas en un archivo.

Saludos.

adearmas 12-02-2008 21:26:00

Me gusto mucho el truco... Me resulto muy interesante... sobretodo porque no sabia que se podian devolver tipos de datos e instanciar una clase como lo hiciste.
Siempre se aprende algo nuevo... Gracias!


Chris 12-02-2008 22:09:14

No hay de que adearmas, es un placer compartir. :-)

Delfino 27-03-2008 20:35:55

Puedes mejorar la funcion mirando este enlace http://www.clubdelphi.com/foros/showthread.php?t=12174


La franja horaria es GMT +2. Ahora son las 03:51:09.

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