Jump to content


Photo

[MULTILENGUAJE] Leer archivos graficos en varios formatos.


  • Please log in to reply
No replies to this topic

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 07 April 2011 - 03:57 AM

GDI plus es una potente extensión de las clásicas GDI de windows. Entre otras cosas, permiten leer y codificar archivos graficos de los tipos BMP, GIF, JPEG, PNG, TIFF, WMF, EMF, ICON, todos ellos muy interesantes.

Quizás Microsoft a enfocado demasiado la interface del GDI+ hacia el C++, hasta el punto de que existe toda una librería de clases para este lenguaje. Pese a su comodidad de uso desde el mismo Builder, precisa descargar WSDK. No se si en las versiones mas recientes de delphi y Builder se incorpora de serie la librería de clases del GDI+, pero en las versiones que uso yo no se incluyen, es por eso que me he decidido a publicar este truco.

Propongo un código simple para crear un HBITMAP a partir de un archivo de los tipos arriba descritos, pero lo pondré de distintas formas según gustos y comodidades.

Usando La librería de clases GDI+:


cpp
  1. #define STRICT
  2. #include <windows.h>
  3. #include <algorithm>
  4. using std::min;
  5. using std::max;
  6. #include "Gdiplus.h"
  7. #pragma link "Gdiplus.lib"
  8.  
  9. HBITMAP CreateHBITMAPFromFile(CHAR *cFileName)
  10. {
  11.   WCHAR *FileName = new WCHAR[strlen(cFileName)+1];
  12.   int size = strlen(cFileName)*sizeof(WCHAR)+1;
  13.   MultiByteToWideChar(CP_ACP, 0, cFileName, -1, FileName, size);
  14.  
  15.   // Initialize GDI+.
  16.   Gdiplus::GdiplusStartupInput gdiplusStartupInput;
  17.   ULONG_PTR  gdiplusToken;
  18.   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
  19.  
  20.   HBITMAP hBitmap;
  21.   Gdiplus::Bitmap *GBitmap = new Gdiplus::Bitmap(FileName, 0);
  22.   GBitmap->GetHBITMAP(0, &hBitmap);
  23.  
  24.   //shutdown GDI+
  25.   Gdiplus::GdiplusShutdown(gdiplusToken);
  26.   delete GBitmap;
  27.   delete FileName;
  28.   return hBitmap;
  29. }



Si no tenemos o no queremos usar la WSDK, podemos optar por usar la GDI+ Flat API importando las API que necesitemos usar.

Usando GDI+ Flat API en C/C++:


cpp
  1. HBITMAP CreateHBITMAPFromFile(CHAR *cFileName)
  2. {
  3.   typedef DWORD (__stdcall *PGdiplusStartup)(ULONG_PTR *hToken, void *input, void *Output);
  4.   typedef void  (__stdcall *PGdiplusShutdown)(ULONG_PTR token);
  5.   typedef DWORD (__stdcall *PGdipCreateBitmapFromFile)(WCHAR* filename, HANDLE* bitmap);
  6.   typedef DWORD (__stdcall *PGdipCreateHBITMAPFromBitmap)(HANDLE bitmap, HBITMAP* hBitmap, DWORD BKColor);
  7.   PGdiplusStartup GdiplusStartup = (PGdiplusStartup)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdiplusStartup");
  8.   PGdipCreateBitmapFromFile GdipCreateBitmapFromFile = (PGdipCreateBitmapFromFile)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdipCreateBitmapFromFile");
  9.   PGdipCreateHBITMAPFromBitmap GdipCreateHBITMAPFromBitmap = (PGdipCreateHBITMAPFromBitmap)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdipCreateHBITMAPFromBitmap");
  10.   PGdiplusShutdown GdiplusShutdown = (PGdiplusShutdown)GetProcAddress(LoadLibrary("gdiplus.dll"), "GdiplusShutdown");
  11.   if(!GdiplusStartup || !GdiplusShutdown || !GdipCreateBitmapFromFile || !GdipCreateHBITMAPFromBitmap) return 0;
  12.  
  13.   // Pasamos a Unicode
  14.   WCHAR *FileName = new WCHAR[strlen(cFileName)+1];
  15.   int size = strlen(cFileName)*sizeof(WCHAR)+1;
  16.   MultiByteToWideChar(CP_ACP, 0, cFileName, -1, FileName, size);
  17.  
  18.   // Inicializamos GDI+.
  19.   HBITMAP hBitmap = 0;
  20.   ULONG_PTR  gdiplusToken;
  21.   char GdiPlusStartupInput[16] = {1,0};
  22.   if(!GdiplusStartup(&gdiplusToken, GdiPlusStartupInput, NULL)){
  23.     HANDLE GBitmap = 0;
  24.     GdipCreateBitmapFromFile(FileName, &GBitmap);
  25.     GdipCreateHBITMAPFromBitmap(GBitmap, &hBitmap, 0);
  26.     GdipDisposeImage(GBitmap);
  27.     // Cerramos GDI+
  28.     GdiplusShutdown(gdiplusToken);
  29.   }
  30.   delete FileName;
  31.   return hBitmap;
  32. }



Y este segundo método con GDI+ Flat API en delphi:


delphi
  1. function GdiplusStartup(var GdiToken: DWORD; Startup, Output: PBYTE): DWORD; stdcall external 'gdiplus';
  2. function GdipCreateBitmapFromFile(lpFileName: PWCHAR; var GBitmap: THANDLE): DWORD; stdcall external 'gdiplus';
  3. function GdipCreateHBITMAPFromBitmap(GBitmap: THANDLE; var hBitmap: HBITMAP; BKColor: DWORD): DWORD; stdcall external 'gdiplus';
  4. procedure GdiplusShutdown(GdiToken: DWORD); stdcall external 'gdiplus';
  5.  
  6. function CreateHBITMAPFromFile(cFileName: PCHAR): HBITMAP;
  7. var
  8.   FileName: array of WCHAR;
  9.   size: integer;
  10.   gdiplusToken: DWORD;
  11.   GdiPlusStartupInput: array[0..2] of int64;
  12.   GBitmap: THANDLE;
  13.  
  14. begin
  15.   Result:= 0;
  16.  
  17.   // Pasamos a Unicode
  18.   SetLength(FileName, lstrlen(cFileName)+1);
  19.   size:= lstrlen(cFileName)*sizeof(WCHAR)+1;
  20.   MultiByteToWideChar(CP_ACP, 0, cFileName, -1, @FileName[0], size);
  21.  
  22.   // Inicializamos GDI+.
  23.   GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0;
  24.   if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) = 0 then
  25.   begin
  26.     GdipCreateBitmapFromFile(PWCHAR(FileName), GBitmap);
  27.     GdipCreateHBITMAPFromBitmap(GBitmap, Result, 0);
  28.     GdipDisposeImage(GBitmap);   
  29.     // Cerramos GDI+
  30.     GdiplusShutdown(gdiplusToken);
  31.   end;
  32. end;



Ejemplos de código:


cpp
  1. Image1->Picture->Bitmap->Handle = CreateHBITMAPFromFile("Image.png");




cpp
  1. Image1.Picture.Bitmap.Handle:= CreateHBITMAPFromFile('Image.png');




Espero que la información y el código os sea de utilidad.

Saludos.


Edito para cambiar etiquetas de código
  • 0




IP.Board spam blocked by CleanTalk.