diff options
Diffstat (limited to 'lib/Thumbnail')
-rw-r--r-- | lib/Thumbnail/Thumbnail.vcxproj | 236 | ||||
-rw-r--r-- | lib/Thumbnail/thumbnail.cpp | 486 | ||||
-rw-r--r-- | lib/Thumbnail/thumbnail.h | 85 |
3 files changed, 0 insertions, 807 deletions
diff --git a/lib/Thumbnail/Thumbnail.vcxproj b/lib/Thumbnail/Thumbnail.vcxproj deleted file mode 100644 index a98aadab..00000000 --- a/lib/Thumbnail/Thumbnail.vcxproj +++ /dev/null @@ -1,236 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{70394AEF-5897-4911-AFA1-82EAF0581EFA}</ProjectGuid> - <RootNamespace>ShadowDll</RootNamespace> - <Keyword>Win32Proj</Keyword> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <WholeProgramOptimization>true</WholeProgramOptimization> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <CharacterSet>Unicode</CharacterSet> - <PlatformToolset>v120_xp</PlatformToolset> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup> - <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> - <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\</OutDir> - <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">OBJ\$(ProjectName)_$(Configuration)_$(Platform)\</IntDir> - <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Thumbnail_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Thumbnail_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Thumbnail_$(Platform)</TargetName> - <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Thumbnail_$(Platform)</TargetName> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;ZEN_WIN;_DEBUG;_WINDOWS;_USRDLL;THUMBNAIL_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>false</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>EditAndContinue</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>true</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> - <SubSystem>Windows</SubSystem> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX86</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <Midl> - <TargetEnvironment>X64</TargetEnvironment> - </Midl> - <ClCompile> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;_DEBUG;_WINDOWS;_USRDLL;THUMBNAIL_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>false</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> - <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <SmallerTypeCheck>true</SmallerTypeCheck> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile> - <SubSystem>Windows</SubSystem> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX64</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;THUMBNAIL_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <SubSystem>Windows</SubSystem> - <OptimizeReferences>true</OptimizeReferences> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX86</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <BuildLog> - <Path>$(IntDir)Build.html</Path> - </BuildLog> - <Midl> - <TargetEnvironment>X64</TargetEnvironment> - </Midl> - <ClCompile> - <Optimization>MaxSpeed</Optimization> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>ZEN_WIN;WXINTL_NO_GETTEXT_MACRO;NDEBUG;_WINDOWS;_USRDLL;THUMBNAIL_DLL_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - <FunctionLevelLinking>true</FunctionLevelLinking> - <PrecompiledHeader> - </PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <SuppressStartupBanner>true</SuppressStartupBanner> - <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> - <DisableSpecificWarnings>4100;4996</DisableSpecificWarnings> - <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> - <AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories> - <MultiProcessorCompilation>true</MultiProcessorCompilation> - </ClCompile> - <Link> - <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> - <SuppressStartupBanner>true</SuppressStartupBanner> - <GenerateDebugInformation>true</GenerateDebugInformation> - <SubSystem>Windows</SubSystem> - <OptimizeReferences>true</OptimizeReferences> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration> - <ProfileGuidedDatabase> - </ProfileGuidedDatabase> - <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary> - <TargetMachine>MachineX64</TargetMachine> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" /> - <ClCompile Include="thumbnail.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="thumbnail.h" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project>
\ No newline at end of file diff --git a/lib/Thumbnail/thumbnail.cpp b/lib/Thumbnail/thumbnail.cpp deleted file mode 100644 index 53c30bc3..00000000 --- a/lib/Thumbnail/thumbnail.cpp +++ /dev/null @@ -1,486 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#include "thumbnail.h" -#include <algorithm> -#include <string> - -#define WIN32_LEAN_AND_MEAN -#include <zen/win.h> -#include <zen/win_ver.h> -#include <zen/sys_error.h> - -#define STRICT_TYPED_ITEMIDS //better type safety for IDLists -#include <Shlobj.h> - -#include <Shellapi.h> -#include <CommonControls.h> - -#include <zen/com_error.h> -#include <zen/com_ptr.h> -#include <zen/string_tools.h> -#include <zen/scope_guard.h> -#include <zen/basic_math.h> -//#include <zen/perf.h> - -using namespace zen; - - -namespace -{ -thumb::ImageData* allocImageData(int width, int height) //throw SysError; return value always bound! -{ - ZEN_COM_ASSERT(width >= 0 && height >= 0); //throw SysError - - std::unique_ptr<thumb::ImageData> idata = make_unique<thumb::ImageData>(); - - idata->width = width; - idata->height = height; - idata->rgb = new unsigned char[width * height * 4]; - idata->alpha = idata->rgb + width * height * 3; - - return idata.release(); -} - -void releaseImageData_impl(const thumb::ImageData* id) -{ - if (id) - { - delete [] id->rgb; - delete id; - } -} - - -//caller takes ownership! -HICON createIconFromBitmap(HBITMAP bitmap) //throw SysError -{ - BITMAP bmpInfo = {}; - ZEN_COM_ASSERT(::GetObject(bitmap, //__in HGDIOBJ hgdiobj, - sizeof(bmpInfo), //__in int cbBuffer, - &bmpInfo)); //__out LPVOID lpvObject - //no documented extended error info - - HDC hScreenDC = ::GetDC(nullptr); - ZEN_COM_ASSERT(hScreenDC); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::ReleaseDC(nullptr, hScreenDC)); - - HBITMAP bitmapMask = ::CreateCompatibleBitmap(hScreenDC, bmpInfo.bmWidth, bmpInfo.bmHeight); - ZEN_COM_ASSERT(bitmapMask); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteObject(bitmapMask)); - - ICONINFO iconInfo = {}; - iconInfo.fIcon = true; - iconInfo.hbmColor = bitmap; - iconInfo.hbmMask = bitmapMask; - - HICON result = ::CreateIconIndirect(&iconInfo); - if (!result) throw SysError(formatSystemError(L"CreateIconIndirect", getLastError())); - return result; -} - - -//caller takes ownership! -thumb::ImageData* convertToImageData(HBITMAP bmp) //throw SysError -{ - //GetDIBits ???? - - BITMAP bmpInfo = {}; - ZEN_COM_ASSERT(::GetObject(bmp, //__in HGDIOBJ hgdiobj, - sizeof(BITMAP), //__in int cbBuffer, - &bmpInfo)); //__out LPVOID lpvObject - - HDC hScreenDC = ::GetDC(nullptr); - ZEN_COM_ASSERT(hScreenDC); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::ReleaseDC(nullptr, hScreenDC)); - - //32-bit RGB with alpha channel support - BITMAPV5HEADER bi = {}; - bi.bV5Size = sizeof(bi); - bi.bV5Width = bmpInfo.bmWidth; - bi.bV5Height = -bmpInfo.bmHeight; //negative for top left origin - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5AlphaMask = 0xFF000000; - bi.bV5RedMask = 0x00FF0000; - bi.bV5GreenMask = 0x0000FF00; - bi.bV5BlueMask = 0x000000FF; - unsigned char* bitsRgbBmp = nullptr; - - HBITMAP rgbBmp = ::CreateDIBSection(hScreenDC, //_In_ HDC hdc, - reinterpret_cast<const BITMAPINFO*>(&bi), //_In_ const BITMAPINFO *pbmi, - DIB_RGB_COLORS, //_In_ UINT iUsage, - reinterpret_cast<VOID**>(&bitsRgbBmp), //_Out_ VOID **ppvBits, - nullptr, //_In_ HANDLE hSection, - 0); //_In_ DWORD dwOffset - ZEN_COM_ASSERT(rgbBmp); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteObject(rgbBmp);); - ZEN_COM_ASSERT(bitsRgbBmp); //check after rgbBmp is owned by us - - HDC memDCSrc = ::CreateCompatibleDC(hScreenDC); - ZEN_COM_ASSERT(memDCSrc); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteDC(memDCSrc)); - - HDC memDCTrg = ::CreateCompatibleDC(hScreenDC); - ZEN_COM_ASSERT(memDCTrg); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteDC(memDCTrg)); - - HGDIOBJ hgdiSrcOld = ::SelectObject(memDCSrc, bmp); - ZEN_COM_ASSERT(hgdiSrcOld); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::SelectObject(memDCSrc, hgdiSrcOld)); - - HGDIOBJ hgdiTrgOld = ::SelectObject(memDCTrg, rgbBmp); - ZEN_COM_ASSERT(hgdiTrgOld); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::SelectObject(memDCTrg, hgdiTrgOld)); - - if (!::BitBlt(memDCTrg, //_In_ HDC hdcDest, - 0, //_In_ int nXDest, - 0, //_In_ int nYDest, - bmpInfo.bmWidth, //_In_ int nWidth, - bmpInfo.bmHeight, //_In_ int nHeight, - memDCSrc, //_In_ HDC hdcSrc, - 0, //_In_ int nXSrc, - 0, //_In_ int nYSrc, - SRCCOPY)) //_In_ DWORD dwRop - throw SysError(formatSystemError(L"BitBlt", getLastError())); - - //CreateDIBSection: "Access to the bitmap must be synchronized. [...]. This applies to any use of the pointer to the bitmap bit values." - /*bool rv = */ - ::GdiFlush(); - - thumb::ImageData* imgOut = allocImageData(bmpInfo.bmWidth, bmpInfo.bmHeight); //throw SysError - ScopeGuard guardImgData = zen::makeGuard([&] { releaseImageData_impl(imgOut); }); - - unsigned char* rgbPtr = imgOut->rgb; - unsigned char* alphaPtr = imgOut->alpha; - - for (int i = 0; i < bmpInfo.bmWidth * bmpInfo.bmHeight; ++i) - { - unsigned char b = *bitsRgbBmp++; - unsigned char g = *bitsRgbBmp++; - unsigned char r = *bitsRgbBmp++; - unsigned char a = *bitsRgbBmp++; - - *rgbPtr++ = r; - *rgbPtr++ = g; - *rgbPtr++ = b; - *alphaPtr++ = a; - } - - guardImgData.dismiss(); - return imgOut; -} - - -//caller takes ownership! -const thumb::ImageData* getThumbnail_impl(const wchar_t* filename, int requestedSize) //throw SysError -{ - const std::wstring filenameStr(filename); - - ComPtr<IShellFolder> desktopFolder; - ZEN_COM_CHECK(::SHGetDesktopFolder(desktopFolder.init())); //throw SysError - ZEN_COM_ASSERT(desktopFolder); //throw SysError -> better safe than sorry? - - PIDLIST_RELATIVE pidlFolder = nullptr; - { - std::wstring pathName = beforeLast(filenameStr, L'\\'); - ZEN_COM_CHECK(desktopFolder->ParseDisplayName(nullptr, // [in] HWND hwnd, - nullptr, // [in] IBindCtx *pbc, - const_cast<LPWSTR>(pathName.c_str()), // [in] LPWSTR pszDisplayName, - nullptr, // [out] ULONG *pchEaten, - &pidlFolder, // [out] PIDLIST_RELATIVE* ppidl, - nullptr)); // [in, out] ULONG *pdwAttributes - } - ZEN_COM_ASSERT(pidlFolder); - ZEN_ON_SCOPE_EXIT(::ILFree(pidlFolder)); //older version: ::CoTaskMemFree - - ComPtr<IShellFolder> imageFolder; - ZEN_COM_CHECK(desktopFolder->BindToObject(pidlFolder, // [in] PCUIDLIST_RELATIVE pidl, - nullptr, // [in] IBindCtx *pbc, - IID_PPV_ARGS(imageFolder.init()))); - ZEN_COM_ASSERT(imageFolder); - - PIDLIST_RELATIVE pidImage = nullptr; - { - std::wstring shortName = afterLast(filenameStr, L'\\'); - ZEN_COM_CHECK(imageFolder->ParseDisplayName(nullptr, // [in] HWND hwnd, - nullptr, // [in] IBindCtx *pbc, - const_cast<LPWSTR>(shortName.c_str()), // [in] LPWSTR pszDisplayName, - nullptr, // [out] ULONG *pchEaten, - &pidImage, // [out] PIDLIST_RELATIVE *ppidl, - nullptr)); // [in, out] ULONG *pdwAttributes - } - ZEN_COM_ASSERT(pidImage); - ZEN_ON_SCOPE_EXIT(::ILFree(pidImage)); //older version: ::CoTaskMemFree - - ComPtr<IExtractImage> extractImage; - ZEN_COM_CHECK(imageFolder->GetUIObjectOf(nullptr, // [in] HWND hwndOwner, - 1, // [in] UINT cidl, - reinterpret_cast<PCUITEMID_CHILD_ARRAY>(&pidImage), // [in] PCUITEMID_CHILD_ARRAY apidl, - //this is where STRICT_TYPED_ITEMIDS gets us ;) - IID_IExtractImage, // [in] REFIID riid, - nullptr, // [in, out] UINT *rgfReserved, - reinterpret_cast<void**>(extractImage.init()))); // [out] void **ppv - ZEN_COM_ASSERT(extractImage); - - { - wchar_t pathBuffer[MAX_PATH]; - DWORD priority = 0; - const SIZE prgSize = { requestedSize, requestedSize }; - DWORD clrDepth = 32; //"recommended color depth" - DWORD flags = IEIFLAG_SCREEN | IEIFLAG_OFFLINE; - - ZEN_COM_CHECK(extractImage->GetLocation(pathBuffer, // [out] LPWSTR pszPathBuffer, - MAX_PATH, // [in] DWORD cchMax, - &priority, // [out] DWORD *pdwPriority, - &prgSize, // [in] const SIZE *prgSize, - clrDepth, // [in] DWORD dwRecClrDepth, - &flags)); // [in, out] DWORD *pdwFlags - } - - HBITMAP bitmap = nullptr; - ZEN_COM_CHECK(extractImage->Extract(&bitmap)); - ZEN_COM_ASSERT(bitmap); - ZEN_ON_SCOPE_EXIT(::DeleteObject(bitmap)); - - return convertToImageData(bitmap); //throw SysError, pass ownership -} - - -const bool wereVistaOrLater = vistaOrLater(); //thread-safety: init at startup - -//caller takes ownership! -const thumb::ImageData* getIconByIndex_impl(int iconIndex, thumb::IconSizeType st) //throw SysError -{ - //Note: - //- using IExtractIcon::Extract is *no* alternative, just as ::SHGetFileInfo(), it only supports small (16x16) and large (32x32) icons - //- IShellItemImageFactory::GetImage requires Vista or later - - using namespace thumb; - int requestedSize = 16; - int shilIconType = SHIL_SMALL; //16x16, size can be customized by the user. - { - if (!wereVistaOrLater && //XP doesn't have jumbo icons - (st == ICON_SIZE_128 || - st == ICON_SIZE_256)) - st = ICON_SIZE_48; - - switch (st) - { - case ICON_SIZE_16: - break; - case ICON_SIZE_32: - requestedSize = 32; - shilIconType = SHIL_LARGE; //32x32, may be 48x48 if "Use large icon" option is set in Display Properties - break; - case ICON_SIZE_48: - requestedSize = 48; - shilIconType = SHIL_EXTRALARGE; //48x48, size can be customized by the user. - break; - case ICON_SIZE_128: - requestedSize = 128; - shilIconType = SHIL_JUMBO; //256x256 pixels -> scale down! - break; - case ICON_SIZE_256: - requestedSize = 256; - shilIconType = SHIL_JUMBO; //256x256 pixels; Vista and later only - break; - } - } - - ComPtr<IImageList> imageList; //perf: 0,12 µs only to get the image list - ZEN_COM_CHECK(::SHGetImageList(shilIconType, //__in int iImageList, - IID_PPV_ARGS(imageList.init()))); - ZEN_COM_ASSERT(imageList); - - int srcWidth = 0; - int srcHeight = 0; - ZEN_COM_CHECK(imageList->GetIconSize(&srcWidth, &srcHeight)); - - int targetWidth = srcWidth; - int targetHeight = srcHeight; - bool needDownScale = false; //scale down if required (e.g Vista Jumbo icons/user-customized icon sizes) - - ZEN_COM_ASSERT(srcWidth > 0 && srcHeight > 0 && requestedSize > 0); - - const int maxExtent = std::max(srcWidth, srcHeight); - if (requestedSize < maxExtent) - { - needDownScale = true; - targetWidth = srcWidth * requestedSize / maxExtent; - targetHeight = srcHeight * requestedSize / maxExtent; - } - - HDC hScreenDC = ::GetDC(nullptr); - ZEN_COM_ASSERT(hScreenDC); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::ReleaseDC(nullptr, hScreenDC)); - - auto createRGBDib = [&](unsigned char** rawBits) -> HBITMAP - { - BITMAPINFO bi = {}; - bi.bmiHeader.biSize = sizeof(bi); - bi.bmiHeader.biWidth = targetWidth; - bi.bmiHeader.biHeight = -targetHeight; //negative for top left origin - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = 24; //we don't want an alpha channel - bi.bmiHeader.biCompression = BI_RGB; - - return ::CreateDIBSection(hScreenDC, //_In_ HDC hdc, - &bi, //_In_ const BITMAPINFO *pbmi, - DIB_RGB_COLORS, //_In_ UINT iUsage, - reinterpret_cast<VOID**>(rawBits), //_Out_ VOID **ppvBits, - nullptr, //_In_ HANDLE hSection, - 0); //_In_ DWORD dwOffset - }; - - unsigned char* bitsBlackBg = nullptr; - HBITMAP bmpBlackBg = createRGBDib(&bitsBlackBg); - ZEN_COM_ASSERT(bmpBlackBg); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteObject(bmpBlackBg);); - ZEN_COM_ASSERT(bitsBlackBg); //check after bmpBlackBg is owned by us - - HDC memDC = ::CreateCompatibleDC(hScreenDC); - ZEN_COM_ASSERT(memDC); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteDC(memDC)); - - HGDIOBJ hgdiOld = ::SelectObject(memDC, bmpBlackBg); - ZEN_COM_ASSERT(hgdiOld); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::SelectObject(memDC, hgdiOld)); - - IMAGELISTDRAWPARAMS drawParams = {}; - drawParams.cbSize = sizeof(drawParams); - drawParams.hdcDst = memDC; - drawParams.i = iconIndex; - drawParams.rgbBk = 0x000000; //black - drawParams.fStyle = ILD_NORMAL; - //other flags: http://msdn.microsoft.com/en-us/library/windows/desktop/bb775230(v=vs.85).aspx - - if (needDownScale) - { - drawParams.fStyle |= ILD_SCALE; - drawParams.cx = targetWidth; - drawParams.cy = targetHeight; - } - - //IDO_SHGIOI_LINK does not draw properly in some cases: - //Win7: draws link overlay *twice* if SHIL_JUMBO is requested, but icon does not have this size - //XP: drawing IDO_SHGIOI_LINK generally draws corrupted icons and links - //if (addShortcutOverlay) - //{ - // int linkOverlay = ::SHGetIconOverlayIndex(nullptr, IDO_SHGIOI_LINK); //-1 on error - // if (linkOverlay != -1) - // { - // //int imgIndex = 0; - // //if (SUCCEEDED(imageList->GetOverlayImage(linkOverlay, &imgIndex))) - // //{ - // // drawParams.i = imgIndex; - // // ZEN_COM_CHECK(imageList->Draw(&drawParams)); - // //} - - // drawParams.fStyle |= INDEXTOOVERLAYMASK(linkOverlay); - // } - //} - - ZEN_COM_CHECK(imageList->Draw(&drawParams)); - - //----------------------------------------------- - //we draw the icon twice on different backgrounds to extract the alpha channel: - //- IImageList::GetIcon doesn't properly render SHIL_JUMBO for icons that don't have jumbo sizes, but IImageList::Draw does! - //- minor: each HICON consumes 3 GDI handles - //- IImageList::Draw does not reliably support alpha channel on device context (Windows XP) - //- wxBitmap created from HBITMAP is very unreliable; often drawn incorrectly by wxDC::DrawBitmap => support wxImage instead - - unsigned char* bitsWhiteBg = nullptr; - HBITMAP bmpWhiteBg = createRGBDib(&bitsWhiteBg); - ZEN_COM_ASSERT(bmpWhiteBg); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::DeleteObject(bmpWhiteBg)); - ZEN_COM_ASSERT(bitsWhiteBg); //check after bmpWhiteBg is owned by us - - HGDIOBJ hgdiOld2 = ::SelectObject(memDC, bmpWhiteBg); - ZEN_COM_ASSERT(hgdiOld2); //no documented extended error info - ZEN_ON_SCOPE_EXIT(::SelectObject(memDC, hgdiOld2)); - - drawParams.rgbBk = 0xFFFFFF; //white - - ZEN_COM_CHECK(imageList->Draw(&drawParams)); - - //##################################################################################### - - //"Access to the bitmap must be synchronized. [...]. This applies to any use of the pointer to the bitmap bit values." - /*bool rv = */ - ::GdiFlush(); - - ImageData* imgOut = allocImageData(targetWidth, targetHeight); //throw SysError - ScopeGuard guardImgData = zen::makeGuard([&] { releaseImageData_impl(imgOut); }); - - unsigned char* rgbPtr = imgOut->rgb; - unsigned char* alphaPtr = imgOut->alpha; - - for (int i = 0; i < targetWidth * targetHeight; ++i) - { - unsigned char b_black = *bitsBlackBg++; - unsigned char g_black = *bitsBlackBg++; - unsigned char r_black = *bitsBlackBg++; - - unsigned char b_white = *bitsWhiteBg++; - unsigned char g_white = *bitsWhiteBg++; - unsigned char r_white = *bitsWhiteBg++; - - const int tmp = 255 + r_black - r_white + //mixed mode arithmetics! - 255 + g_black - g_white + - 255 + b_black - b_white; - unsigned char alpha = static_cast<unsigned char>(numeric::confineCpy(tmp / 3, 0, 255)); - - auto calcColor = [&](unsigned char c_black, unsigned char c_white) - { - return static_cast<unsigned char>(tmp == 0 ? 0 : numeric::confineCpy - (255 * (3 * (-255 + c_white + c_black) + tmp) / (2 * tmp), //mixed mode arithmetics! - 0, 255)); - }; - - *rgbPtr++ = calcColor(r_black, r_white); - *rgbPtr++ = calcColor(g_black, g_white); - *rgbPtr++ = calcColor(b_black, b_white); - *alphaPtr++ = alpha; - } - - guardImgData.dismiss(); - return imgOut; -} -} - - -const thumb::ImageData* thumb::getThumbnail(const wchar_t* filename, int requestedSize) //return 0 on failure, caller takes ownership! -{ - try - { - return getThumbnail_impl(filename, requestedSize); //throw SysError - } - catch (const SysError&) - { - return nullptr; - } -} - - -const thumb::ImageData* thumb::getIconByIndex(int iconIndex, thumb::IconSizeType st) //return 0 on failure, caller takes ownership! -{ - try - { - return getIconByIndex_impl(iconIndex, st); //throw SysError - } - catch (const SysError&) - { - return nullptr; - } -} - - -void thumb::releaseImageData(const thumb::ImageData* id) -{ - releaseImageData_impl(id); -} diff --git a/lib/Thumbnail/thumbnail.h b/lib/Thumbnail/thumbnail.h deleted file mode 100644 index 307fc7cc..00000000 --- a/lib/Thumbnail/thumbnail.h +++ /dev/null @@ -1,85 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef THUMBNAIL_DLL_HEADER_487108471324 -#define THUMBNAIL_DLL_HEADER_487108471324 - -#ifdef THUMBNAIL_DLL_EXPORTS -#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport) -#else -#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport) -#endif - -#include <zen/build_info.h> -//#include <WinDef.h> - -namespace thumb -{ -/* -PREREQUISITES: - -1. COM must be initialized for the current thread via ::CoInitialize(nullptr) or ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED), - but NOT ::CoInitializeEx(nullptr, COINIT_MULTITHREADED) -> internal access violation crash! -2. call ::FileIconInit() on app start to remedy obscure errors like SHELL_E_WRONG_BITDEPTH (0x80270102) - for certain file types, e.g. lnk, mpg - required on Windows 7 see http://msdn.microsoft.com/en-us/library/ms683212(v=VS.85).aspx -*/ - -/*-------------- - |declarations| - --------------*/ -struct ImageData //consider alignment! -{ - unsigned char* rgb; //rgb-byte order for use with wxImage - unsigned char* alpha; - int width; - int height; -}; - -DLL_FUNCTION_DECLARATION -const ImageData* getThumbnail(const wchar_t* filename, int requestedSize); //return nullptr on failure, release after use -//Note: not all file types support thumbnails! implement fallback to file icon! - -enum IconSizeType -{ - ICON_SIZE_16, - ICON_SIZE_32, - ICON_SIZE_48, - ICON_SIZE_128, - ICON_SIZE_256, -}; -//"iconIndex" as returned by ::SHGetFileInfo() -DLL_FUNCTION_DECLARATION -const ImageData* getIconByIndex(int iconIndex, IconSizeType st); //return nullptr on failure, release after use - -DLL_FUNCTION_DECLARATION -void releaseImageData(const ImageData* id); - - -/*---------- - |typedefs| - ----------*/ -typedef const ImageData* (*FunType_getThumbnail )(const wchar_t* filename, int requestedSize); -typedef const ImageData* (*FunType_getIconByIndex )(int iconIndex, IconSizeType st); -typedef void (*FunType_releaseImageData)(const ImageData* id); - - -/*-------------- - |symbol names| - --------------*/ -//(use const pointers to ensure internal linkage) -const char funName_getThumbnail [] = "getThumbnail"; -const char funName_getIconByIndex [] = "getIconByIndex"; -const char funName_releaseImageData[] = "releaseImageData"; - -/*--------------- - |library names| - ---------------*/ -inline const wchar_t* getDllName() { return zen::is64BitBuild ? L"Thumbnail_x64.dll" : L"Thumbnail_Win32.dll"; } -} - -#undef DLL_FUNCTION_DECLARATION - -#endif //THUMBNAIL_DLL_HEADER_487108471324 |