Revision: 10349 https://osdn.net/projects/ttssh2/scm/svn/commits/10349 Author: zmatsuo Date: 2022-11-06 15:24:32 +0900 (Sun, 06 Nov 2022) Log Message: ----------- GDI+ も使用して画像ファイルを読み込むようにした - Susie pluginで読み込めなかったとき - teraterm単体でpng形式の画像ファイルが読み込めるようになった - Windows10で読み込めなかったbmp形式の画像ファイルが読み込めるようになった - 高さがマイナスの場合読めなかった - gdiplus.lib をリンク(gdiplus.dllを使用)するようにした - GDI+ は Windows XP から利用可能 - XPより前のWindowsでは動作しなくなった - ttgdiplus.cpp,h を追加 Modified Paths: -------------- trunk/teraterm/common/CMakeLists.txt trunk/teraterm/common/common_static.v16.vcxproj trunk/teraterm/common/common_static.v8.vcproj trunk/teraterm/teraterm/CMakeLists.txt trunk/teraterm/teraterm/teraterm.cpp trunk/teraterm/teraterm/teraterml.h trunk/teraterm/teraterm/ttermpro.v16.vcxproj trunk/teraterm/teraterm/ttermpro.v8.vcproj trunk/teraterm/teraterm/vtdisp.c Added Paths: ----------- trunk/teraterm/common/ttgdiplus.cpp trunk/teraterm/common/ttgdiplus.h -------------- next part -------------- Modified: trunk/teraterm/common/CMakeLists.txt =================================================================== --- trunk/teraterm/common/CMakeLists.txt 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/common/CMakeLists.txt 2022-11-06 06:24:32 UTC (rev 10349) @@ -25,8 +25,8 @@ getcontent.h i18n.h i18n_static.c + inifile_com.cpp inifile_com.h - inifile_com.cpp tipwin.cpp tipwin.h tipwin2.cpp @@ -37,8 +37,10 @@ tmfc_propdlg.cpp tmfc_propdlg.h tmfc_property.cpp + ttgdiplus.cpp + ttgdiplus.h + ttknownfolders.c ttknownfolders.h - ttknownfolders.c ttlib.h ttlib_charset.cpp ttlib_charset.h Modified: trunk/teraterm/common/common_static.v16.vcxproj =================================================================== --- trunk/teraterm/common/common_static.v16.vcxproj 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/common/common_static.v16.vcxproj 2022-11-06 06:24:32 UTC (rev 10349) @@ -149,6 +149,7 @@ <ClCompile Include="dllutil.cpp" /> <ClCompile Include="getcontent.cpp" /> <ClCompile Include="i18n_static.c" /> + <ClCompile Include="ttgdiplus.cpp" /> <ClCompile Include="ttknownfolders.c" /> <ClCompile Include="ttlib_charset.cpp" /> <ClCompile Include="ttlib_static.c" /> @@ -171,6 +172,7 @@ <ClInclude Include="codeconv.h" /> <ClInclude Include="getcontent.h" /> <ClInclude Include="tmfc_propdlg.h" /> + <ClInclude Include="ttgdiplus.h" /> <ClInclude Include="ttknownfolders.h" /> <ClInclude Include="ttlib.h" /> <ClInclude Include="ttlib_charset.h" /> Modified: trunk/teraterm/common/common_static.v8.vcproj =================================================================== --- trunk/teraterm/common/common_static.v8.vcproj 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/common/common_static.v8.vcproj 2022-11-06 06:24:32 UTC (rev 10349) @@ -297,6 +297,14 @@ > </File> <File + RelativePath=".\ttgdiplus.cpp" + > + </File> + <File + RelativePath=".\ttgdiplus.h" + > + </File> + <File RelativePath=".\ttknownfolders.c" > </File> Added: trunk/teraterm/common/ttgdiplus.cpp =================================================================== --- trunk/teraterm/common/ttgdiplus.cpp (rev 0) +++ trunk/teraterm/common/ttgdiplus.cpp 2022-11-06 06:24:32 UTC (rev 10349) @@ -0,0 +1,180 @@ +/* + * (C) 2022- TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// TODO: +// - GDI+ Flat API \x82֒u\x82\xAB\x82\xA9\x82\xA6\x82\xC4 DLL \x82\xAA\x82Ȃ\xA2\x8Fꍇ\x82\xF0\x8Dl\x97\xB6 +// - GDI+ \x82\xCD Windows XP\x82\xA9\x82痘\x97p\x89\ + +#include <windows.h> +#include <gdiplus.h> +#include <assert.h> + +#include "ttgdiplus.h" + +#define DEBUG_CHECK_IMAGE 0 + +static ULONG_PTR gdiplusToken; + +void GDIPInit(void) +{ + assert(gdiplusToken == 0); + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + Gdiplus::Status r = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, 0); + assert(r == Gdiplus::Ok); + (void)r; +} + +void GDIPUninit(void) +{ + Gdiplus::GdiplusShutdown(gdiplusToken); + gdiplusToken = 0; +} + +/** + * Gdiplus::Bitmap \x82̉摜\x95ۑ\xB6 + * + * \x8Eg\x82\xA2\x95\xFB + * Gdiplus::Bitmap bitmap; + * CLSID encoderClsid; + * GetEncoderClsid(L"image/png", &encoderClsid); + * bitmap.Save(L"Bird.png", &encoderClsid, NULL); + */ +#if DEBUG_CHECK_IMAGE +static int GetEncoderClsid(const wchar_t *mime_ext, CLSID *pClsid) +{ + UINT num = 0; // number of image encoders + UINT size = 0; // size of the image encoder array in bytes + + Gdiplus::ImageCodecInfo *pImageCodecInfo = NULL; + + Gdiplus::GetImageEncodersSize(&num, &size); + if (size == 0) + return -1; // Failure + + pImageCodecInfo = (Gdiplus::ImageCodecInfo *)(malloc(size)); + if (pImageCodecInfo == NULL) + return -1; // Failure + + GetImageEncoders(num, size, pImageCodecInfo); + + for (UINT j = 0; j < num; ++j) { + if ((wcsstr(pImageCodecInfo[j].MimeType, mime_ext) == NULL) || + (wcsstr(pImageCodecInfo[j].FilenameExtension, mime_ext) == NULL) || + (wcsstr(pImageCodecInfo[j].FormatDescription, mime_ext) == NULL)) { + *pClsid = pImageCodecInfo[j].Clsid; + free(pImageCodecInfo); + return j; // Success + } + } + + free(pImageCodecInfo); + return -1; // Failure +} +#endif + +#if DEBUG_CHECK_IMAGE +static void GDIPSavePNG(Gdiplus::Bitmap *bitmap, const wchar_t *filename) +{ + CLSID encoderClsid; + GetEncoderClsid(L"image/png", &encoderClsid); + bitmap->Save(filename, &encoderClsid, NULL); +} +#endif + +static HBITMAP bitmap_GetHBITMAP(Gdiplus::Bitmap *bitmap) +{ + const int width = bitmap->GetWidth(); + const int height = bitmap->GetHeight(); + + Gdiplus::Rect rect(0, 0, width, height); + Gdiplus::BitmapData src_info; + Gdiplus::Status r; + r = bitmap->LockBits(&rect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &src_info); + if(r != Gdiplus::Ok) { + return NULL; + } + + BITMAPINFO bmi = {}; + bmi.bmiHeader.biSize = sizeof(bmi); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; // = 8*4 + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = width * height * 4; + + // usage == DIB_PAL_COLORS \x82̂Ƃ\xAB hdc\x82̃p\x83\x8C\x83b\x83g\x82\xAA\x8Eg\x97p\x82\xB3\x82\xEA\x82\xE9 + // DIB_RGB_COLORS \x82̂Ƃ\xAB\x82\xCD hdc \x82͎Q\x8FƂ\xB3\x82\xEA\x82Ȃ\xA2? + // MSDN\x82ɂ\xCDNULL\x82ł\xE0ok\x82Ƃ͏\x91\x82\xA9\x82\xEA\x82Ă\xA2\x82Ȃ\xA2 + void* pvBits; + HBITMAP hBmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0); + if (hBmp == NULL) { + return NULL; + } + + memcpy(pvBits, src_info.Scan0, width * height * 4); + + return hBmp; +} + +/** + * \x89摜\x83t\x83@\x83C\x83\x8B\x82\xF0\x93ǂݍ\x9E\x82\xF1\x82\xC5 HBITMAP \x82\xF0\x95Ԃ\xB7 + * + * @param filename \x83t\x83@\x83C\x83\x8B\x96\xBC + * @retval HBITMAP + * \x95s\x97v\x82ɂȂ\xC1\x82\xBD\x82\xE7 DeleteObject() \x82\xB7\x82邱\x82\xC6 + * @retval NULL \x83t\x83@\x83C\x83\x8B\x82\xAA\x93ǂݍ\x9E\x82߂Ȃ\xA9\x82\xC1\x82\xBD + */ +HBITMAP GDIPLoad(const wchar_t *filename) +{ + Gdiplus::Bitmap bitmap(filename); + if (bitmap.GetLastStatus() != Gdiplus::Ok) { + return NULL; + } + +#if DEBUG_CHECK_IMAGE + GDIPSavePNG(&bitmap, L"test.png"); +#endif + + Gdiplus::PixelFormat format = bitmap.GetPixelFormat(); + + if (format != PixelFormat32bppARGB) { + HBITMAP hBmp; + Gdiplus::Status r; + Gdiplus::Color bgColor = Gdiplus::Color(0, 0, 0); + r = bitmap.GetHBITMAP(bgColor, &hBmp); + if (r != Gdiplus::Ok) { + return NULL; + } + return hBmp; + } + else { + // GetHBITMAP() returns no alpha info + return bitmap_GetHBITMAP(&bitmap); + } +} Copied: trunk/teraterm/common/ttgdiplus.h (from rev 10348, trunk/teraterm/teraterm/teraterml.h) =================================================================== --- trunk/teraterm/common/ttgdiplus.h (rev 0) +++ trunk/teraterm/common/ttgdiplus.h 2022-11-06 06:24:32 UTC (rev 10349) @@ -0,0 +1,41 @@ +/* + * (C) 2022- TeraTerm Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void GDIPInit(void); +void GDIPUninit(void); +HBITMAP GDIPLoad(const wchar_t *fname); + +#ifdef __cplusplus +} +#endif Modified: trunk/teraterm/teraterm/CMakeLists.txt =================================================================== --- trunk/teraterm/teraterm/CMakeLists.txt 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/teraterm/CMakeLists.txt 2022-11-06 06:24:32 UTC (rev 10349) @@ -2,6 +2,8 @@ project(${PACKAGE_NAME}) +option(ENABLE_GDIPLUS "Use GDI+ library" ON) + include(${CMAKE_CURRENT_SOURCE_DIR}/../../libs/lib_SFMT.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/../../libs/lib_oniguruma.cmake) @@ -332,6 +334,18 @@ ) endif() +if(ENABLE_GDIPLUS) + target_compile_options( + ${PACKAGE_NAME} + PRIVATE "-DENABLE_GDIPLUS=1" + ) +else(ENABLE_GDIPLUS) + target_compile_options( + ${PACKAGE_NAME} + PRIVATE "-DENABLE_GDIPLUS=0" + ) +endif(ENABLE_GDIPLUS) + target_link_libraries( ${PACKAGE_NAME} PRIVATE @@ -368,6 +382,14 @@ ws2_32 ) +if(ENABLE_GDIPLUS) + target_link_libraries( + ${PACKAGE_NAME} + PRIVATE + gdiplus.lib + ) +endif(ENABLE_GDIPLUS) + install( TARGETS ${PACKAGE_NAME} DESTINATION . Modified: trunk/teraterm/teraterm/teraterm.cpp =================================================================== --- trunk/teraterm/teraterm/teraterm.cpp 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/teraterm/teraterm.cpp 2022-11-06 06:24:32 UTC (rev 10349) @@ -55,6 +55,9 @@ #include "ttdebug.h" #include "win32helper.h" #include "asprintf.h" +#if ENABLE_GDIPLUS +#include "ttgdiplus.h" +#endif #if defined(_DEBUG) && defined(_MSC_VER) #define new ::new(_NORMAL_BLOCK, __FILE__, __LINE__) @@ -296,9 +299,14 @@ srand((unsigned int)time(NULL)); ts.TeraTermInstance = hInstance; + hInst = hInstance; init(); _HtmlHelpW(NULL, NULL, HH_INITIALIZE, (DWORD_PTR)&HtmlHelpCookie); - hInst = hInstance; + +#if ENABLE_GDIPLUS + GDIPInit(); +#endif + CVTWindow *m_pMainWnd = new CVTWindow(hInstance); pVTWin = m_pMainWnd; main_window = m_pMainWnd->m_hWnd; @@ -371,6 +379,10 @@ delete m_pMainWnd; m_pMainWnd = NULL; +#if ENABLE_GDIPLUS + GDIPUninit(); +#endif + _HtmlHelpW(NULL, NULL, HH_CLOSE_ALL, 0); _HtmlHelpW(NULL, NULL, HH_UNINITIALIZE, HtmlHelpCookie); Modified: trunk/teraterm/teraterm/teraterml.h =================================================================== --- trunk/teraterm/teraterm/teraterml.h 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/teraterm/teraterml.h 2022-11-06 06:24:32 UTC (rev 10349) @@ -29,5 +29,13 @@ /* teraterm local header */ /* teraterm/ folder only */ +/** + * \x89摜\x93ǂݍ\x9E\x82݂\xC9 GDI+ \x83\x89\x83C\x83u\x83\x89\x83\x8A\x82\xF0\x8Eg\x97p\x82\xB7\x82\xE9 + * Windows XP \x82\xA9\x82痘\x97p\x89\ + */ +#if !defined(ENABLE_GDIPLUS) +#define ENABLE_GDIPLUS 1 // 0/1=\x97L\x8C\xF8/\x96\xB3\x8C\xF8 +#endif + void AddModelessHandle(HWND hWnd); void RemoveModelessHandle(HWND hWnd); Modified: trunk/teraterm/teraterm/ttermpro.v16.vcxproj =================================================================== --- trunk/teraterm/teraterm/ttermpro.v16.vcxproj 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/teraterm/ttermpro.v16.vcxproj 2022-11-06 06:24:32 UTC (rev 10349) @@ -81,7 +81,7 @@ <AdditionalIncludeDirectories>$(SolutionDir)common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ResourceCompile> <Link> - <AdditionalDependencies>onig_sd.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>onig_sd.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies)</AdditionalDependencies> <SuppressStartupBanner>true</SuppressStartupBanner> <AdditionalLibraryDirectories>$(SolutionDir)..\libs\oniguruma\src;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <DelayLoadDLLs>imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs)</DelayLoadDLLs> @@ -125,7 +125,7 @@ <AdditionalIncludeDirectories>$(SolutionDir)common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ResourceCompile> <Link> - <AdditionalDependencies>onig_s.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>onig_s.lib;comctl32.lib;ws2_32.lib;imagehlp.lib;setupapi.lib;gdiplus.lib;%(AdditionalDependencies)</AdditionalDependencies> <SuppressStartupBanner>true</SuppressStartupBanner> <AdditionalLibraryDirectories>$(SolutionDir)..\libs\oniguruma\src;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <DelayLoadDLLs>imagehlp.dll;user32.dll;shell32.dll;%(DelayLoadDLLs)</DelayLoadDLLs> Modified: trunk/teraterm/teraterm/ttermpro.v8.vcproj =================================================================== --- trunk/teraterm/teraterm/ttermpro.v8.vcproj 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/teraterm/ttermpro.v8.vcproj 2022-11-06 06:24:32 UTC (rev 10349) @@ -72,7 +72,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="LIBCMTd.lib LIBCPMTd.lib onig_sd.lib layer_for_unicode.lib comctl32.lib ws2_32.lib imagehlp.lib user32.lib gdi32.lib SHELL32.lib comdlg32.lib ole32.lib ADVAPI32.lib OleAut32.lib uuid.lib setupapi.lib User32.lib" + AdditionalDependencies="LIBCMTd.lib LIBCPMTd.lib onig_sd.lib layer_for_unicode.lib comctl32.lib ws2_32.lib imagehlp.lib user32.lib gdi32.lib SHELL32.lib comdlg32.lib ole32.lib ADVAPI32.lib OleAut32.lib uuid.lib setupapi.lib User32.lib gdiplus.lib" LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="$(SolutionDir)..\libs\oniguruma\src;$(OutDir)" @@ -167,7 +167,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies="LIBCMT.lib LIBCPMT.lib onig_s.lib layer_for_unicode.lib comctl32.lib ws2_32.lib imagehlp.lib user32.lib gdi32.lib SHELL32.lib comdlg32.lib ole32.lib ADVAPI32.lib OleAut32.lib setupapi.lib uuid.lib" + AdditionalDependencies="LIBCMT.lib LIBCPMT.lib onig_s.lib layer_for_unicode.lib comctl32.lib ws2_32.lib imagehlp.lib user32.lib gdi32.lib SHELL32.lib comdlg32.lib ole32.lib ADVAPI32.lib OleAut32.lib setupapi.lib uuid.lib gdiplus.lib" LinkIncremental="1" SuppressStartupBanner="true" AdditionalLibraryDirectories="$(SolutionDir)..\libs\oniguruma\src;$(OutDir)" Modified: trunk/teraterm/teraterm/vtdisp.c =================================================================== --- trunk/teraterm/teraterm/vtdisp.c 2022-11-06 06:24:19 UTC (rev 10348) +++ trunk/teraterm/teraterm/vtdisp.c 2022-11-06 06:24:32 UTC (rev 10349) @@ -29,6 +29,7 @@ /* TERATERM.EXE, VT terminal display routines */ #include "teraterm.h" +#include "teraterml.h" #include "tttypes.h" #include <string.h> #include <olectl.h> @@ -49,6 +50,9 @@ #include "win32helper.h" #include "ttknownfolders.h" // for FOLDERID_Desktop #include "ttlib.h" +#if ENABLE_GDIPLUS +#include "ttgdiplus.h" +#endif #include "theme.h" #include "vtdisp.h" @@ -449,6 +453,12 @@ hbm = LoadImageA(0,src->fileTmp,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); } +#if ENABLE_GDIPLUS + if (hbm == NULL) { + hbm = GDIPLoad(load_file); + } +#endif + if (hbm == NULL && !IsLoadImageOnlyEnabled()) { // OLE \x82𗘗p\x82\xB5\x82\xC4jpeg\x82\xF0\x93ǂ\xDE // LoadImage()\x82̂\x96\x89\xB3\x82\xEA\x82Ă\xA2\x82\xE9\x8A\xAB\x82ł͂Ȃ\xA2\x82Ƃ\xAB