Ir al contenido



Foto

[MULTILENGUAJE] Cargar una Imagen de un Resource RT_RCDATA con API pura y GDI+ Flat


  • Por favor identifícate para responder
2 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.839 mensajes
  • LocationMadrid - España

Escrito 02 enero 2017 - 06:09

Es posible que en nuestro archivo de recursos tengamos imágenes en formatos gráficos que no sean Bitmap (png, jpg...) y deseemos cargarlos como una imagen desde ese archivo.

 

Imaginemos que tenemos un archivo rc como este:


php
  1. Imagen1 RCDATA "Imagen1.png"
  2. Imagen2 RCDATA "Imagen2.jpg"

Y lo compilamos como un archivo.res para incluir en nuestro ejecutable.

 

Para extraer las imágenes podemos crear los archivos correspondientes o cargarlas directamente de memoria sin necesidad de un archivo intermedio. La forma de actuar con al API sería así:


delphi
  1. uses
  2. Winapi.Windows, Winapi.ActiveX;
  3.  
  4.  
  5. // GDI+ Flat API...
  6. function GdiplusStartup(var GdiToken: ULONG_PTR; Startup, Output: PBYTE): Cardinal; stdcall external 'gdiplus';
  7. procedure GdiplusShutdown(GdiToken: ULONG_PTR); stdcall external 'gdiplus';
  8. function GdipCreateHBITMAPFromBitmap(GBitmap: THANDLE; var hBitmap: HBITMAP; BKColor: DWORD): DWORD; stdcall external 'gdiplus';
  9. function GdipCreateBitmapFromStream(stream: ISTREAM; var GBitmap: THANDLE): Cardinal; stdcall external 'gdiplus';
  10. function GdipDisposeImage(image: THANDLE): Cardinal; stdcall external 'gdiplus';
  11.  
  12. type
  13. TGdiplusStartupInput = record
  14. GdiplusVersion: UINT32;
  15. DebugEventCallback: Pointer;
  16. SuppressBackgroundThread: BOOL;
  17. SuppressExternalCodecs: BOOL;
  18. end;
  19.  
  20.  
  21. implementation
  22. {$R MiArchivo.res}
  23.  
  24. function CreateHBITMAPFromRCDATAResurce(FileName: PWCHAR):HBITMAP;
  25. const
  26. RT_RCDATAW: PWCHAR = MakeIntResourceW(10);
  27. var
  28. Res: HRSRC;
  29. Size: DWORD;
  30. hMem: HGLOBAL;
  31. pImage: Pointer;
  32. GBitmap: THANDLE;
  33. Stream: IStream;
  34. gdiplusToken: ULONG_PTR;
  35. GdiPlusStartupInput: TGdiplusStartupInput;
  36. begin
  37. // Inicializamos GDI+.
  38. GdiPlusStartupInput.GdiplusVersion:= 1; GdiPlusStartupInput.DebugEventCallback:= nil;
  39. GdiPlusStartupInput.SuppressBackgroundThread:= FALSE; GdiPlusStartupInput.SuppressExternalCodecs:= FALSE;
  40. GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil);
  41.  
  42. Result:= 0;
  43. Res:= FindResourceW(0, FileName, RT_RCDATAW);//MAKEINTRESOURCEW(10));
  44. if Res <> 0 then
  45. begin
  46. Size:= SizeofResource(0, Res);
  47. hMem:= GlobalAlloc(GMEM_MOVEABLE, Size);
  48. pImage:= GlobalLock(hMem);
  49. CopyMemory(pImage, LockResource(LoadResource(0, Res)), Size);
  50. GlobalUnlock(hMem);
  51. CreateStreamOnHGlobal(hMem, true, Stream);
  52. GdipCreateBitmapFromStream(Stream, GBitmap);
  53. GdipCreateHBITMAPFromBitmap(GBitmap, Result, 0);
  54. GdipDisposeImage(GBitmap);
  55. GlobalFree(hMem);
  56. end;
  57. // Shutdown GDI+
  58. GdiplusShutdown(gdiplusToken);
  59. end;

Y un ejemplo de uso:


delphi
  1. begin
  2. Image1.Picture.Bitmap.Handle:= CreateHBITMAPFromRCDATAResurce('Imagen1');
  3. end;

El ejemplo está desarrollado con Berlin pero funciona en delphi7

 

¿Por qué usar la API pura y GDI+ Flat? Para economizar recursos y tamaño del ejecutable cuando eso sea lo que prime.

 

 

 

Saludos.


  • 1

#2 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.839 mensajes
  • LocationMadrid - España

Escrito 02 enero 2017 - 11:30

El mismo truco en C/C++:
 

cpp
  1. #include <windows.h>
  2.  
  3. #pragma link "Gdiplus.lib"
  4. #pragma resource "MiArchivo.res"
  5.  
  6. extern "C" {
  7. DWORD WINAPI GdiplusStartup(ULONG_PTR *hToken, void *input, void *Output);
  8. void WINAPI GdiplusShutdown(ULONG_PTR token);
  9. DWORD WINAPI GdipCreateBitmapFromHBITMAP(HBITMAP hBmp, HPALETTE hPal, HANDLE* GBitmap);
  10. DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE Bmp, HBITMAP* hBmp, DWORD BKColor);
  11. DWORD WINAPI GdipCreateFromHDC(HDC hDC, HANDLE* hGraphics);
  12. DWORD WINAPI GdipDisposeImage(HANDLE hImage);
  13. DWORD WINAPI GdipTranslateWorldTransform(HANDLE hGraphics, float sx, float sy, DWORD Order);
  14. DWORD WINAPI GdipRotateWorldTransform(HANDLE hGraphics, float Angle, DWORD Order);
  15. DWORD WINAPI GdipDrawImage(HANDLE hGraphics, HANDLE hImage, float sx, float sy);
  16. DWORD WINAPI GdipDeleteGraphics(HANDLE hGraphics);
  17. DWORD WINAPI GdipCreateBitmapFromFile(WCHAR* filename, HANDLE* bitmap);
  18. DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE bitmap, HBITMAP* hBitmap, DWORD BKColor);
  19. //DWORD WINAPI GdipCreateBitmapFromResource(HINSTANCE hInstance, WCHAR* lpBitmapName, HANDLE* GBitmap);
  20. DWORD WINAPI GdipCreateBitmapFromStream(IStream* stream, HANDLE* GBitmap);
  21.  
  22.  
  23. DWORD WINAPI GdipImageRotateFlip(HANDLE hImage, DWORD rfType);
  24. }
  25.  
  26. TForm1 *Form1;
  27.  
  28. typedef struct {
  29. UINT32 GdiplusVersion;
  30. PVOID DebugEventCallback; //DebugEventProc
  31. BOOL SuppressBackgroundThread;
  32. BOOL SuppressExternalCodecs;
  33. } GdiplusStartupInput;
  34.  
  35. HBITMAP CreateHBITMAPFromRCDATAResurce(PWCHAR FileName)
  36. {
  37. PWCHAR RT_RCDATAW = MAKEINTRESOURCEW(10);
  38. HBITMAP hBitmap = 0;
  39. HANDLE GBitmap = 0;
  40. IStream* Stream;
  41. ULONG_PTR gdiplusToken;
  42. GdiplusStartupInput gdiplusStartupInput = {0};
  43. gdiplusStartupInput.GdiplusVersion = 1;
  44. if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL)) return 0;
  45.  
  46. HRSRC Res = FindResourceW(0, FileName, RT_RCDATAW);//MAKEINTRESOURCEW(10));
  47. if(Res){
  48. DWORD Size = SizeofResource(0, Res);
  49. HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, Size);
  50. LPVOID pImage = ::GlobalLock(hMem);
  51. CopyMemory(pImage, LockResource(LoadResource(0, Res)), Size);
  52. ::GlobalUnlock(hMem);
  53. ::CreateStreamOnHGlobal(hMem, true, &Stream);
  54. GdipCreateBitmapFromStream(Stream, &GBitmap);
  55. GdipCreateHBITMAPFromBitmap(GBitmap, &hBitmap, 0);
  56. GdipDisposeImage(GBitmap);
  57. //GlobalFree(hMem);
  58. Stream->Release();
  59. }
  60.  
  61. //shutdown GDI+
  62. GdiplusShutdown(gdiplusToken);
  63.  
  64. return hBitmap;
  65. }

 Y la forma de uso:

cpp
  1. Image1->Picture->Bitmap->Handle = CreateHBITMAPFromRCDATAResurce(L"Imagen1");


Saludos.
  • 1

#3 ELKurgan

ELKurgan

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 543 mensajes
  • LocationEspaña

Escrito 03 enero 2017 - 12:31

Muy buen código. como siempre

 

Gracias por el aporte


  • 0