From 037d8e19dcfec8c387ff258e496772ea8ef32425 Mon Sep 17 00:00:00 2001 From: neoarc Date: Tue, 4 Sep 2018 12:25:39 +0900 Subject: [PATCH 1/2] Implemented Image.Load for Windows using GDI+ --- Source/Image.cc | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ Source/Image.h | 2 ++ 2 files changed, 89 insertions(+) diff --git a/Source/Image.cc b/Source/Image.cc index 8d3f461..27af017 100644 --- a/Source/Image.cc +++ b/Source/Image.cc @@ -20,6 +20,15 @@ using std::memcpy; using std::memcmp; +#ifdef ROBOT_OS_WIN + + #include + #include + #include + #pragma comment(lib, "gdiplus.lib") + +#endif + ROBOT_NS_BEGIN @@ -153,6 +162,84 @@ void Image::Destroy (void) //////////////////////////////////////////////////////////////////////////////// +bool Image::Load(const char *filename) +{ +#ifdef ROBOT_OS_WIN + + auto hwnd = GetDesktopWindow(); + auto hDesktopDC = GetDC(hwnd); + auto hMemoryDC = ::CreateCompatibleDC(hDesktopDC); + + // For convert filename to WCHAR + int size = 0; + + // Compute size of resulting string + size = MultiByteToWideChar(CP_UTF8, 0, filename, (int)strlen(filename), nullptr, 0); + + std::wstring filenameW(size, 0); + + // Convert UTF8 string to wide-string + size = MultiByteToWideChar(CP_UTF8, 0, filename, (int)strlen(filename), &filenameW[0], size); + + // Initialize gdi+ + Gdiplus::GdiplusStartupInput si; + ULONG_PTR gdiplusToken; + GdiplusStartup(&gdiplusToken, &si, NULL); + + // Load image file + Gdiplus::Image* pGdiImage = new Gdiplus::Image(filenameW.c_str()); + + // Converting to bitmap + HBITMAP hBitmap; + Gdiplus::Bitmap* pGdiBitmap = static_cast(pGdiImage); + pGdiBitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0), &hBitmap); + + Create(pGdiImage->GetWidth(), pGdiImage->GetHeight()); + + bool bFail = true; + HDC hCompatibleDC = nullptr; + HGDIOBJ hOldObj = nullptr; + do + { + HDC hCompatibleDC = CreateCompatibleDC(hMemoryDC); + if (!hCompatibleDC) + break; + + BITMAPINFO bmi; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biBitCount = 0; + if (!GetDIBits(hCompatibleDC, hBitmap, 0, 0, nullptr, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS)) + break; + + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biHeight = -bmi.bmiHeader.biHeight; + + hOldObj = SelectObject(hCompatibleDC, hBitmap); + if (!(GetDIBits(hCompatibleDC, hBitmap, 0, -bmi.bmiHeader.biHeight, GetData(), (LPBITMAPINFO)&bmi, DIB_RGB_COLORS))) + break; + + bFail = false; + } while (false); + + if (hOldObj) + SelectObject(hCompatibleDC, hOldObj); + DeleteDC(hCompatibleDC); + + // Shutdown gdi+ + delete pGdiImage; + Gdiplus::GdiplusShutdown(gdiplusToken); + + return (bFail == false); + +#endif + + // #TODO implement function for MacOS & Linux + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// + Color Image::GetPixel (const Point& point) const { return GetPixel (point.X, point.Y); diff --git a/Source/Image.h b/Source/Image.h index cbc8609..f104f0b 100644 --- a/Source/Image.h +++ b/Source/Image.h @@ -46,6 +46,8 @@ class ROBOT_EXPORT Image bool Create (uint16 w, uint16 h); void Destroy (void); + bool Load (const char* filename); + uint16 GetWidth (void) const { return mWidth; } uint16 GetHeight (void) const { return mHeight; } uint32 GetLength (void) const { return mLength; } From 4fde3e00778f641c78e4a7d0babb38b7e99171e4 Mon Sep 17 00:00:00 2001 From: neoarc Date: Mon, 17 Sep 2018 17:30:28 +0900 Subject: [PATCH 2/2] Fixed crash bug in Image.Load --- Source/Image.cc | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/Source/Image.cc b/Source/Image.cc index 27af017..b50eba4 100644 --- a/Source/Image.cc +++ b/Source/Image.cc @@ -173,12 +173,9 @@ bool Image::Load(const char *filename) // For convert filename to WCHAR int size = 0; - // Compute size of resulting string + // Convert UTF8 string to wide-string size = MultiByteToWideChar(CP_UTF8, 0, filename, (int)strlen(filename), nullptr, 0); - std::wstring filenameW(size, 0); - - // Convert UTF8 string to wide-string size = MultiByteToWideChar(CP_UTF8, 0, filename, (int)strlen(filename), &filenameW[0], size); // Initialize gdi+ @@ -194,18 +191,29 @@ bool Image::Load(const char *filename) Gdiplus::Bitmap* pGdiBitmap = static_cast(pGdiImage); pGdiBitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0), &hBitmap); - Create(pGdiImage->GetWidth(), pGdiImage->GetHeight()); + RESET(*this); + if (Create(pGdiImage->GetWidth(), pGdiImage->GetHeight()) == false) + { + delete pGdiImage; + Gdiplus::GdiplusShutdown(gdiplusToken); + return false; + } bool bFail = true; HDC hCompatibleDC = nullptr; HGDIOBJ hOldObj = nullptr; do { - HDC hCompatibleDC = CreateCompatibleDC(hMemoryDC); + struct BITMAPINFO3 + { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[260]; + } bmi; + + hCompatibleDC = CreateCompatibleDC(hMemoryDC); if (!hCompatibleDC) - break; - - BITMAPINFO bmi; + break; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biBitCount = 0; if (!GetDIBits(hCompatibleDC, hBitmap, 0, 0, nullptr, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS)) @@ -223,10 +231,14 @@ bool Image::Load(const char *filename) if (hOldObj) SelectObject(hCompatibleDC, hOldObj); - DeleteDC(hCompatibleDC); + if (hCompatibleDC) + DeleteDC(hCompatibleDC); + if (hMemoryDC) + DeleteDC(hMemoryDC); + if (pGdiImage) + delete pGdiImage; // Shutdown gdi+ - delete pGdiImage; Gdiplus::GdiplusShutdown(gdiplusToken); return (bFail == false);