grabar y llamar un archivo de imagen en una tabla mySQL

grabar y llamar un archivo de imagen en una tabla mySQL

Postby armando.lagunas » Thu Apr 22, 2010 5: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
User avatar
armando.lagunas
 
Posts: 346
Joined: Mon Oct 05, 2009 3:35 pm
Location: Curico-Chile

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby antolin » 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: Select all  Expand view  RUN
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 view  RUN
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
antolin
 
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby antolin » 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
antolin
 
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby antolin » Thu Apr 22, 2010 12:28 pm

Este si funciona:

Code: Select all  Expand view  RUN
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
antolin
 
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby jose_murugosa » Fri Apr 23, 2010 1: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 y el teclado y la IA!!"
User avatar
jose_murugosa
 
Posts: 1180
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby armando.lagunas » Fri Apr 23, 2010 3: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
User avatar
armando.lagunas
 
Posts: 346
Joined: Mon Oct 05, 2009 3:35 pm
Location: Curico-Chile

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby sjingo » Fri Apr 23, 2010 3: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: Select all  Expand view  RUN
//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 view  RUN

//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
User avatar
sjingo
 
Posts: 229
Joined: Sat Mar 18, 2006 3:42 pm
Location: Ibarra-Ecuador

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby armando.lagunas » Fri Apr 23, 2010 4: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
User avatar
armando.lagunas
 
Posts: 346
Joined: Mon Oct 05, 2009 3:35 pm
Location: Curico-Chile

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby Daniel Garcia-Gil » Fri Apr 23, 2010 4: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
User avatar
Daniel Garcia-Gil
 
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby Daniel Garcia-Gil » Fri Apr 23, 2010 4: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
User avatar
Daniel Garcia-Gil
 
Posts: 2365
Joined: Wed Nov 02, 2005 11:46 pm
Location: Isla de Margarita

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby antolin » Fri Apr 23, 2010 8: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: Select all  Expand view  RUN

LOCAL cImage
cImage := MemoRead( "C:\....\Imagen.Bmp")
BuilImage( cImage )
 

La nueva función sería esta:

Code: Select all  Expand view  RUN
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
antolin
 
Posts: 498
Joined: Thu May 10, 2007 8:30 pm
Location: Sevilla

Re: grabar y llamar un archivo de imagen en una tabla mySQL

Postby armando.lagunas » Sat Apr 24, 2010 4: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
User avatar
armando.lagunas
 
Posts: 346
Joined: Mon Oct 05, 2009 3:35 pm
Location: Curico-Chile


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 63 guests