Page 1 of 3

Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 9:32 am
by AngelSalom
Buenas amigos.
Estoy implementando un módulo que requiere una conversión masiva de archivos de imagen. De cada fichero saldrán 8 a distintos tamaños en una base de datos de unos 1000 registros.
Hasta la fecha he venido utilizando una función que creé aunque nunca con gran volumen de datos, sólo la llamaba en ciertos procesos de la aplicación y ningún problema. Pero ahora al procesar este volumen de imágenes el sistema queda totalmente colapsado al poco de iniciar.

Aquí el código de la función de redimensionado a ver si veis algún fallo o sugerencia. O si conocéis algún método mejor para redimensionar imágenes.
Gracias,

Code: Select all  Expand view

Function RedimensionaJPG ( cFileIn, cFileOut, nWidth, nHeight, lBorrar )
/* ===================================================================================================================
   Se ocupa de redimensionar un archivo . Se le puede pasar ancho y alto o sólo uno de los dos parámetros para
   que redimensione proporcionalmente.
   
   Parámetros : cFileIn  - Fichero de Entrada
                cFileOut - Fichero de Saluda
                nWidth   - nAncho
                nHeight  - nAlto
                lBorrar  - Borrar fichero origen
   ====================================================================================================================
*/

Local hBmp, hDib, cTempFile:=cTempFile(), lSaved
Local hResizedBitmap

  DEFAULT lBorrar:=.F.
 
  If cFileIn<>NIL .AND. cFileOut<>NIL
    // Cargo un fichero
    hBmp:=FILOADIMG (cFileIn)
   
    If hBmp<>0
      // Redimensiono hBmp
      hResizedBitmap:=RedimensionaProporcionado ( hBmp, nWidth, nHeight )

      // Guardo en fichero temporal el redimensionado
      hDib := DibFromBitmap( hResizedBitmap )
      DibWrite( cTempFile, hDib )

      // Libero memoria
      GlobalUnlock( hDib)
      GloBalFree  ( hDib )
      GlobalUnlock( hResizedBitmap )
      GlobalFree  ( hResizedBitmap )

      // Convierto un fichero en otro
      lSaved = FIConvertImageFile( cTempFile, cFileOut, 2 )

      // Borro fichero temporal
      FErase( cTempFile )

      // Borro el fichero original si es necesario
      If lSaved .AND. lBorrar
        FErase ( cFileIn )
      Endif
      SysRefresh()
    Else
        lSaved:=.F.
    Endif
  Endif

Return (lSaved)                  

Function RedimensionaProporcionado ( hbmp, nWidth, nHeight )
/* ===================================================================================================================
   Permite redimensionar un "handle" (hbmp) de forma proporcionada si se le pasa nWidth o nHeight
   
   Parámetros : hBmp   - Handle bmp creado
                nWidth - Ancho
                nHeight  - nAlto
 
   ====================================================================================================================
*/


Local hResizedBitmap:=hBmp

  If Valtype( nWidth ) == "N" .AND. Valtype( nHeight ) == "N"
    If nBmpWidth( hBmp )>nWidth .OR. nBmpHeight( hBmp )>nHeight
      hResizedBitmap := ResizeBmp( hBmp, nWidth, nHeight )
    Endif
 
  ElseIf Valtype( nWidth ) == "N"
     If nBmpWidth( hBmp ) > nWidth
       hResizedBitmap := ResizeBmp( hBmp, nWidth, nBmpHeight( hBmp ) / ( nBmpWidth( hBmp ) /nWidth ) )
     Endif
  ElseIf Valtype( nHeight )=="N"
     If nBmpHeight( hBmp ) > nHeight
        hResizedBitmap := ResizeBmp( hBmp, nBmpWidth( hBmp ) / (nBmpHeight( hBmp ) / nHeight ), nHeight )
     Endif
  Endif
Return (hResizedBitmap)  

 

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 10:32 am
by mastintin
Aqui usas la libreria freeimage para hacer las conversiones , estos dias atras hemos creado un codigo que usa gdi+ para hacerlo ....
Si te interesa intentarlo sería estupendo para comprobar que efectivamante funciona bien .
Tendrias que crear un archivo cpp con un codigo y enlazarlo y tambien una pequeña función .
Saludos.

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 10:48 am
by AngelSalom
Mastitin, Si me indicas cómo me tiro de cabeza :D :D

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 11:26 am
by mastintin
pues vamos a ello :
Crea un nuevo archivo gdiplusfun.cpp y coloca dentro :
Code: Select all  Expand view


#include <hbapi.h>
#include <windows.h>
#include <gdiplus.h>

using namespace Gdiplus;

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR   gdiplusToken;



HB_FUNC( GDIPLUSCREATEIMAGEFROMFILE )
{
    Bitmap * newImage =  new Bitmap(  (LPCWSTR) hb_parc(1)  );  
  hb_retnl( ( HB_LONG ) newImage );
 
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETWIDTHBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG )   newImage->GetWidth() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETHEIGHTBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG ) newImage->GetHeight() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSCREATETHUMBNAILIMAGE )
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  int nWidth  = hb_parnd( 2 );
  int nHeight = hb_parnd( 3 );
   
  Image * thumb = newImage->GetThumbnailImage( nWidth, nHeight, NULL, NULL  ) ;
   
  hb_retnl( ( HB_LONG ) thumb );
 
}


HB_FUNC( GDIPLUSIMAGESAVE )
{
  Image * newImage = ( Image * ) hb_parnl( 1 );
  CLSID cClsid ;
  LPWSTR file = (LPWSTR) hb_parc(2);
  LPWSTR identificador =  (LPWSTR) hb_parc(3);
  CLSIDFromString( identificador, &cClsid ) ;
   newImage->Save( file , &cClsid, NULL);
}


 



en cualquiera de tus prg coloca esta funcion :

Code: Select all  Expand view

Function GDIPlusSaveThumbnail( cImageIni, cImageEnd , nWidth, nHeight )

local cExtIni := Upper(cFileExt( cImageIni ))
local cExtEnd := Upper(cFileExt(cImageEnd ))
local hImage:= GDIPLUSCREATEIMAGEFROMFILE( cImageIni )
local hThumb
local nScan
local nRatio
local nOldWidth  := GDIPLUSGETWIDTHBITMAP( hImage )
local nOldHeight := GDIPLUSGETHEIGHTBITMAP( hImage )
local aExtIni := { "BMP", "JPG", "GIF", "TIF", "PNG" }
local aExtEnd := { "BMP", "JPG", "GIF", "TIF", "PNG" }
local aCLSID  := { "{557CF400-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF401-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF402-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF405-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF406-1A04-11D3-9A73-0000F81EF32E}"  ;
               }

local cCLSID

  if Empty( nHeight )
     nRatio := nOldWidth / nOldHeight
     nHeight := nWidth * nRatio
  endif

 if( nScan:= aScan( aExtIni, cExtIni )) == 0
    Msginfo( " el archivo "+ cImageIni + " tiene un formato no soportado")
    return .f.
 endif

 hThumb:= GDIPLUSCREATETHUMBNAILIMAGE( hImage, nWhidth, nHeight )
 
 nScan:= aScan( aExtEnd, cExtend )

 if nScan == 0
    msginfo( "Formato no soportado" )
    Return .f.
endif

 cCLSID := aCLSID[ nScan ]
 
 cCLSID = AnsiToWide( cCLSID )
 cImageEnd  = AnsiToWide( cImageEnd )

 GdiPlusImageSave( hThumb, cImageEnd, cCLSID )
 
 
 
hImage:= nil
hThumb:= nil

return .t.

 


enlaza el nuevo archivo y listo .
Dime si he metido algun gazapo o te da algún error...

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 11:30 am
by Antonio Linares
+1 ;-)

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 2:37 pm
by AngelSalom
Bueno, me he puesto a ello pero sin éxito de momento.

He montado un ejemplo autocontenido antes de implantarlo en la aplicación. El gdiplusfan.cpp es tal cual me lo pasa mastitin, pero lo copio también aquí. La función GDIPLusSaveThumbnail tiene un pequeño cambio para poner algún msginfo que vaya desvelando los problemas. Bien, el tema es que GDIPLUSCREATEIMAGEFROMFILE devuelve 0 y al llamar a GDIPLUSGETWIDTHBITMAP con el handle el programa revienta con el fallo de windows "test.exe dejó de funcionar ...".

Dejo también el fichero de compilado a ver si hago algo mal.
Saludetes,

test.prg
Code: Select all  Expand view

#include "fivewin.ch"

Function Main ()

  GDIPlusSaveThumbnail ("c:\envio\captura.jpg", "c:\envio\captura2.jpg",100 )
 
Return (nil)

Function GDIPlusSaveThumbnail( cImageIni, cImageEnd , nWidth, nHeight )

local cExtIni := Upper(cFileExt( cImageIni ))
local cExtEnd := Upper(cFileExt(cImageEnd ))
local hImage
local hThumb
local nScan
local nRatio
local nOldWidth  
local nOldHeight
local aExtIni := { "BMP", "JPG", "GIF", "TIF", "PNG" }
local aExtEnd := { "BMP", "JPG", "GIF", "TIF", "PNG" }
local aCLSID  := { "{557CF400-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF401-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF402-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF405-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF406-1A04-11D3-9A73-0000F81EF32E}"  ;
               }

local cCLSID
 
  msginfo (file (cimageini) )
 
  hImage:=GDIPLUSCREATEIMAGEFROMFILE( cImageIni )
  msginfo (himage)

  nOldWidth  := GDIPLUSGETWIDTHBITMAP( hImage )
  msginfo (nOldWidth)

  nOldHeight := GDIPLUSGETHEIGHTBITMAP( hImage )
  msginfo (nOldHeight)

  DEFAULT nWidth:=nOldWidth
 

  if Empty( nHeight )
     nRatio := nOldWidth / nOldHeight
     nHeight := nWidth * nRatio
  endif

 if( nScan:= aScan( aExtIni, cExtIni )) == 0
    Msginfo( " el archivo "+ cImageIni + " tiene un formato no soportado")
    return .f.
 endif

 hThumb:= GDIPLUSCREATETHUMBNAILIMAGE( hImage, nWhidth, nHeight )
 
 nScan:= aScan( aExtEnd, cExtension )

 if nScan == 0
    msginfo( "Formato no soportado" )
    Return .f.
endif

 cCLSID := aCLSID[ nScan ]
 
 cCLSID = AnsiToWide( cCLSID )
 cImageEnd  = AnsiToWide( cImageEnd )

 GdiPlusImageSave( hThumb, cImageEnd, cCLSID )
 
 
 
hImage:= nil
hThumb:= nil

return .t.

 


gdiplusfan.cpp
Code: Select all  Expand view


#include <hbapi.h>
#include <windows.h>
#include <gdiplus.h>

using namespace Gdiplus;

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR   gdiplusToken;



HB_FUNC( GDIPLUSCREATEIMAGEFROMFILE )
{
    Bitmap * newImage =  new Bitmap(  (LPCWSTR) hb_parc(1)  );  
  hb_retnl( ( HB_LONG ) newImage );
 
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETWIDTHBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG )   newImage->GetWidth() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETHEIGHTBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG ) newImage->GetHeight() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSCREATETHUMBNAILIMAGE )
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  int nWidth  = hb_parnd( 2 );
  int nHeight = hb_parnd( 3 );
   
  Image * thumb = newImage->GetThumbnailImage( nWidth, nHeight, NULL, NULL  ) ;
   
  hb_retnl( ( HB_LONG ) thumb );
 
}


HB_FUNC( GDIPLUSIMAGESAVE )
{
  Image * newImage = ( Image * ) hb_parnl( 1 );
  CLSID cClsid ;
  LPWSTR file = (LPWSTR) hb_parc(2);
  LPWSTR identificador =  (LPWSTR) hb_parc(3);
  CLSIDFromString( identificador, &cClsid ) ;
   newImage->Save( file , &cClsid, NULL);
}


 
 


c.bat
Code: Select all  Expand view

@ECHO OFF

set hdir  = c:\SI\NLEN\harbour
set bcdir = c:\SI\NLEN\bcc582
set fwdir = c:\si\nlen\fwh1204

%bcdir%\bin\bcc32 -M -c -v -O2 -I%hdir%\include;%bcdir%\include;%bcdir%\include\dinkumware gdiplusfan.cpp
%hdir%\bin\harbour test.prg /i%fwdir%\include;%hdir%\include;%bcdir%\include
%bcdir%\bin\bcc32 -M -c -I%hdir%\include;%bcdir%\include %test.c

echo %bcdir%\lib\c0w32.obj + > b32.bc
echo test.obj        +>> b32.bc
echo gdiplusfan.obj, +>> b32.bc
echo test.exe,       + >> b32.bc
echo test.map,       + >> b32.bc

echo %fwdir%\lib\FiveH.lib %fwdir%\lib\FiveHC.lib + >> b32.bc
echo %hdirl%\hbrtl.lib + >> b32.bc
echo %hdirl%\hbvm.lib + >> b32.bc
echo %hdirl%\gtgui.lib + >> b32.bc
echo %hdirl%\hblang.lib + >> b32.bc
echo %hdirl%\hbmacro.lib + >> b32.bc
echo %hdirl%\hbrdd.lib + >> b32.bc
echo %hdirl%\rddntx.lib + >> b32.bc
echo %hdirl%\rddcdx.lib + >> b32.bc
echo %hdirl%\rddfpt.lib + >> b32.bc
echo %hdirl%\hbsix.lib + >> b32.bc
echo %hdirl%\hbdebug.lib + >> b32.bc
echo %hdirl%\hbcommon.lib + >> b32.bc
echo %hdirl%\hbpp.lib + >> b32.bc
echo %hdirl%\hbcpage.lib + >> b32.bc
echo %hdirl%\hbwin.lib + >> b32.bc
echo %hdirl%\hbcplr.lib + >> b32.bc
echo %hdirl%\hbct.lib + >> b32.bc
echo %hdirl%\hbpcre.lib + >> b32.bc
echo %hdirl%\xhb.lib + >> b32.bc
echo %hdirl%\hbziparc.lib + >> b32.bc
echo %hdirl%\hbmzip.lib + >> b32.bc
echo %hdirl%\hbzlib.lib + >> b32.bc
echo %hdirl%\minizip.lib + >> b32.bc
echo %hdirl%\png.lib + >> b32.bc

echo %bcdir%\lib\cw32.lib + >> b32.bc
echo %bcdir%\lib\uuid.lib + >> b32.bc
echo %bcdir%\lib\import32.lib + >> b32.bc
echo %bcdir%\lib\ws2_32.lib + >> b32.bc
echo %bcdir%\lib\psdk\odbc32.lib + >> b32.bc
echo %bcdir%\lib\psdk\nddeapi.lib + >> b32.bc
echo %bcdir%\lib\psdk\iphlpapi.lib + >> b32.bc
echo %bcdir%\lib\psdk\msimg32.lib + >> b32.bc
echo %bcdir%\lib\psdk\psapi.lib + >> b32.bc
echo %bcdir%\lib\psdk\rasapi32.lib + >> b32.bc
echo %bcdir%\lib\psdk\gdiplus.lib + >> b32.bc
echo %bcdir%\lib\psdk\shell32.lib, + >> b32.bc

%bcdir%\bin\ilink32 -Gn -aa -Tpe -s @b32.bc


 

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 5:54 pm
by mastintin
Bien en el prg :
Dos gazapos ...

hThumb:= GDIPLUSCREATETHUMBNAILIMAGE( hImage, nWidth, nHeight ) // bug
nScan:= aScan( aExtEnd, cExtend ) // bug

y añadir :



init procedure GdiPlusStart()

GdiPlusStartup()

return

//----------------------------------------------------------------------------//

exit procedure GdiPlusEnd()

GdiPlusShutdown()

return

en el cpp :
añadir :


HB_FUNC( GDIPLUSSTARTUP )
{
hb_retl( GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL ) );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSSHUTDOWN )
{
GdiplusShutdown( gdiplusToken );
}

Sigo buscando los gazapos.... ahora no nos devuelve el ancho y el alto

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 7:04 pm
by AngelSalom
Aplicados los cambios que sugieres mastintin, ahora no da el fallo y ciertamente devuelve el ancho y alto a cero ... he probado a pasarle valores tanto de ancho como de alto para que no tenga que calcular y la función GDIPLUSCREATETHUMBNAILIMAGE parece que devuelve un handle correcto, en cambio la GdiPlusImageSave parece no hacer nada.
He comprobado las cadenas cCLSID y cImageEnd y parece que contienen la información adecuada ...
:shock: :shock:

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 7:18 pm
by mastintin
Una pregunta . ¿Tienes en tu fwh Tgdiplus.prg ? c:\fwh\source\clases

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 8:03 pm
by AngelSalom
Si, aquí te pego el contenido. La versión de FWH que uso es de Abril del 2012. Tengo también la versión de febrero de 2014 pero es la de 64bits, pendiente de migrar las aplicaciones :oops:

Code: Select all  Expand view

// GdiPlus support classes. (c) FiveTech Software 2011

#include "FiveWin.ch"

#DEFINE GDI_PEN_ROUND   1

//----------------------------------------------------------------------------//

CLASS Graphics

   DATA   hGraphics

   METHOD New( hDC , lNoHighQuality )

   METHOD SetHighQuality( ) INLINE GdiPlusHighQuality( ::hGraphics )

   METHOD SetNormalQuality( ) INLINE GdiPlusNormalQuality( ::hGraphics )

   METHOD DrawLine( oPen, nLeft, nTop, nRight, nBottom ) INLINE ;
          GdiPlusDrawLine( ::hGraphics, if(!empty(oPen),oPen:hPen,NIL), nLeft, nTop, nRight, nBottom )

   METHOD DrawRect( oPen, oBrush, nLeft, nTop, nWidth, nHight ) INLINE ;
          GdiPlusDrawRect( ::hGraphics, if(!empty(oPen),oPen:hPen,NIL), if(!empty(oBrush),oBrush:hBrush,NIL) , nLeft, nTop, nWidth, nHight )

   METHOD DrawEllipse( oPen, oBrush, nLeft, nTop, nWidth, nHight ) INLINE ;
          GdiPlusDrawEllipse( ::hGraphics, if(!empty(oPen),oPen:hPen,NIL), if(!empty(oBrush),oBrush:hBrush,NIL) , nLeft, nTop, nWidth, nHight )

   METHOD Destroy()

   DESTRUCTOR Destroy()

ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( hDC , lNoHighQuality ) CLASS Graphics

   ::hGraphics = GdiPlusNewGraphics( hDC )

   DEFAULT lNoHighQuality := .F.

   if lNoHighQuality
    ::SetNormalQuality( )
   else
    ::SetHighQuality( )
   endif

return Self

//----------------------------------------------------------------------------//

METHOD Destroy() CLASS Graphics

   GdiPlusDeleteGraphics( ::hGraphics )

   ::hGraphics = nil

return nil

//----------------------------------------------------------------------------//

CLASS Pen

   DATA   hPen

   METHOD New( nTrans, nRed, nGreen, nBlue, nSize, lRound, lAlign )

   METHOD SetSize( nSize ) INLINE GdiPlusPenSize( ::hPen , nSize )

   METHOD SetStyle( nStyle )

   METHOD SetInset( ) INLINE GdiPlusAlign( ::hPen )

   METHOD SetNoInset( ) INLINE GdiPlusNoAlign( ::hPen )

   METHOD Destroy()

   DESTRUCTOR Destroy()

ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( nTrans, nRed, nGreen, nBlue, nSize, lRound, lAlign ) CLASS Pen

   ::hPen = GdiPlusNewPen( nTrans, nRed, nGreen, nBlue )

   DEFAULT nSize := 1 , lRound := .F. , lAlign := .F.

   ::SetSize( nSize )

   if lRound
        ::SetStyle ( GDI_PEN_ROUND )
     endif
   
     if lAlign
          ::SetAlign ( )
     endif

return Self

//----------------------------------------------------------------------------//

METHOD SetStyle( nStyle ) CLASS Pen

   do case
        case nStyle == GDI_PEN_ROUND
               GdiPlusPenStyle( ::hPen, 2 )

   endcase

return nil

//----------------------------------------------------------------------------//

METHOD Destroy() CLASS Pen

   GdiPlusDeletePen( ::hPen )

   ::hPen = nil

return nil

//----------------------------------------------------------------------------//

CLASS Brush

   DATA   hBrush

   METHOD NewSolidBrush( nTrans, nRed, nGreen, nBlue )

   METHOD Destroy()

   DESTRUCTOR Destroy()

ENDCLASS

//----------------------------------------------------------------------------//

METHOD NewSolidBrush( nTrans, nRed, nGreen, nBlue ) CLASS Brush

   ::hBrush = GdiPlusNewSolidBrush( nTrans, nRed, nGreen, nBlue )

return Self

//----------------------------------------------------------------------------//

METHOD Destroy() CLASS Brush

   GdiPlusDeleteBrush( ::hBrush )

   ::hBrush = nil

return nil

//----------------------------------------------------------------------------//

init procedure GdiPlusStart()

   GdiPlusStartup()

return

//----------------------------------------------------------------------------//

exit procedure GdiPlusEnd()

   GdiPlusShutdown()

return

//----------------------------------------------------------------------------//
 

Re: Redimensionando imágenes

PostPosted: Wed Dec 10, 2014 11:05 pm
by mastintin
Ya lo tengo funcionando . He recreado los archivos que copio y parece funcionar bien . Espero no falte nada que este cogiendo de las librerías fwh y que tu no tengas .
Bien . Vamos a hacerlo de otra forma . Vamos a copiar el archivo tgdiplus.prg al directorio donde estés trabajando el ejemplo y lo añadimos al bat .
Ahora al final del archivo añadimos la clase bitmap .

Code: Select all  Expand view


CLASS GDIBmp

   DATA hBmp
   DATA aCLSID
   DATa aExtIni, aExtEnd
   
   METHOD New( cFile )
   METHOD Destroy()
   METHOD Save( cFile )
   METHOD getwidth() INLINE GDIPLUSGETWIDTHBITMAP( ::hBmp )  
   METHOD getHeight() INLINE GDIPLUSGETHEIGHTBITMAP( ::hBmp )  
   DESTRUCTOR Destroy()

ENDCLASS


//----------------------------------------------------------------------------//

METHOD New( cFile ) CLASS GDIBmp
local aBmpPal

 
   ::aExtIni := { "BMP", "JPG", "GIF", "TIF", "PNG","EMF","WMF","ICO" }
   ::aExtEnd := { "BMP", "JPG", "GIF", "TIF", "PNG" }
   ::aCLSID := { "{557CF400-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF401-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF402-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF405-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF406-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF403-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF404-1A04-11D3-9A73-0000F81EF32E}" ,;
                               "{557CF407-1A04-11D3-9A73-0000F81EF32E}" ;
               }
     
   
  if !Empty(cFile)
      if File( cFile )
       ::hBmp = GdiPlusCreateImageFromFile( AnsiToWide( cFile ) )  
      else
        msginfo( "fichero no encontrados" )    
      endif  
   endif
                       
return Self


//----------------------------------------------------------------------------//

METHOD Save( cFile ) CLASS GDIBmp
local cExtension := Upper(cFileExt(cFile))
local cCLSID

local nScan:= aScan( ::aExtEnd, cExtension )

if nScan == 0
    msginfo( "Formato no soportado" )
    Return .f.
endif

 cCLSID := ::aCLSID[ nScan ]
 
 cCLSID = AnsiToWide( cCLSID )
 cFile  = AnsiToWide( cFile )
 
 GdiPlusImageSave( ::hBmp, cFile, cCLSID )

Return nil


METHOD Destroy() CLASS GDIBmp
      ::hBmp = nil
return nil


Function GDIPlusResizeImage( cImageIni, cImageEnd , nWidth, nHeight )

local cExtIni := Upper(cFileExt( cImageIni ))
local cExtEnd := Upper(cFileExt( cImageEnd ))
local oImage
local nScan
local nOldHeight, nOldWidth, nRatio

if cImageIni == cImageEnd
   msginfo( "Error. La imagen inicial y final son la misma" )
   Return .f.
endif


oImage:= GDIBmp():New( cImageIni )

 if( nScan:= aScan( oImage:aExtIni, cExtIni )) == 0
    Msginfo( " el archivo "+ cImageIni + " tiene un formato no soportado")
    return .f.
 endif
 
 if( nScan:= aScan( oImage:aExtEnd, cExtEnd )) == 0
    Msginfo( " el archivo "+ cImageEnd + " tiene un formato no soportado")
    return .f.
 endif
 
 
  nOldWidth  := oImage:getWidth()
  nOldHeight := oImage:GetHeight()
   
 if Empty( nHeight )
     nRatio :=  nOldHeight / nOldWidth
     nHeight := nWidth * nRatio
  endif
 
   if Empty( nWidth )
     nRatio :=  nOldHeight /  nOldWidth
     nWidth := nHeight * nRatio
  endif


 
oImage:hBmp:= GDIPLUSIMAGERESIZE(oImage:hBmp ,  nWidth, nHeight )
 
oImage:Save( cImageEnd )
oImage:Destroy()

Return nil



 


ahora vamos con el archivo cpp . Borra lo que tengas en el y vamos a poner lo que copio aquí :

Code: Select all  Expand view


// GdiPlus support (c) FiveTech Software

#include <hbapi.h>
#include <windows.h>
#include <gdiplus.h>



using namespace Gdiplus;

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR   gdiplusToken;


//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETWIDTHBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG )   newImage->GetWidth() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETHEIGHTBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG ) newImage->GetHeight() );
}

//----------------------------------------------------------------------------//

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSIMAGERESIZE )
{
     int nWidth =  hb_parni( 2 );
   int nHeight = hb_parni( 3 );
   Bitmap * original = ( Bitmap * ) hb_parnl( 1 );
   //Bitmap * original = new Bitmap(  (LPCWSTR) hb_parc(1)  );  
 
   Bitmap* newImage  = new Bitmap( nWidth, nHeight);
   Graphics * graphics = new Graphics( newImage );
  graphics->DrawImage( original ,0, 0, nWidth, nHeight);

 hb_retnl( ( HB_LONG ) newImage );
 
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSIMAGESAVE )
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  CLSID cClsid ;
  LPWSTR file = (LPWSTR) hb_parc(2);
  LPWSTR identificador =  (LPWSTR) hb_parc(3);
  CLSIDFromString( identificador, &cClsid ) ;
   newImage->Save( file , &cClsid, NULL);
   
}

HB_FUNC( GDIPLUSCREATEIMAGEFROMFILE )
{
    Bitmap * newImage =  new Bitmap(  (LPCWSTR) hb_parc(1)  );  
  hb_retnl( ( HB_LONG ) newImage );
 
}



 


Por ultimo el test, esto falta colocarlo bonito : :D .

Code: Select all  Expand view


#include "FiveWin.ch"

Function Main ()
local ownd

 DEFINE WINDOW oWnd TITLE "Testing GDI+ Class" FROM 5,5 TO 600, 800 PIXEL
   
       @ 2,2 button "crear" Action  ( GDIPlusResizeImage( "c:\fwh\bitmaps\pngs\image13.png" , "c:\fwh\bitmaps\pngs\image13333.png" , 50  ) )
   
    @ 2 ,30 Button "salir" Action ownd:end()
     
    ACTIVATE WINDOW oWnd


Return (nil)

 


Espero que no mwe falte nada ....

Re: Redimensionando imágenes

PostPosted: Thu Dec 11, 2014 8:03 am
by AngelSalom
Bueeeeeeno. Ahora SI que ha funcionado.
Voy a adaptarlo a la aplicación, haré el test de conversión "masivo" y os cuento los resultados.
:D :D

Re: Redimensionando imágenes

PostPosted: Thu Dec 11, 2014 8:26 am
by Antonio Linares
Manuel y Angel,

Muchas gracias, esto es muy bueno para todos :-)

Manuel, hay algún cambio que incluir nuevo a FWH ?

gracias!!!

Re: Redimensionando imágenes

PostPosted: Thu Dec 11, 2014 10:30 am
by mastintin
Antonio , Vamos a esperar los resultados de Angel , pero en principio si que tenemos cosas para incluir ...

en cpp 3 funciones :

Code: Select all  Expand view


//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETWIDTHBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG )   newImage->GetWidth() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSGETHEIGHTBITMAP)
{
  Bitmap * newImage = ( Bitmap * ) hb_parnl( 1 );
  hb_retnl( ( HB_LONG ) newImage->GetHeight() );
}

//----------------------------------------------------------------------------//

HB_FUNC( GDIPLUSIMAGERESIZE )
{
     int nWidth =  hb_parni( 2 );
   int nHeight = hb_parni( 3 );
   Bitmap * original = ( Bitmap * ) hb_parnl( 1 );
   //Bitmap * original = new Bitmap(  (LPCWSTR) hb_parc(1)  );  
 
   Bitmap* newImage  = new Bitmap( nWidth, nHeight);
   Graphics * graphics = new Graphics( newImage );
  graphics->DrawImage( original ,0, 0, nWidth, nHeight);

 hb_retnl( ( HB_LONG ) newImage );
 
}


 


en el tgdiimage.prg :
3 metodos y una funcion :

Code: Select all  Expand view

  CLASS GDIBmp
  ....
  METHOD getwidth() INLINE GDIPLUSGETWIDTHBITMAP( ::hBmp )  
  METHOD getHeight() INLINE GDIPLUSGETHEIGHTBITMAP( ::hBmp )  
 ....


Function GDIPlusResizeImage( cImageIni, cImageEnd , nWidth, nHeight )

local cExtIni := Upper(cFileExt( cImageIni ))
local cExtEnd := Upper(cFileExt( cImageEnd ))
local oImage
local nScan
local nOldHeight, nOldWidth, nRatio

if cImageIni == cImageEnd
   msginfo( "Error. La imagen inicial y final son la misma" )
   Return .f.
endif


oImage:= GDIBmp():New( cImageIni )

 if( nScan:= aScan( oImage:aExtIni, cExtIni )) == 0
    Msginfo( " el archivo "+ cImageIni + " tiene un formato no soportado")
    return .f.
 endif
 
 if( nScan:= aScan( oImage:aExtEnd, cExtEnd )) == 0
    Msginfo( " el archivo "+ cImageEnd + " tiene un formato no soportado")
    return .f.
 endif
 
 
  nOldWidth  := oImage:getWidth()
  nOldHeight := oImage:GetHeight()
   
 if Empty( nHeight )
     nRatio :=  nOldHeight / nOldWidth
     nHeight := nWidth * nRatio
  endif
 
   if Empty( nWidth )
     nRatio :=  nOldHeight /  nOldWidth
     nWidth := nHeight * nRatio
  endif


 
oImage:hBmp:= GDIPLUSIMAGERESIZE(oImage:hBmp ,  nWidth, nHeight )
 
oImage:Save( cImageEnd )
oImage:Destroy()

Return nil


 

queda un nuevo methodo resize() pendiente de probar ...
su codigo :
Code: Select all  Expand view


METHOD Resize( nWidth, nHeight ) CLASS GDIBmp
local nRatio
local nOldWidth  := ::getWidth()
local nOldHeight := ::GetHeight()
   
 if Empty( nHeight )
     nRatio :=  nOldHeight / nOldWidth
     nHeight := nWidth * nRatio
  endif
 
   if Empty( nWidth )
     nRatio :=  nOldHeight /  nOldWidth
     nWidth := nHeight * nRatio
  endif
 
  ::hBmp:= GdiPlusImageResize(::hBmp , nWidth, nHeight )

 

Re: Redimensionando imágenes

PostPosted: Thu Dec 11, 2014 10:53 am
by AngelSalom
Os cuento. Acabo de hacer un test a lo bruto en un bucle redimensionando 5000 imágenes y ha funcionado rápido, muy rápido.
Peeeeero (siempre hay un pero), el consumo de memoria se incrementa en cada conversión provocando en el tiempo un "Cannot allocate memory" , estoy intentando aislar la parte de la conversión que se come la memoria ... ya os cuento.