FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour grabar y llamar un archivo de imagen en una tabla mySQL
Posts: 346
Joined: Mon Oct 05, 2009 03:35 PM
grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Thu Apr 22, 2010 05:26 AM

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

SkyPe: armando.lagunas@hotmail.com

Mail: armando.lagunas@gmail.com
Posts: 498
Joined: Thu May 10, 2007 08:30 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Thu Apr 22, 2010 12:00 PM
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.

Code (fw): Select all Collapse
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 (fw): Select all Collapse
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
Posts: 498
Joined: Thu May 10, 2007 08:30 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Thu Apr 22, 2010 12:15 PM

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
Posts: 498
Joined: Thu May 10, 2007 08:30 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Thu Apr 22, 2010 12:28 PM
Este si funciona:

Code (fw): Select all Collapse
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
Posts: 1279
Joined: Mon Feb 06, 2006 04:28 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 01:46 AM

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 :roll: , ya que me parece una funci贸n muy 煤til para una aplicaci贸n que me encuentro desarrollando :wink: .

Gracias desde ya a los compa帽eros del foro, verdaderamente es un placer contar con Uds. :D

Saludos/Regards,

Jos茅 Murugosa

"Los errores en programaci贸n, siempre est谩n entre la silla, el teclado y la IA!!"
Posts: 346
Joined: Mon Oct 05, 2009 03:35 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 03:19 AM

gracias por contestar, voy a realizar las pruebas y les cuento como me fue.

gracias.

SkyPe: armando.lagunas@hotmail.com

Mail: armando.lagunas@gmail.com
Posts: 229
Joined: Sat Mar 18, 2006 03:42 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 03:40 AM
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")


Code (fw): Select all Collapse
//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 (fw): Select all Collapse
//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
聽 聽 聽 聽 ::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
聽 聽 聽 聽 ::SaveToFile(cfoto, adSaveCreateOverWrite) 聽 
聽 聽 聽 聽 if fsize(cfoto)>0 聽
聽 聽 聽 聽 聽 聽 oImg:LoadBmp(cfoto)
聽 聽 聽 聽 else
聽 聽 聽 聽 聽 聽 oImg:LoadImage( "shade" )
聽 聽 聽 聽 endif
聽 聽 聽 聽 oimg:Refresh()
聽 聽 endif
endif

::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
Posts: 346
Joined: Mon Oct 05, 2009 03:35 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 04:01 AM

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.

SkyPe: armando.lagunas@hotmail.com

Mail: armando.lagunas@gmail.com
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 04:36 AM
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
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 04:49 AM
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
Posts: 498
Joined: Thu May 10, 2007 08:30 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Fri Apr 23, 2010 08:49 AM
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.

Code (fw): Select all Collapse
LOCAL cImage
cImage := MemoRead( "C:\....\Imagen.Bmp")
BuilImage( cImage )

La nueva funci贸n ser铆a esta:

Code (fw): Select all Collapse
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
Posts: 346
Joined: Mon Oct 05, 2009 03:35 PM
Re: grabar y llamar un archivo de imagen en una tabla mySQL
Posted: Sat Apr 24, 2010 04:23 AM

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.

:D

SkyPe: armando.lagunas@hotmail.com

Mail: armando.lagunas@gmail.com

Continue the discussion