77#include < shlwapi.h>
88#include < gdiplus.h>
99#include < thumbcache.h>
10+ #include < memory>
1011
1112#pragma comment(lib, "Ole32.lib")
1213#pragma comment(lib, "Shlwapi.lib")
@@ -65,26 +66,27 @@ HRESULT GetThumbnailImage(const std::wstring& filePath, int size, HBITMAP& hBitm
6566void SaveBitmapAsPNG (HBITMAP hBitmap, const std::wstring& outputPath) {
6667 GdiplusStartupInput gdiplusStartupInput;
6768 ULONG_PTR gdiplusToken;
68- GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, nullptr );
69+ if ( GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, nullptr ) != Ok) return ;
6970
7071 BITMAP bm;
71- GetObject (hBitmap, sizeof (BITMAP), &bm);
72+ if (! GetObject (hBitmap, sizeof (BITMAP), &bm)) return ;
7273
7374 Bitmap bitmap (bm.bmWidth , bm.bmHeight , PixelFormat32bppARGB);
74-
75- Gdiplus::BitmapData bmpData;
75+ BitmapData bmpData;
7676 Rect rect (0 , 0 , bm.bmWidth , bm.bmHeight );
7777
7878 if (bitmap.LockBits (&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bmpData) == Ok) {
79- int bytesPerPixel = 4 ;
80- BYTE* srcData = (BYTE*)bm.bmBits ;
81- BYTE* destData = (BYTE*)bmpData.Scan0 ;
82-
83- for (int y = 0 ; y < bm.bmHeight ; y++) {
84- BYTE* srcRow = srcData + (bm.bmHeight - 1 - y) * bm.bmWidth * bytesPerPixel;
85- BYTE* destRow = destData + y * bmpData.Stride ;
86- memcpy (destRow, srcRow, bm.bmWidth * bytesPerPixel);
87- }
79+ BITMAPINFO bmi = {};
80+ bmi.bmiHeader .biSize = sizeof (BITMAPINFOHEADER);
81+ bmi.bmiHeader .biWidth = bm.bmWidth ;
82+ bmi.bmiHeader .biHeight = -bm.bmHeight ;
83+ bmi.bmiHeader .biPlanes = 1 ;
84+ bmi.bmiHeader .biBitCount = 32 ;
85+ bmi.bmiHeader .biCompression = BI_RGB;
86+
87+ HDC hdc = GetDC (nullptr );
88+ GetDIBits (hdc, hBitmap, 0 , bm.bmHeight , bmpData.Scan0 , &bmi, DIB_RGB_COLORS);
89+ ReleaseDC (nullptr , hdc);
8890
8991 bitmap.UnlockBits (&bmpData);
9092 }
@@ -109,9 +111,16 @@ void getImage(const Napi::CallbackInfo& info, bool useThumbnail) {
109111
110112 GdiplusStartupInput gdiplusStartupInput;
111113 ULONG_PTR gdiplusToken;
112- GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, nullptr );
114+ if (GdiplusStartup (&gdiplusToken, &gdiplusStartupInput, nullptr ) != Ok) {
115+ Napi::Error::New (env, " Failed to initialize GDI+" ).ThrowAsJavaScriptException ();
116+ return ;
117+ }
113118
114- CoInitializeEx (nullptr , COINIT_APARTMENTTHREADED);
119+ if (FAILED (CoInitializeEx (nullptr , COINIT_APARTMENTTHREADED))) {
120+ GdiplusShutdown (gdiplusToken);
121+ Napi::Error::New (env, " Failed to initialize COM" ).ThrowAsJavaScriptException ();
122+ return ;
123+ }
115124
116125 HBITMAP hBitmap = nullptr ;
117126 HRESULT hr = useThumbnail
@@ -122,7 +131,7 @@ void getImage(const Napi::CallbackInfo& info, bool useThumbnail) {
122131 SaveBitmapAsPNG (hBitmap, outputPath);
123132 DeleteObject (hBitmap);
124133 } else {
125- Napi::Error::New (env, " Failed to retrieve image. " ).ThrowAsJavaScriptException ();
134+ Napi::Error::New (env, " Failed to retrieve image" ).ThrowAsJavaScriptException ();
126135 }
127136
128137 CoUninitialize ();
@@ -162,4 +171,4 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
162171
163172NODE_API_MODULE (winicon, Init)
164173
165- #endif
174+ #endif
0 commit comments