grabar y llamar un archivo de imagen en una tabla mySQL
- armando.lagunas
- Posts: 346
- Joined: Mon Oct 05, 2009 3:35 pm
- Location: Curico-Chile
- Contact:
grabar y llamar un archivo de imagen en una tabla mySQL
Hola Amigos:
Quisiera saber si alguien me puede ayudar a realizar esta acción.
lo que quiero conseguir es que un archivo de imagen, (jpg o bmp), que fue sacada con una cámara digital, la pueda grabar en un campo de una tabla Mysql, y posteriormente mostrarla con mi aplicación en una pantalla de ingreso.
espero que me hayan entendido.
saludos desde Chile
Quisiera saber si alguien me puede ayudar a realizar esta acción.
lo que quiero conseguir es que un archivo de imagen, (jpg o bmp), que fue sacada con una cámara digital, la pueda grabar en un campo de una tabla Mysql, y posteriormente mostrarla con mi aplicación en una pantalla de ingreso.
espero que me hayan entendido.
saludos desde Chile
SkyPe: armando.lagunas@hotmail.com
Mail: armando.lagunas@gmail.com
Mail: armando.lagunas@gmail.com
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Armando, yo he conseguido hacerlo así, pero solo para bitmaps tipo BMP de 24 bits (lo he probado con un bitmap pequeño de 256X256, con más grandes supong que fucionará igual):
Necesitas tres campos en tu base d datos: ANCHO, ALTO y DATOS (de la imagen). los dos primeros numéricos y el último un MEMO.
Me explico: Carga la imagen como si fuera un TXT, con MEMOREAD(), calculas nWidth, nHeight y cImage como en el ejemplo y guarda nWidth en el campo ANCHO, nHeight en el campo ALTO y cImage en el MEMO DATOS.
Para reconstruir la imagen he creado la función en C++ (borland 5.5) BUILDIMAGE, este es el código.
A mi me funciona perfectamente.
Para compilar la función en C++ tendrás que utilizar las cabeceras pertinentes (alguien habrá que sepas cuales son). Lo que pasa es que yo lo he hecho incluyendo esa función en una librería en la que tengo varias funciones de C++ y no se que cabeceras se utilizan para FWH con PRAGMA (nunca lo he heco).
Necesitas tres campos en tu base d datos: ANCHO, ALTO y DATOS (de la imagen). los dos primeros numéricos y el último un MEMO.
Code: Select all | Expand
FUNCTION Prueba()
LOCAL oDlg
LOCAL nWidth,nHeight
LOCAL hBmp
LOCAL cImg := CurDrive()+":\"+CurDir()+"\PAISAJE.bmp" // imagen BMP de 24 bits
*
cImg := MEMOREAD( cImg )
nWidth = ASC(SubStr(cimg,19,1))+(ASC(SubStr(cimg,20,1))*256)+(ASC(SubStr(cimg,21,1))*65536)
nHeight = ASC(SubStr(cimg,23,1))+(ASC(SubStr(cimg,24,1))*256)+(ASC(SubStr(cimg,25,1))*65536)
cImg := SubStr(cImg,55) // DATOS DE LA IMAGEN
*
hBmp := BuildImage( nWidth, nHeight, cImg )
*
DEFINE DIALOG oDlg SIZE 350,350
oDlg:bPainted := { |hDc| PaintPrb(hDc,hBmp) }
ACTIVATE DIALOG oDlg CENTER
DeleteObject( hBmp )
RETURN NIL
*
FUNCTION PaintPrb(hDc,hBit)
PalBmpDraw( hDc,10,10,hBit)
RETURN NIL
Me explico: Carga la imagen como si fuera un TXT, con MEMOREAD(), calculas nWidth, nHeight y cImage como en el ejemplo y guarda nWidth en el campo ANCHO, nHeight en el campo ALTO y cImage en el MEMO DATOS.
Para reconstruir la imagen he creado la función en C++ (borland 5.5) BUILDIMAGE, este es el código.
Code: Select all | Expand
HB_FUNC( BUILDIMAGE ) // BuildImage( nWidth, nHeight, cImage )
{
HDC hDc1 = CreateCompatibleDC( NULL ) ;
int nWidth = hb_parni( 1 ) ;
int nHeight = hb_parni( 2 ) ;
LPSTR cImage = hb_parc( 3 ) ;
BITMAPINFO bmi ;
HBITMAP hBitmap ;
VOID *pvBits ;
int i,j,k,v ;
int nQWidth = ((( nWidth * 24 + 31 ) & ~31 ) >> 3 ) ;
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ) ;
bmi.bmiHeader.biWidth = nWidth ;
bmi.bmiHeader.biHeight = nHeight ;
bmi.bmiHeader.biPlanes = 1 ;
bmi.bmiHeader.biBitCount = 24 ;
bmi.bmiHeader.biCompression = BI_RGB ;
bmi.bmiHeader.biSizeImage = nQWidth * nHeight ;
hBitmap = CreateDIBSection( hDc1, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0 ) ;
v = 0 ;
for ( i = 0; i < nHeight; ++i )
{
k = i * nQWidth ;
for ( j = 0; j < (nWidth*3); j += 3 )
{
( (BYTE *) pvBits )[k+j+0] = ( BYTE ) cImage[ v+0 ] ;
( (BYTE *) pvBits )[k+j+1] = ( BYTE ) cImage[ v+1 ] ;
( (BYTE *) pvBits )[k+j+2] = ( BYTE ) cImage[ v+2 ] ;
v += 3 ;
}
}
DeleteDC( hDc1 ) ;
hb_retnl( ( LONG ) hBitmap ) ;
}
A mi me funciona perfectamente.
Para compilar la función en C++ tendrás que utilizar las cabeceras pertinentes (alguien habrá que sepas cuales son). Lo que pasa es que yo lo he hecho incluyendo esa función en una librería en la que tengo varias funciones de C++ y no se que cabeceras se utilizan para FWH con PRAGMA (nunca lo he heco).
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
FWH 2007 - xHarbour - BCC55
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Armando, creo que he cometido un error, esto solo funciona cuando el numero de bits por linea de la imagen es multiplo de 4. Hoy no tengo tiempo de seguir experimentando pero lo miro y te lo posteo.
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
FWH 2007 - xHarbour - BCC55
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Este si funciona:
Code: Select all | Expand
HB_FUNC( BUILDIMAGE ) // BuildImage( nWidth, nHeight, cImage )
{
HDC hDc1 = CreateCompatibleDC( NULL ) ;
int nWidth = hb_parni( 1 ) ;
int nHeight = hb_parni( 2 ) ;
LPSTR cImage = hb_parc( 3 ) ;
BITMAPINFO bmi ;
HBITMAP hBitmap ;
VOID *pvBits ;
int i,j,k,v ;
int nQWidth = ((( nWidth * 24 + 31 ) & ~31 ) >> 3 ) ;
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ) ;
bmi.bmiHeader.biWidth = nWidth ;
bmi.bmiHeader.biHeight = nHeight ;
bmi.bmiHeader.biPlanes = 1 ;
bmi.bmiHeader.biBitCount = 24 ;
bmi.bmiHeader.biCompression = BI_RGB ;
bmi.bmiHeader.biSizeImage = nQWidth * nHeight ;
hBitmap = CreateDIBSection( hDc1, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0 ) ;
v = 0 ;
for ( i = 0; i < nHeight; ++i )
{
k = i * nQWidth ;
for ( j = 0; j < (nWidth*3); j += 3 )
{
( (BYTE *) pvBits )[k+j+0] = ( BYTE ) cImage[ v+0 ] ;
( (BYTE *) pvBits )[k+j+1] = ( BYTE ) cImage[ v+1 ] ;
( (BYTE *) pvBits )[k+j+2] = ( BYTE ) cImage[ v+2 ] ;
v += 3 ;
}
while ( v%4 > 0 )
{
++v ;
}
}
DeleteDC( hDc1 ) ;
hb_retnl( ( LONG ) hBitmap ) ;
}
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
FWH 2007 - xHarbour - BCC55
- jose_murugosa
- Posts: 1185
- Joined: Mon Feb 06, 2006 4:28 pm
- Location: Uruguay
- Contact:
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Este es un tema que me resulta muy interesante, por favor, si logran que funcione plenamente y determinar cuales archivos de cabezal se deben incluir, háganlo saber
, ya que me parece una función muy útil para una aplicación que me encuentro desarrollando
.
Gracias desde ya a los compañeros del foro, verdaderamente es un placer contar con Uds.![Very Happy :D](./images/smilies/icon_biggrin.gif)
![Rolling Eyes :roll:](./images/smilies/icon_rolleyes.gif)
![Wink :wink:](./images/smilies/icon_wink.gif)
Gracias desde ya a los compañeros del foro, verdaderamente es un placer contar con Uds.
![Very Happy :D](./images/smilies/icon_biggrin.gif)
Saludos/Regards,
José Murugosa
"Los errores en programación, siempre están entre la silla y el teclado y la IA!!"
José Murugosa
"Los errores en programación, siempre están entre la silla y el teclado y la IA!!"
- armando.lagunas
- Posts: 346
- Joined: Mon Oct 05, 2009 3:35 pm
- Location: Curico-Chile
- Contact:
Re: grabar y llamar un archivo de imagen en una tabla mySQL
gracias por contestar, voy a realizar las pruebas y les cuento como me fue.
gracias.
gracias.
SkyPe: armando.lagunas@hotmail.com
Mail: armando.lagunas@gmail.com
Mail: armando.lagunas@gmail.com
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Armando
Si usas ADO, lo puedes hacer mediante el objeto ADO Stream. Para ello (como yo lo hago) previamente debes crear un objeto Connection, un objeto Recordset que venga vacío para agregarle el nuevo registro con la foto y un Objeto ADO Stream. El objeto Stream carga el archivo que posteriormente será enviado al objeto recordset. El regreso se hace a la inversa. Se carga la foto al objeto stream desde el recordset para posteriormente grabarlo en una carpeta local, y ya copiado lo podemos usar como queramos. A continucación parte del código, Ojo que el objeto connection ya está creado con oCon:TOleAuto():New("adodb.connection")
Ahora para leerla
Una vez bajado lo podemos usar a nuestro gusto, yo lo he cargado a un objeto Image.
Es una opción más que lo puedes probar.
Un saludo
Marcelo Jingo
Si usas ADO, lo puedes hacer mediante el objeto ADO Stream. Para ello (como yo lo hago) previamente debes crear un objeto Connection, un objeto Recordset que venga vacío para agregarle el nuevo registro con la foto y un Objeto ADO Stream. El objeto Stream carga el archivo que posteriormente será enviado al objeto recordset. El regreso se hace a la inversa. Se carga la foto al objeto stream desde el recordset para posteriormente grabarlo en una carpeta local, y ya copiado lo podemos usar como queramos. A continucación parte del código, Ojo que el objeto connection ya está creado con oCon:TOleAuto():New("adodb.connection")
Code: Select all | Expand
//Recordset para la foto grande
TRY
oRsFoto := TOleAuto():New("adodb.recordset")
CATCH oError
MsgStop( "No se pudo crear el recordset para la Foto !", CAR_VERSION)
RETURN .f.
END
//Configuramos el recordset
oRsFoto:CursorLocation := adUseClient
oRsFoto:LockType := adLockOptimistic
oRsFoto:CursorType := adOpenKeyset//adOpenDynamic
//lo siguiente recupera una tabla vacia
oRsFoto:Source := "SELECT cod,cod_veh,foto_p,foto,tipo,fecha,nota FROM fotos_veh where cod = 0 "
oRsFoto:ActiveConnection(oCon)
TRY
oRsFoto:Open()
CATCH oError
MsgStop( "No se pudo abrir la Tabla de la Foto!", car_version)
ShowError(oError,oCon)
RETURN .f.
END
//----Objeto stream para la foto grande
TRY
::oStream := TOleAuto():New("adodb.Stream")
CATCH oError
MsgStop( "No se pudo crear el Stream para leer la Foto !", CAR_VERSION)
END
// Especifica el tipo de datos ( binario )
::oStream:Type := adTypeBinary
TRY
::oStream:Open()
CATCH oError
MsgStop( "No se pudo establecer la conexion stream!", car_version)
ShowError(oError,oCon)
return .f.
END
::oStream:LoadFromFile(cfile)// cfile puede ser obtenida con cgetfile()
oRsfoto:Addnew()
oRsfoto:fields('cod_veh'):Value := ::oRsV:Fields('cod_veh'):Value
try
oRsFoto:Fields('foto'):Value = ::oStream:Read()
catch oError
MsgStop("Problemas al subir la fotografía")
ShowError(oError,oCon)
end
oRsFoto:Fields('fecha'):Value = fecha
oRsFoto:Fields('nota'):Value = nota
oRsFoto:Update()
::oStream:Close()
Ahora para leerla
Code: Select all | Expand
//Recordset para la foto grande
TRY
oRsFoto := TOleAuto():New("adodb.recordset")
CATCH oError
MsgStop( "No se pudo crear el recordset para la Foto !", CAR_VERSION)
RETURN .f.
END
//Configuramos el recordset que me dovolvera una foto
oRsFoto:CursorLocation := adUseClient
oRsFoto:LockType := adLockOptimistic
oRsFoto:CursorType := adOpenKeyset//adOpenDynamic
oRsFoto:Source := "SELECT cod,foto,tipo FROM fotos_veh where cod ="+ nCod
oRsFoto:ActiveConnection(oCon)
TRY
oRsFoto:Open()
CATCH oError
MsgStop( "No se pudo abrir la Tabla de la Foto!", car_version)
ShowError(oError,oCon)
RETURN .f.
END
TRY
::oStream := TOleAuto():New("adodb.Stream")
CATCH oError
MsgStop( "No se pudo crear el Stream para leer la Foto !", CAR_VERSION)
END
// Especifica el tipo de datos ( binario )
::oStream:Type := adTypeBinary
TRY
::oStream:Open()
CATCH oError
MsgStop( "No se pudo establecer la conexion stream!", car_version)
ShowError(oError,oCon)
return .f.
END
if !lisDir("imgtmp")
lMkDir("imgtmp")
endif
if !lisDir("imgtmp\" + cFold )
lMkDir("imgtmp\" + cFold )
endif
if !oRsFoto:EOF .and. !oRsFoto:BOF
//Graba los datos en el objeto stream
IF oRsFoto:Fields('foto'):Value !=nil
::oStream:Write(oRsFoto:Fields('foto'):Value)
cfoto:="imgtmp\" + cFold+"fg"+alltrim(str(oRsFoto:Fields('cod'):Value)) + "." + alltrim(oRsFoto:Fields('tipo'):Value)
if file(cfoto)
ferase(cfoto)
endif
//Se graba un archivo temporal en disco
::oStream:SaveToFile(cfoto, adSaveCreateOverWrite)
if fsize(cfoto)>0
oImg:LoadBmp(cfoto)
else
oImg:LoadImage( "shade" )
endif
oimg:Refresh()
endif
endif
::oStream:Close()
oRsfoto:Close()
Una vez bajado lo podemos usar a nuestro gusto, yo lo he cargado a un objeto Image.
Es una opción más que lo puedes probar.
Un saludo
Marcelo Jingo
Marcelo Jingo
- armando.lagunas
- Posts: 346
- Joined: Mon Oct 05, 2009 3:35 pm
- Location: Curico-Chile
- Contact:
Re: grabar y llamar un archivo de imagen en una tabla mySQL
estimado sjingo:
lamentablemente, no utilizo ADO, realizo mi conexión por ODBC 5.1 de mysql, pero me has dado una luz con el codigo que publicaste, asi que lo voy a estudiar a fondo para ver la posibilidad de transformarlo y hacerlo funcionar con ODBC.
cuando tenga algo concreto lo voy a publicar para que quede a disposición de la comunidad Fivewinera.
bueno, si alguien más me pueda ayudar, estaré atento a sus sugerencias.
saludos desde Chile.
lamentablemente, no utilizo ADO, realizo mi conexión por ODBC 5.1 de mysql, pero me has dado una luz con el codigo que publicaste, asi que lo voy a estudiar a fondo para ver la posibilidad de transformarlo y hacerlo funcionar con ODBC.
cuando tenga algo concreto lo voy a publicar para que quede a disposición de la comunidad Fivewinera.
bueno, si alguien más me pueda ayudar, estaré atento a sus sugerencias.
saludos desde Chile.
SkyPe: armando.lagunas@hotmail.com
Mail: armando.lagunas@gmail.com
Mail: armando.lagunas@gmail.com
- Daniel Garcia-Gil
- Posts: 2365
- Joined: Wed Nov 02, 2005 11:46 pm
- Location: Isla de Margarita
- Contact:
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Saludos...
la clase TImagen cuenta con esa propiedad y existe la funcion FILoadFromMemory, esta ubicada en fwh\source\image.prg, usa freeimage.dll es tan simple como hacer
MiCampo = MemoRead( "mifoto.jpg" )
hBmp = FILoadFromMemory( MiCampo )
o usar la propia clase TImaga para que realice dicha labor
lamentablemente dentro de los ejemplo de fivewin no hay uno sobre dicha funcionalidad, pero no deberia ser muy complicado y aparenta ser muy facil usarlo
igualmente puden revisar este post del colega Cesar Lozada que patocino la idea inicial: http://forums.fivetechsupport.com/viewtopic.php?p=76883#p76883
la clase TImagen cuenta con esa propiedad y existe la funcion FILoadFromMemory, esta ubicada en fwh\source\image.prg, usa freeimage.dll es tan simple como hacer
MiCampo = MemoRead( "mifoto.jpg" )
hBmp = FILoadFromMemory( MiCampo )
o usar la propia clase TImaga para que realice dicha labor
lamentablemente dentro de los ejemplo de fivewin no hay uno sobre dicha funcionalidad, pero no deberia ser muy complicado y aparenta ser muy facil usarlo
igualmente puden revisar este post del colega Cesar Lozada que patocino la idea inicial: http://forums.fivetechsupport.com/viewtopic.php?p=76883#p76883
our best documentation is the source code
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
- Daniel Garcia-Gil
- Posts: 2365
- Joined: Wed Nov 02, 2005 11:46 pm
- Location: Isla de Margarita
- Contact:
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Saludos...
Ahora si solo usas .BMP creo que la funcion CreateMemBitmap te podria servir tambien, o usando la clase TBitmap el metodo LoadFromString revisa este otro post: http://forums.fivetechsupport.com/viewtopic.php?p=49250#p49250
Ahora si solo usas .BMP creo que la funcion CreateMemBitmap te podria servir tambien, o usando la clase TBitmap el metodo LoadFromString revisa este otro post: http://forums.fivetechsupport.com/viewtopic.php?p=49250#p49250
our best documentation is the source code
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
Isla de Margarita Venezuela.
danielgarciagil@gmail.com
http://tdolphin.blogspot.com/
https://www.dropbox.com/referrals/NTI5N ... rc=global9
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Armando, ayer te contesté de forma apresurada, y creé la función a partir de otras mias, pero ahora he dado con la tecla para guardar cualquier tipo de BMP.
Carga la imagen con MEMOREAD como antes, pero no hay que descomponerla, guárdala tal cual en un campo MEMO, BUILDIMAGE() te devolverá el handle de la imagen cuando lo necesites.
La nueva función sería esta:
Y nada más. Así de simple. Como te decía, sirve para cualquier BMP.
Carga la imagen con MEMOREAD como antes, pero no hay que descomponerla, guárdala tal cual en un campo MEMO, BUILDIMAGE() te devolverá el handle de la imagen cuando lo necesites.
Code: Select all | Expand
LOCAL cImage
cImage := MemoRead( "C:\....\Imagen.Bmp")
BuilImage( cImage )
La nueva función sería esta:
Code: Select all | Expand
HB_FUNC( BUILDIMAGE ) // BuildImage( cImage )
{
HDC hDc1 = CreateCompatibleDC( NULL ) ;
LPSTR cImage = hb_parc( 1 ) ;
HBITMAP hBitmap ;
BITMAPINFO bmi ;
BITMAPFILEHEADER bmh ;
VOID * pvBits ;
BYTE * pvDats ;
BITMAPINFO * lpbi ;
pvDats = &cImage[0] ;
bmh = * ( BITMAPFILEHEADER * ) pvDats ;
pvDats += 14 ;
lpbi = ( BITMAPINFO * ) pvDats ;
pvDats += ( bmh.bfOffBits-14 ) ;
bmi = * lpbi ;
hBitmap = CreateDIBSection( hDc1, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0 ) ;
SetDIBits( hDc1, hBitmap, 0L, bmi.bmiHeader.biHeight, pvDats, ( LPBITMAPINFO ) lpbi, ( DWORD ) DIB_RGB_COLORS ) ;
DeleteDC( hDc1 ) ;
hb_retnl( ( LONG ) hBitmap ) ;
}
Y nada más. Así de simple. Como te decía, sirve para cualquier BMP.
Peaaaaaso de foro...
FWH 2007 - xHarbour - BCC55
FWH 2007 - xHarbour - BCC55
- armando.lagunas
- Posts: 346
- Joined: Mon Oct 05, 2009 3:35 pm
- Location: Curico-Chile
- Contact:
Re: grabar y llamar un archivo de imagen en una tabla mySQL
gracias por contestar, estoy probando con sus aportaciones, apenas me resulte las voy a publicar.
hay una acotación, el tipo de campo que debo ocupar es tipo BLOB en una tabla MYSQL, y lo ideal es tener por separado, una tabla con los datos de la persona y en otra, la imagen con un campo indice apuntando a la principal.
saludos desde Chile.
![Very Happy :D](./images/smilies/icon_biggrin.gif)
hay una acotación, el tipo de campo que debo ocupar es tipo BLOB en una tabla MYSQL, y lo ideal es tener por separado, una tabla con los datos de la persona y en otra, la imagen con un campo indice apuntando a la principal.
saludos desde Chile.
![Very Happy :D](./images/smilies/icon_biggrin.gif)
SkyPe: armando.lagunas@hotmail.com
Mail: armando.lagunas@gmail.com
Mail: armando.lagunas@gmail.com