FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Redimensionando imágenes
Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Redimensionando imágenes
Posted: Wed Dec 10, 2014 09:32 AM
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 (fw): Select all Collapse
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)
Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
Posts: 1516
Joined: Thu May 27, 2010 02:06 PM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 10:32 AM

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.

Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 10:48 AM

Mastitin, Si me indicas cómo me tiro de cabeza :D :D

Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
Posts: 1516
Joined: Thu May 27, 2010 02:06 PM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 11:26 AM
pues vamos a ello :
Crea un nuevo archivo gdiplusfun.cpp y coloca dentro :
Code (fw): Select all Collapse
#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 (fw): Select all Collapse
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...
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 11:30 AM

+1 ;-)

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 02:37 PM
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 (fw): Select all Collapse
#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 (fw): Select all Collapse
#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 (fw): Select all Collapse
@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
Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
Posts: 1516
Joined: Thu May 27, 2010 02:06 PM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 05:54 PM

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

Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 07:04 PM

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:

Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
Posts: 1516
Joined: Thu May 27, 2010 02:06 PM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 07:18 PM

Una pregunta . ¿Tienes en tu fwh Tgdiplus.prg ? c:\fwh\source\clases

Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 08:03 PM
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 :-)

Code (fw): Select all Collapse
// 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

//----------------------------------------------------------------------------//
Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
Posts: 1516
Joined: Thu May 27, 2010 02:06 PM
Re: Redimensionando imágenes
Posted: Wed Dec 10, 2014 11:05 PM
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 (fw): Select all Collapse
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 (fw): Select all Collapse
// 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 : :-) .

Code (fw): Select all Collapse
#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 ....
Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Re: Redimensionando imágenes
Posted: Thu Dec 11, 2014 08:03 AM

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

Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Redimensionando imágenes
Posted: Thu Dec 11, 2014 08:26 AM

Manuel y Angel,

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

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

gracias!!!

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 1516
Joined: Thu May 27, 2010 02:06 PM
Re: Redimensionando imágenes
Posted: Thu Dec 11, 2014 10:30 AM
Antonio , Vamos a esperar los resultados de Angel , pero en principio si que tenemos cosas para incluir ...

en cpp 3 funciones :

Code (fw): Select all Collapse
//----------------------------------------------------------------------------//

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 (fw): Select all Collapse
  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 (fw): Select all Collapse
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 )
Posts: 728
Joined: Fri Oct 07, 2005 07:38 AM
Re: Redimensionando imágenes
Posted: Thu Dec 11, 2014 10:53 AM

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.

Angel Salom
Visionwin Software - https://www.visionwin.com
------------------------------------------------------------
fwh 19.05 - harbour 3.2 - bcc 7.4