|
|
|
En este ejemplo veremos como guardar una imagen en una tabla de Interbase. Trabajaremos con los componentes IBX de acceso a Interbase, y permitiremos que se almacenen imágenes con distintos formatos: BMP, JPG y GIF[1].
La tabla que usaremos es muy simple:
CREATE
TABLE PERSONAS (
ID_PERSONA INTEGER NOT NULL,
NOMBRE VARCHAR(30) NOT NULL,
FOTO BLOB SUB_TYPE 0 SEGMENT SIZE 80,
FORMATO_FOTO VARCHAR(3),
CONSTRAINT PERSONAS_PK PRIMARY KEY
(ID_PERSONA)
);
Como podemos ver, guardamos en un campo extra el formato de la foto; la extensión, con tres letras y sin punto.
Vamos a Delphi. Creamos un nuevo proyecto y en el form principal colocamos los componentes de acceso a la tabla de Interbase: TIBDatabase, TIBTransaction, TIBDataset. Conectamos con la Base de Datos y hacemos que el IBDataset trabaje con la tabla PERSONAS.
Agregamos ahora un DBNavigator y un Datasource; enlazamos todo como de costumbre. Coloquemos también sobre el formulario un DBEdit para cada campo, salvo el de Foto para el que ponemos un Timage (si, escribí bien: el componente TDBImage no parece llevarse bien con los formatos distintos del BMP, así que usaremos una imagen común que modificaremos en tiempo de ejecución).
El form queda más o menos como en la imagen siguiente

Ah! Me olvidaba del OpenPictureDialog que necesitaremos para buscar el archivo gráfico, mediante el botón que se ve en la imagen.
El código del botón carga la imagen en el campo BLOB:
procedure TForm1.Button1Click(Sender: TObject);
var
m, f: TStream; s: string;begin
if OpenPictureDialog1.Execute thenbegin
IBDataSet1.Edit; //tendria que dar error sin estom:= IBDataSet1.CreateBlobStream(IBDataSet1FOTO, bmWrite);
f:= TFileStream.Create(OpenPictureDialog1.filename, fmOpenRead); m.CopyFrom(f, f.Size); s:= AnsiUpperCase(ExtractFileExt(OpenPictureDialog1.FileName)); //Siempre en mayusculas if s='.JPEG' then s:= '.JPG'; //un caso especialIBDataSet1FORMATO_FOTO.AsString:= Copy(s,2,3); //elimino el punto
IBDataSet1.Post;
f.Free;m.Free;
end
Se muestra el cuadro de diálogo de selección de imagen, y si se presiona cancelar no pasa más nada; en cambio, si se acepta el archivo gráfico seleccionado se realiza lo siguiente:
· ponemos en edición la tabla, ya que vamos a cambiar el contenido de uno de los campos
· creamos un Stream a partir del campo BLOB que contendrá la imagen
· creamos otro Stream para acceder al archivo gráfico
· copiamos de un Stream a otro. Esta operación efectivamente mueve los bytes que componen la imagen al campo de la tabla
· extraemos y guardamos la extensión (sin el punto) en el campo Formato_Foto
· guardamos los cambios llamando a Post (podría dejarse en estado de edición para que el usuario decida si quiere aceptar los cambios o no)
· y finalmente, destruimos los Streams que habíamos creado
En este punto, el programa ya cumple su cometido de introducir un gráfico en la tabla. Note que no hemos tenido necesidad de especificar el formato gráfico, ya que a la Base de Datos no le interesa lo que pongamos en el campo BLOB: simplemente copiamos un bloque de bytes de un lado a otro.
Pero difícilmente podemos dar por concluido nuestro trabajo aquí, ya que la imagen no se ve. Y ya sabemos que ojos que no ven, corazón que no siente...
Para mostrar la imagen necesitamos un evento que se produzca cada vez que se cambia algo en el registro, y también cuando se mueve el cursor de la tabla a otro registro. El componente Datasource nos proporciona tal evento: OnDataChange. Veamos la implementación elegida.
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
var
m, f: TStream;begin
if IBDataSet1FOTO.IsNull then Image1.Picture:= nil else begin if IBDataSet1FORMATO_FOTO.AsString = 'BMP' then Image1.Picture.Graphic:= TBitmap.Create else if IBDataSet1FORMATO_FOTO.AsString = 'JPG' then Image1.Picture.Graphic:= TJpegImage.Create else if IBDataSet1FORMATO_FOTO.AsString='GIF' then Image1.Picture.Graphic:= TGIFImage.Create else Exit; m:= IBDataSet1.CreateBlobStream(IBDataSet1FOTO, bmRead); Image1.Picture.Graphic.LoadFromStream(m); m.Free; end;end;
Como vemos en el código, ahora si es necesario saber el formato de la imagen con que trabajamos, ya que el componente Image no es capaz de discernir por su cuenta.
El primer paso es necesario para que en un registro que no tenga foto la imagen aparezca vacía (pruebe a eliminar el primer IF y agregue un registro sin foto... después no diga que no le avisé). Una vez que comprobamos que tenemos una foto, el siguiente paso es crear el componente adecuado para mostrarla y asignarlo a la propiedad Picture de la Imagen. Hecho esto, volvemos a las corrientes: copiamos los datos desde la tabla como un Stream de bytes, sin tener en cuenta el formato.
Y esto es todo. Como mejoras, se podría implementar una forma de eliminar una foto de un registro (ahora tendríamos que borrar el registro completo); el campo Formato_Foto no debería estar habilitado si no hay una foto guardada; opción de recortar las fotos o estirarlas a un tamaño fijo, etc. El límite, como siempre, está dado por las ganas y el tiempo... ah, y por la imaginación también, claro.
[1] Necesitará para esto el componente TGIFImage, que se puede obtener gratis de Internet en www.jedi.org