Skip to content

Instantly share code, notes, and snippets.

@ThioJoe
Last active January 31, 2025 20:34
Show Gist options
  • Select an option

  • Save ThioJoe/c5ebb3246a3cd9ec3c7609a2165d2371 to your computer and use it in GitHub Desktop.

Select an option

Save ThioJoe/c5ebb3246a3cd9ec3c7609a2165d2371 to your computer and use it in GitHub Desktop.
Low-Res Icon Upscaler Batch Script
@echo off
setlocal enabledelayedexpansion
rem | Lines beginning with 'rem' are comments
rem -------------------------------------------------------------------------------------------
rem | "Icon Upscaler" Script by ThioJoe: https://github.com/ThioJoe
rem | I created this script specifically for upscaling very low res (such as 256x256) icons like those in Windows. It uses a combination of Image Magick (to first improve the transparency edges) and the RealCugan-ncnn-vulkan upscaler which seems to perform the best for this use case. Of course, the script can be used for all sorts of images, but I have found this to yield the best results of any other method, and better than just using an upscaler alone.
rem -------------------------------------------------------------------------------------------
rem | HOW TO USE: Run the script and enter a file path to an image. Or, drag an image file onto this batch file to also run it. The result will go into the "outputs" folder.
rem | Also because of the limiations of batch files, if you enter a file path that has a different drive letter than the script, there is a good chance you'll get errors. So make sure the image files are on the same drive.
rem | REQUIREMENT 1: Windows binaries for realcugan-ncnn-vulkan here https://github.com/nihui/realcugan-ncnn-vulkan
rem | REQUIREMENT 2: "Convert.exe" from the Image Magick suite. Go to the download page ( https://imagemagick.org/script/download.php ), go to the Windows Binary Release section, and get the portable version described as "Portable Win64 static at 16 bits-per-pixel component". From the zip file you only need "convert.exe", and copy that into the same folder as this script.
:START
rem | -------- COMMON SETTINGS --------
set SCALE=4
set UPSCALE_ROUNDS=1
set NOISE_LEVEL=0
set OUTPUT_FORMAT=png
set MODEL_PATH=models-se
set SKIP_TRANSPARENCY_FIX=FALSE
rem --- Descriptions for common settings -----
rem | MODEL_PATH: The folder containing model files. For example: models-pro, models-se, models-nose
rem | SCALE: The multiplicative upscale amount. models-se possible values: 2,3,4 | models-pro possible values: 2,3
rem | UPSCALE_ROUNDS: The total number of times in a row the image will be upscaled by the SCALE number. For example, with SCALE=4 and UPSCALE_ROUNDS=1, the total upscale will be 4x. With scale=2 and UPSCALE_ROUNDS=3, the total upscale will be 8x (because 2*2*2)
rem | NOISE_LEVEL: Denoise level (-1/0/1/2/3, default=-1)
rem | OUTPUT_FORMAT: Output image format (jpg/png/webp, default=ext/png)
rem | SKIP_TRANSPARENCY_FIX: (TRUE/FALSE) Skips the use of convert.exe for improving the transparency mask. You can disable this to experiment, or if you are upscaling an image with no transparency.
rem ---------- ADVANCED SETTINGS -----------
set TILE_SIZE=0
set SYNC_GAP_MODE=2
set GPU_ID=auto
set THREAD_COUNT=1:2:2
set TTA_MODE=FALSE
rem --- Descriptions for advanced settings -----
rem | TILE_SIZE (>=32/0=auto, default=0) can be 0,0,0 for multi-gpu
rem | SYNC_GAP_MODE: Default=3 | Reduces the impact of image blocking. It's a trade-off between speed and quality. | 0=without process for sync gap (fast), 1=accurate lossless (slow), 2=some loss for background, less loss for texture (middle), 3=more loss for background, less loss for texture (fast) |
rem | GPU_ID - GPU devices to use (-1=cpu, default=auto) can be 0,1,2 for multi-gpu
rem | THREAD_COUNT: Thread count for the three stages in the following format - loading:processing:saving | (default=1:2:2) | Can use a comma to specify for multiple GPUs like 3:3:3,3:3:3
rem | TTA_MODE: "Test-Time Augmentation" Mode - Averages the upscaling results of 8 versions of the image (that are flipped or rotated of the original). May yield better results but will also probably take 8x as long.
rem | For full details on all parameters, see: https://github.com/nihui/realcugan-ncnn-vulkan#full-usages
rem | This fork also has some more detailed info on the meaning of the parameters: https://github.com/Kiyamou/VapourSynth-RealCUGAN-ncnn-Vulkan
rem -------------------------------------------
set argPath=%1
set SE_MAX_SCALE=4
set PRO_MAX_SCALE=3
set NOSE_MAX_SCALE=2
rem Check for invalid upscale amounts per model
if "!MODEL_PATH!"=="models-se" (
if !SCALE! GTR !SE_MAX_SCALE! (
echo ERROR: Scale is higher than maximum for models-se, use UPSCALE_ROUNDS setting to scale higher.
goto ERROR_QUIT
)
) else if "!MODEL_PATH!"=="models-pro" (
if !SCALE! GTR !PRO_MAX_SCALE! (
echo ERROR: Scale is higher than maximum for models-pro, use UPSCALE_ROUNDS setting to scale higher.
goto ERROR_QUIT
)
) else if "!MODEL_PATH!"=="models-nose" (
if !SCALE! GTR !NOSE_MAX_SCALE! (
echo ERROR: Scale is higher than maximum for models-nose, use UPSCALE_ROUNDS setting to scale higher.
goto ERROR_QUIT
)
)
rem Check for invalid number of upscale rounds
if %UPSCALE_ROUNDS% LSS 1 (
echo ERROR: UPSCALE_ROUNDS setting must be at least 1. If UPSCALE_ROUNDS is 1, the final upcale will equal the SCALE value.
goto ERROR_QUIT
)
echo Note 1: Because of .bat file limitations, using a file path on a different drive letter than this script might not work.
echo Note 2: You can also run the script by dragging the image file onto the script file in file explorer.
echo -
if "!argPath!"=="" (
set /p INPUT_PATH="Enter Image Path > "
) else (
set INPUT_PATH=%argPath%
)
set INPUT_PATH=%INPUT_PATH:"=%
set OUTPUT_DIR=%~dp0outputs\
for %%A in ("%INPUT_PATH%") do set "BASE_FILENAME=%%~nA-upscaled"
set TEMP_DIR=%~dp0temp\
set COUNTER=1
set REPEAT_COUNTER=1
:LOOP
if %COUNTER%==1 (
set OUTPUT_FILENAME=%BASE_FILENAME%
) else (
set OUTPUT_FILENAME=%BASE_FILENAME%-%COUNTER%
)
set OUTPUT_PATH=%OUTPUT_DIR%%OUTPUT_FILENAME%.%OUTPUT_FORMAT%
if exist "!OUTPUT_PATH!" (
set /a COUNTER+=1
goto LOOP
)
if not exist "!OUTPUT_DIR!" mkdir "!OUTPUT_DIR!"
if not exist "!TEMP_DIR!" mkdir "!TEMP_DIR!"
set TEMP_MASK=%TEMP_DIR%%OUTPUT_FILENAME%-mask.png
set TEMP_UPSCALED_MASK=%TEMP_DIR%%OUTPUT_FILENAME%-upscaled-mask.png
convert.exe "!INPUT_PATH!" -alpha extract -quality 05 "!TEMP_MASK!"
:UPSCALE
rem --- Calculate total upscale amount for current round
rem calculate x^n
SET x=%SCALE%
SET n=!REPEAT_COUNTER!
SET CURRENT_UPSCALE=1
FOR /L %%i IN (1,1,%n%) DO SET /A CURRENT_UPSCALE*=x
echo -
echo Running Upscale Round !REPEAT_COUNTER! (To !CURRENT_UPSCALE!x)
realcugan-ncnn-vulkan.exe -i "!INPUT_PATH!" -o "!OUTPUT_PATH!" -n %NOISE_LEVEL% -s %SCALE% -t %TILE_SIZE% -c %SYNC_GAP_MODE% -m %MODEL_PATH% -g %GPU_ID% -j %THREAD_COUNT% -x %TTA_MODE% -f %OUTPUT_FORMAT%
if "!SKIP_TRANSPARENCY_FIX!"=="FALSE" (
realcugan-ncnn-vulkan.exe -i "!TEMP_MASK!" -o "!TEMP_UPSCALED_MASK!" -n %NOISE_LEVEL% -s %SCALE% -t %TILE_SIZE% -c %SYNC_GAP_MODE% -m %MODEL_PATH% -g %GPU_ID% -j %THREAD_COUNT% -x %TTA_MODE% -f %OUTPUT_FORMAT%
)
if "!SKIP_TRANSPARENCY_FIX!"=="FALSE" (
convert.exe "!OUTPUT_PATH!" "!TEMP_UPSCALED_MASK!" -compose copyopacity -composite -quality 05 "!OUTPUT_PATH!"
)
if !REPEAT_COUNTER! LSS !UPSCALE_ROUNDS! (
set INPUT_PATH=!OUTPUT_PATH!
set TEMP_MASK=!TEMP_UPSCALED_MASK!
set TEMP_UPSCALED_MASK=%TEMP_DIR%%OUTPUT_FILENAME%-upscaled-!REPEAT_COUNTER!-mask.png
set /a REPEAT_COUNTER+=1
goto UPSCALE
)
echo -
echo Done - Output File: "!OUTPUT_PATH!"
echo ------------------------------------
rem | If the script was run by clicking on it, it will start over and prompt for a new image
if "!argPath!"=="" (
goto START
)
rem | Delete the temp directory
rd /s /q "!TEMP_DIR!"
rem | Wait for user input before closing and open output directory
set /p EXIT_INPUT="Done^! Close this window, or press Enter to open the Output folder and exit..."
start "" "explorer.exe" "!OUTPUT_DIR!"
exit /b
:ERROR_QUIT
set /p EXIT_INPUT="Press Enter to Exit..."
exit /b
@bfffggh
Copy link
Copy Markdown

bfffggh commented Jan 8, 2024

what even is this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment