Last active
March 21, 2025 08:28
-
-
Save MircoBabin/d798f1f536aefb36b953781804e0bb9e to your computer and use it in GitHub Desktop.
Convert SVG to Windows executable icon using ImageMagick
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off | |
setlocal | |
rem SvgToWindowsExecutableIcon.bat | |
rem Windows/OS used: Windows/11 | |
rem ---------------------------------------------------- | |
rem | |
rem Version 1.1 - released on friday 21 march 2025 | |
rem | |
rem ---------------------------------------------------- | |
rem Depends on ImageMagick https://imagemagick.org | |
rem Version used: ImageMagick 7.1.1-29 Q16-HDRI x64 | |
rem ---------------------------------------------------- | |
rem %1 is input svg filename, e.g. source.svg | |
rem %2 is full path to magick.exe. If empty or omitted, it is assumed magick.exe is in the path. | |
rem %3 may optionally be "grayscale" to produce a grayscale ico. | |
rem ---------------------------------------------------- | |
rem | |
rem ---------------------------------------------------- | |
rem MIT license | |
rem | |
rem Copyright (c) 2024 Mirco Babin | |
rem | |
rem Permission is hereby granted, free of charge, to any person | |
rem obtaining a copy of this software and associated documentation | |
rem files (the "Software"), to deal in the Software without | |
rem restriction, including without limitation the rights to use, | |
rem copy, modify, merge, publish, distribute, sublicense, and/or sell | |
rem copies of the Software, and to permit persons to whom the | |
rem Software is furnished to do so, subject to the following | |
rem conditions: | |
rem | |
rem The above copyright notice and this permission notice shall be | |
rem included in all copies or substantial portions of the Software. | |
rem | |
rem THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
rem EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
rem OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
rem NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
rem HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
rem WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
rem FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
rem OTHER DEALINGS IN THE SOFTWARE. | |
rem ---------------------------------------------------- | |
rem | |
rem ---------------------------------------------------- | |
rem Why: | |
rem There are lots of tools/snippets/online converters etc. to convert a .SVG file to an icon file. | |
rem But they did not provide an easy way to simply do it "good" for a Windows executable icon. | |
rem A Windows executable icon must contain some not-well-defined sizes and formats to be compatible across different Windows versions. | |
rem Sometime ago I created an icon for TiddlyWikiWatcher ( https://github.com/MircoBabin/TiddlyWikiWatcher ) that seems to work. | |
rem I wanted to use the same sizes&formats for a new icon. | |
rem That is when SvgToWindowsExecutableIcon.bat was born. | |
rem ---------------------------------------------------- | |
set "svgSource=%~dpnx1" | |
set "icoOutput=%~dpn1.ico" | |
set magickExe=magick.exe | |
if not "%~2"=="" set magickExe=%~2 | |
set svgGrayscale=false | |
if "%~3"=="grayscale" set svgGrayscale=true | |
set svgGrayscaledFilename= | |
set icoSources= | |
set tmpMagickCommandInput= | |
set tmpMagickCommandOutput= | |
set tmpMagickCommand= | |
:step_check_magick | |
if exist "%magickExe%" goto step_grayscale_svg | |
where /q "%magickExe%" >nul 2>&1 | |
if errorlevel 1 goto step_magick_not_found | |
goto step_grayscale_svg | |
:step_magick_not_found | |
echo. | |
echo ImageMagick https://imagemagick.org magick.exe was not found. | |
echo "%magickExe%" | |
goto step_error | |
:step_grayscale_svg | |
if not "%svgGrayscale%"=="true" goto step_delete_output | |
echo [GRAYSCALE] --- begin --- | |
call :build_svgGrayscaledFilename "%svgSource%" | |
echo Create grayscaled svg in %svgGrayscaledFilename% | |
set tmpMagickCommandInput=%svgSource% | |
set tmpMagickCommandOutput=%svgGrayscaledFilename% | |
set tmpMagickCommand="%magickExe%" convert "%tmpMagickCommandInput%" -colorspace Gray "%svgGrayscaledFilename%" | |
call :magick_execute | |
if errorlevel 1 goto step_error | |
set icoSources= | |
set svgSource=%svgGrayscaledFilename% | |
echo. | |
echo [GRAYSCALE] --- end --- | |
echo. | |
goto step_delete_output | |
:step_delete_output | |
if not exist "%icoOutput%" goto step_resize | |
del /q "%icoOutput%" >nul 2>&1 | |
if not exist "%icoOutput%" goto step_resize | |
echo Error deleting .ico outputfile: "%icoOutput%" | |
goto step_error | |
:step_resize | |
echo [RESIZE] --- begin --- | |
call :magickResize "%svgSource%" 16x16 bmp-4bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 16x16 bmp-8bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 16x16 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 20x20 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 24x24 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 32x32 bmp-4bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 32x32 bmp-8bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 32x32 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 40x40 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 48x48 bmp-8bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 48x48 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 64x64 bmp-32bit | |
if errorlevel 1 goto step_error | |
call :magickResize "%svgSource%" 256x256 png | |
if errorlevel 1 goto step_error | |
echo. | |
echo [RESIZE] --- end --- | |
echo. | |
:step_creating_ico | |
echo. | |
echo [CREATE ICO] ------------------------------------------------------------------ | |
echo. | |
echo "%magickExe%" %icoSources% "%icoOutput%" | |
"%magickExe%" %icoSources% "%icoOutput%" | |
if exist "%icoOutput%" goto step_created_ico | |
echo. | |
echo .ico outputfile was not created: "%icoOutput%" | |
goto step_error | |
:step_created_ico | |
echo. | |
echo [IDENTIFY ICO] ---------------------------------------------------------------- | |
echo. | |
"%magickExe%" identify "%icoOutput%" | |
echo. | |
echo. | |
echo Created: "%icoOutput%" | |
echo --- SUCCESS --- | |
exit /b 0 | |
:step_error | |
echo. | |
echo !!! ERROR !!! | |
pause | |
exit /b 99 | |
:build_svgGrayscaledFilename | |
set "svgGrayscaledFilename=%~dpn1-grayscale%~x1" | |
set "icoOutput=%~dpn1-grayscale.ico" | |
exit /b 0 | |
:magickResize | |
rem %1 is source.svg | |
rem %2 is size e.g. 16x16 | |
rem %3 is outputtype | |
set tmpMagickCommandInput=%~1 | |
set tmpMagickCommandOutput=%~dpn1.%~2 | |
set tmpMagickCommand="%magickExe%" convert | |
set tmpMagickCommand=%tmpMagickCommand% -size %~2 | |
set tmpMagickCommand=%tmpMagickCommand% -background transparent | |
if "%~3"=="bmp-4bit" goto magickResize_bmp_4bit | |
if "%~3"=="bmp-8bit" goto magickResize_bmp_8bit | |
if "%~3"=="bmp-32bit" goto magickResize_bmp_32bit | |
if "%~3"=="png" goto magickResize_png | |
echo :magickResize - unknown output-type: %~3 | |
exit /b 1 | |
:magickResize_bmp_4bit | |
set tmpMagickCommand=%tmpMagickCommand% +dither -depth 4 -colors 16 -type palette | |
set tmpMagickCommandOutput=%tmpMagickCommandOutput%.4bit.bmp | |
set tmpMagickCommand=%tmpMagickCommand% "%tmpMagickCommandInput%" "%tmpMagickCommandOutput%" | |
goto magick_execute | |
:magickResize_bmp_8bit | |
set tmpMagickCommand=%tmpMagickCommand% +dither -depth 8 -colors 256 -type palette | |
set tmpMagickCommandOutput=%tmpMagickCommandOutput%.8bit.bmp | |
set tmpMagickCommand=%tmpMagickCommand% "%tmpMagickCommandInput%" "%tmpMagickCommandOutput%" | |
goto magick_execute | |
:magickResize_bmp_32bit | |
set tmpMagickCommand=%tmpMagickCommand% -depth 32 | |
set tmpMagickCommandOutput=%tmpMagickCommandOutput%.32bit.bmp | |
set tmpMagickCommand=%tmpMagickCommand% "%tmpMagickCommandInput%" "%tmpMagickCommandOutput%" | |
goto magick_execute | |
:magickResize_png | |
set tmpMagickCommand=%tmpMagickCommand% | |
set tmpMagickCommandOutput=%tmpMagickCommandOutput%.png | |
set tmpMagickCommand=%tmpMagickCommand% "%tmpMagickCommandInput%" "%tmpMagickCommandOutput%" | |
goto magick_execute | |
:magick_execute | |
if exist "%tmpMagickCommandInput%" goto magick_execute1 | |
echo :magickResize - inputfile does not exist: "%tmpMagickCommandInput%" | |
exit /b 2 | |
:magick_execute1 | |
if not exist "%tmpMagickCommandOutput%" goto magick_execute2 | |
del /q "%tmpMagickCommandOutput%" > nul 2>&1 | |
if not exist "%tmpMagickCommandOutput%" goto magick_execute2 | |
echo :magickResize - error deleting outputfile: "%tmpMagickCommandOutput%" | |
exit /b 3 | |
:magick_execute2 | |
echo. | |
echo %tmpMagickCommand% | |
%tmpMagickCommand% | |
if exist "%tmpMagickCommandOutput%" goto magick_execute3 | |
echo. | |
echo :magickResize - outputfile was not created: "%tmpMagickCommandOutput%" | |
exit /b 4 | |
:magick_execute3 | |
"%magickExe%" identify "%tmpMagickCommandOutput%" | |
set icoSources=%icoSources% "%tmpMagickCommandOutput%" | |
exit /b 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Attention: when saving file from GitHub, convert the line ending to Windows (CR LF)! Otherwise strange errors will happen like "label xxxx not found".
The grayscale command
SvgToWindowsExecutableIcon.bat icon.svg "" "grayscale"
produces a warning "magick.exe: Cannot write image with defined png:bit-depth or png:color-type. `' @ warning/png.c/MagickPNGWarningHandler/1526.", but does output an ico file.