Ver Mensaje Individual
  #1  
Antiguo 12-02-2008
Avatar de Chris
[Chris] Chris is offline
Miembro Premium
 
Registrado: abr 2007
Ubicación: Jinotepe, Nicaragua
Posts: 1.678
Reputación: 19
Chris Va por buen camino
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.
Responder Con Cita