From 4875aa88b68f0a9434961e9039a9a3733fd48429 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 23 Feb 2022 17:35:42 +0100 Subject: [PATCH] Tools: [skip ci] in thumbnail provider replace CxImage library with Win32 API --- src/Tools/thumbs/FCStdExtractor.cpp | 146 ++++++- src/Tools/thumbs/FCThumbs.sln | 61 +-- src/Tools/thumbs/FCThumbs.vcxproj | 582 ++++++++++++++++++++++++++++ 3 files changed, 739 insertions(+), 50 deletions(-) create mode 100644 src/Tools/thumbs/FCThumbs.vcxproj diff --git a/src/Tools/thumbs/FCStdExtractor.cpp b/src/Tools/thumbs/FCStdExtractor.cpp index 227af0295d..cf2b228f39 100644 --- a/src/Tools/thumbs/FCStdExtractor.cpp +++ b/src/Tools/thumbs/FCStdExtractor.cpp @@ -32,8 +32,132 @@ #include #include #include -#include -#include +#include +#include +#pragma comment(lib, "WindowsCodecs.lib") + + // The functions + // * CreateStreamOnResource + // * LoadBitmapFromStream + // * CreateHBITMAP + // are taken from https://faithlife.codes/blog/2008/09/displaying_a_splash_screen_with_c_part_i/ + // The code is released under an MIT-style license + + // Creates a stream object initialized with the data from an executable resource. +IStream* CreateStreamOnResource(void* buffer, size_t length) +{ + // initialize return value + IStream* ipStream = NULL; + + // allocate memory to hold the resource data + HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, length); + if (hgblResourceData == NULL) + goto Return; + + // get a pointer to the allocated memory + LPVOID pvResourceData = GlobalLock(hgblResourceData); + if (pvResourceData == NULL) + goto FreeData; + + // copy the data from the resource to the new memory block + CopyMemory(pvResourceData, buffer, length); + GlobalUnlock(hgblResourceData); + + // create a stream on the HGLOBAL containing the data + + if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream))) + goto Return; + +FreeData: + // couldn't create stream; free the memory + + GlobalFree(hgblResourceData); + +Return: + // no need to unlock or free the resource + return ipStream; +} + +IWICBitmapSource* LoadBitmapFromStream(IStream* ipImageStream) +{ + // initialize return value + IWICBitmapSource* ipBitmap = NULL; + + // load WIC's PNG decoder + IWICBitmapDecoder* ipDecoder = NULL; + if (FAILED(CoCreateInstance(CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER, __uuidof(ipDecoder), reinterpret_cast(&ipDecoder)))) + goto Return; + + // load the PNG + if (FAILED(ipDecoder->Initialize(ipImageStream, WICDecodeMetadataCacheOnLoad))) + goto ReleaseDecoder; + + // check for the presence of the first frame in the bitmap + UINT nFrameCount = 0; + if (FAILED(ipDecoder->GetFrameCount(&nFrameCount)) || nFrameCount != 1) + goto ReleaseDecoder; + + // load the first frame (i.e., the image) + IWICBitmapFrameDecode* ipFrame = NULL; + if (FAILED(ipDecoder->GetFrame(0, &ipFrame))) + goto ReleaseDecoder; + + // convert the image to 32bpp BGRA format with pre-multiplied alpha + // (it may not be stored in that format natively in the PNG resource, + // but we need this format to create the DIB to use on-screen) + WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, ipFrame, &ipBitmap); + ipFrame->Release(); + +ReleaseDecoder: + ipDecoder->Release(); +Return: + return ipBitmap; +} + +HBITMAP CreateHBITMAP(IWICBitmapSource* ipBitmap) +{ + // initialize return value + HBITMAP hbmp = NULL; + + // get image attributes and check for valid image + UINT width = 0; + UINT height = 0; + if (FAILED(ipBitmap->GetSize(&width, &height)) || width == 0 || height == 0) + goto Return; + + // prepare structure giving bitmap information (negative height indicates a top-down DIB) + BITMAPINFO bminfo; + ZeroMemory(&bminfo, sizeof(bminfo)); + bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bminfo.bmiHeader.biWidth = width; + bminfo.bmiHeader.biHeight = -((LONG)height); + bminfo.bmiHeader.biPlanes = 1; + bminfo.bmiHeader.biBitCount = 32; + bminfo.bmiHeader.biCompression = BI_RGB; + + // create a DIB section that can hold the image + void* pvImageBits = NULL; + HDC hdcScreen = GetDC(NULL); + hbmp = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0); + ReleaseDC(NULL, hdcScreen); + if (hbmp == NULL) + goto Return; + + // extract the image into the HBITMAP + + const UINT cbStride = width * 4; + const UINT cbImage = cbStride * height; + if (FAILED(ipBitmap->CopyPixels(NULL, cbStride, cbImage, static_cast(pvImageBits)))) + { + // couldn't extract image; delete HBITMAP + + DeleteObject(hbmp); + hbmp = NULL; + } + +Return: + return hbmp; +} CComModule _Module; @@ -146,13 +270,17 @@ HRESULT CFCStdExtractor::Extract(HBITMAP* phBmpThumbnail) content.push_back(c); } - // pass the memory buffer to CxImage library to create - // the bitmap handle - CxMemFile mem(&(content[0]),content.size()); - CxImagePNG png; - png.Decode(&mem); - m_hPreview = png.MakeBitmap(); - *phBmpThumbnail = m_hPreview; + // pass the memory buffer to CxImage library to create the bitmap handle + IStream* stream = CreateStreamOnResource(&(content[0]), content.size()); + if (stream) { + IWICBitmapSource* bmpSrc = LoadBitmapFromStream(stream); + stream->Release(); + if (bmpSrc) { + m_hPreview = CreateHBITMAP(bmpSrc); + *phBmpThumbnail = m_hPreview; + bmpSrc->Release(); + } + } } } catch(...) { diff --git a/src/Tools/thumbs/FCThumbs.sln b/src/Tools/thumbs/FCThumbs.sln index 20e56f8da8..9fcb00fda8 100644 --- a/src/Tools/thumbs/FCThumbs.sln +++ b/src/Tools/thumbs/FCThumbs.sln @@ -1,64 +1,43 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CxImage", "..\..\3rdParty\CxImage\CxImage\cximage.vcproj", "{5B09C649-4D91-4960-8FF8-978146E6F7D5}" - ProjectSection(ProjectDependencies) = postProject - {14699290-6210-4450-B397-83DFE7D8CDEC} = {14699290-6210-4450-B397-83DFE7D8CDEC} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FCThumbs", "FCThumbs.vcproj", "{5E406625-AFD6-4849-875F-C5740E98A28E}" - ProjectSection(ProjectDependencies) = postProject - {5B09C649-4D91-4960-8FF8-978146E6F7D5} = {5B09C649-4D91-4960-8FF8-978146E6F7D5} - {14699290-6210-4450-B397-83DFE7D8CDEC} = {14699290-6210-4450-B397-83DFE7D8CDEC} - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7} = {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\3rdParty\CxImage\zlib\zlib.vcproj", "{14699290-6210-4450-B397-83DFE7D8CDEC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "png", "..\..\3rdParty\CxImage\png\png.vcproj", "{70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31410.357 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FCThumbs", "FCThumbs.vcxproj", "{5E406625-AFD6-4849-875F-C5740E98A28E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 Unicode Debug|Win32 = Unicode Debug|Win32 + Unicode Debug|x64 = Unicode Debug|x64 Unicode Release|Win32 = Unicode Release|Win32 + Unicode Release|x64 = Unicode Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Debug|Win32.ActiveCfg = Debug|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Debug|Win32.Build.0 = Debug|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Release|Win32.ActiveCfg = Release|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Release|Win32.Build.0 = Release|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Unicode Debug|Win32.ActiveCfg = Unicode Debug|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Unicode Debug|Win32.Build.0 = Unicode Debug|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Unicode Release|Win32.ActiveCfg = Unicode Release|Win32 - {5B09C649-4D91-4960-8FF8-978146E6F7D5}.Unicode Release|Win32.Build.0 = Unicode Release|Win32 {5E406625-AFD6-4849-875F-C5740E98A28E}.Debug|Win32.ActiveCfg = Debug|Win32 {5E406625-AFD6-4849-875F-C5740E98A28E}.Debug|Win32.Build.0 = Debug|Win32 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Debug|x64.ActiveCfg = Debug|x64 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Debug|x64.Build.0 = Debug|x64 {5E406625-AFD6-4849-875F-C5740E98A28E}.Release|Win32.ActiveCfg = Release|Win32 {5E406625-AFD6-4849-875F-C5740E98A28E}.Release|Win32.Build.0 = Release|Win32 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Release|x64.ActiveCfg = Release|x64 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Release|x64.Build.0 = Release|x64 {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Debug|Win32.ActiveCfg = Debug|Win32 {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Debug|Win32.Build.0 = Debug|Win32 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Debug|x64.ActiveCfg = Debug|x64 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Debug|x64.Build.0 = Debug|x64 {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Release|Win32.ActiveCfg = Release|Win32 {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Release|Win32.Build.0 = Release|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Debug|Win32.ActiveCfg = Debug|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Debug|Win32.Build.0 = Debug|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Release|Win32.ActiveCfg = Release|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Release|Win32.Build.0 = Release|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Unicode Debug|Win32.ActiveCfg = Unicode Debug|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Unicode Debug|Win32.Build.0 = Unicode Debug|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Unicode Release|Win32.ActiveCfg = Unicode Release|Win32 - {14699290-6210-4450-B397-83DFE7D8CDEC}.Unicode Release|Win32.Build.0 = Unicode Release|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Debug|Win32.ActiveCfg = Debug|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Debug|Win32.Build.0 = Debug|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Release|Win32.ActiveCfg = Release|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Release|Win32.Build.0 = Release|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Unicode Debug|Win32.ActiveCfg = Unicode Debug|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Unicode Debug|Win32.Build.0 = Unicode Debug|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Unicode Release|Win32.ActiveCfg = Unicode Release|Win32 - {70C07CD0-5D25-426E-A6FA-C9CDC0847AB7}.Unicode Release|Win32.Build.0 = Unicode Release|Win32 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Release|x64.ActiveCfg = Release|x64 + {5E406625-AFD6-4849-875F-C5740E98A28E}.Unicode Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A0E0D5A0-B2A9-4F06-8772-5B26FF1EC437} + EndGlobalSection EndGlobal diff --git a/src/Tools/thumbs/FCThumbs.vcxproj b/src/Tools/thumbs/FCThumbs.vcxproj new file mode 100644 index 0000000000..4cd2e990aa --- /dev/null +++ b/src/Tools/thumbs/FCThumbs.vcxproj @@ -0,0 +1,582 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5E406625-AFD6-4849-875F-C5740E98A28E} + MFCProj + + + + DynamicLibrary + v142 + false + MultiByte + + + DynamicLibrary + v142 + false + MultiByte + + + DynamicLibrary + v142 + Dynamic + MultiByte + + + DynamicLibrary + v142 + false + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>16.0.31401.40 + + + .\Release\ + .\Release\ + false + + + false + + + .\Debug\ + .\Debug\ + true + + + true + + + + Performing Registration on $(ProjectPath) + regsvr32 /s /c "$(TargetPath)" +echo regsvr32 exec. time > "$(OutDir)regsvr32.trg" + + $(OutDir)regsvr32.trg;%(Outputs) + + + NDEBUG;%(PreprocessorDefinitions) + Win32 + .\Release/FCThumbs.tlb + + + + MaxSpeed + OnlyExplicitInline + ../../;$(ProgramFiles)\Microsoft Platform SDK\Include\atl;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FreeCADBase_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + Use + stdafx.h + .\Release/FCThumbs.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + gdi32.lib;%(AdditionalDependencies) + .\Release/FCThumbs.dll + true + .\FCThumbs.def + .\Release/FCThumbs.pdb + Windows + false + + .\Release/FCThumbs.lib + MachineX86 + + + true + .\Release/FCThumbs.bsc + + + + + Performing Registration on $(ProjectPath) + regsvr32 /s /c "$(TargetPath)" +echo regsvr32 exec. time > "$(OutDir)regsvr32.trg" + + $(OutDir)regsvr32.trg;%(Outputs) + + + NDEBUG;%(PreprocessorDefinitions) + .\Release/FCThumbs.tlb + + + + + MaxSpeed + OnlyExplicitInline + ../../;$(ProgramFiles)\Microsoft Platform SDK\Include\atl;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;FreeCADBase_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + Use + stdafx.h + .\Release/FCThumbs.pch + .\Release/ + .\Release/ + .\Release/ + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + gdi32.lib;zlibstatic.lib;%(AdditionalDependencies) + .\Release/FCThumbs.dll + true + .\FCThumbs.def + .\Release/FCThumbs.pdb + Windows + false + + + .\Release/FCThumbs.lib + + + true + .\Release/FCThumbs.bsc + + + + + Performing Registration on $(ProjectPath) + regsvr32 /s /c "$(TargetPath)" +echo regsvr32 exec. time > "$(OutDir)regsvr32.trg" + + $(OutDir)regsvr32.trg;%(Outputs) + + + _DEBUG;%(PreprocessorDefinitions) + Win32 + .\Debug/FCThumbs.tlb + + + + Disabled + ../../;$(ProgramFiles)\Microsoft Platform SDK\Include\atl;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FreeCADBase_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Use + stdafx.h + .\Debug/FCThumbs.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + gdi32.lib;%(AdditionalDependencies) + .\Debug/FCThumbs.dll + true + .\FCThumbs.def + true + .\Debug/FCThumbs.pdb + Windows + false + + .\Debug/FCThumbs.lib + MachineX86 + + + true + .\Debug/FCThumbs.bsc + + + + + Performing Registration on $(ProjectPath) + regsvr32 /s /c "$(TargetPath)" +echo regsvr32 exec. time > "$(OutDir)regsvr32.trg" + + $(OutDir)regsvr32.trg;%(Outputs) + + + _DEBUG;%(PreprocessorDefinitions) + .\Debug/FCThumbs.tlb + + + + + Disabled + ../../;$(ProgramFiles)\Microsoft Platform SDK\Include\atl;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;FreeCADBase_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Use + stdafx.h + .\Debug/FCThumbs.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + gdi32.lib;zlibstatic.lib;%(AdditionalDependencies) + .\Debug/FCThumbs.dll + true + .\FCThumbs.def + true + .\Debug/FCThumbs.pdb + Windows + false + + + .\Debug/FCThumbs.lib + + + true + .\Debug/FCThumbs.bsc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + Win32 + true + true + ./ThumbFCStd.tlb + ./ThumbFCStd.tlb + ThumbFCStd_i.h + ThumbFCStd_i.h + ThumbFCStd_i.c + ThumbFCStd_i.c + Win32 + true + true + ./ThumbFCStd.tlb + ./ThumbFCStd.tlb + ThumbFCStd_i.h + ThumbFCStd_i.h + ThumbFCStd_i.c + ThumbFCStd_i.c + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file