25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

139 lines
2.9 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #if defined USE_GDIPLUS
  14. #include <algorithm>
  15. using namespace std;
  16. #include <windows.h>
  17. #include <gdiplus.h>
  18. #include "core.h"
  19. #include "../../image/image-private.h"
  20. namespace lol
  21. {
  22. /*
  23. * Image implementation class
  24. */
  25. DECLARE_IMAGE_LOADER(GdiPlusImageData, 100)
  26. {
  27. public:
  28. virtual bool Open(char const *);
  29. virtual bool Close();
  30. virtual void *GetData() const;
  31. private:
  32. Gdiplus::Bitmap *bitmap;
  33. Gdiplus::BitmapData bdata;
  34. };
  35. /*
  36. * Public Image class
  37. */
  38. bool GdiPlusImageData::Open(char const *path)
  39. {
  40. size_t len;
  41. len = mbstowcs(NULL, path, 0);
  42. wchar_t *wpath = new wchar_t[len + 1];
  43. if (mbstowcs(wpath, path, len + 1) == (size_t)-1)
  44. {
  45. #if !LOL_RELEASE
  46. Log::Error("invalid image name %s\n", path);
  47. #endif
  48. delete[] wpath;
  49. return false;
  50. }
  51. ULONG_PTR token;
  52. Gdiplus::GdiplusStartupInput input;
  53. Gdiplus::GdiplusStartup(&token, &input, NULL);
  54. for (wchar_t const *wname = wpath; *wname; wname++)
  55. if ((bitmap = Gdiplus::Bitmap::FromFile(wname, 0)))
  56. break;
  57. delete[] wpath;
  58. if (!bitmap)
  59. {
  60. #if !LOL_RELEASE
  61. Log::Error("could not load %s\n", path);
  62. #endif
  63. return false;
  64. }
  65. if (bitmap->GetLastStatus() != Gdiplus::Ok)
  66. {
  67. #if !LOL_RELEASE
  68. Log::Error("error %d loading %s\n",
  69. (unsigned)bitmap->GetLastStatus(), path);
  70. #endif
  71. delete bitmap;
  72. return false;
  73. }
  74. size = ivec2(bitmap->GetWidth(), bitmap->GetHeight());
  75. format = Image::FORMAT_RGBA;
  76. Gdiplus::Rect rect(0, 0, size.x, size.y);
  77. if(bitmap->LockBits(&rect, Gdiplus::ImageLockModeRead,
  78. PixelFormat32bppARGB, &bdata) != Gdiplus::Ok)
  79. {
  80. #if !LOL_RELEASE
  81. Log::Error("could not lock bits in %s\n", path);
  82. #endif
  83. delete bitmap;
  84. return false;
  85. }
  86. /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
  87. * know about ARGB, only RGBA. So we swap bytes. We could also fix
  88. * this in the shader. */
  89. uint8_t *p = static_cast<uint8_t *>(bdata.Scan0);
  90. for (int y = 0; y < size.y; y++)
  91. for (int x = 0; x < size.x; x++)
  92. {
  93. uint8_t tmp = p[2];
  94. p[2] = p[0];
  95. p[0] = tmp;
  96. p += 4;
  97. }
  98. return true;
  99. }
  100. bool GdiPlusImageData::Close()
  101. {
  102. bitmap->UnlockBits(&bdata);
  103. delete bitmap;
  104. return true;
  105. }
  106. void * GdiPlusImageData::GetData() const
  107. {
  108. return bdata.Scan0;
  109. }
  110. } /* namespace lol */
  111. #endif /* defined USE_GDIPLUS */