How to Convert Image Formats (PNG, JPG, BMP) in Batch Script
Batch scripts frequently manage file systems filled with graphics, but they lack the built-in capability to manipulate image encoding natively. Converting a heavy BMP to a compact JPG, or changing a JPG to a lossless PNG, requires interacting with external utilities or native .NET Framework libraries via PowerShell.
In this guide, we will demonstrate how to perform format conversions seamlessly using a PowerShell bridge.
The Strategy: The System.Drawing Namespace
Windows includes the .NET System.Drawing library natively on all Windows 10 and 11 systems. By invoking this library from PowerShell inside our Batch script, we can load an image into memory and save it out in a completely different format, without installing any third-party tools.
This method uses libraries included with every modern Windows installation. No downloads, no installers, and no external dependencies are required. This works on all Windows 10 1809+ and Windows 11 systems.
Implementation Script
@echo off
setlocal enabledelayedexpansion
:: 1. Define Paths
set "IMAGE_IN=C:\Temp\photo.bmp"
set "IMAGE_OUT=C:\Temp\photo_converted.jpg"
set "TARGET_FORMAT=Jpeg"
:: Check if source exists
if not exist "!IMAGE_IN!" (
echo [ERROR] Source image "!IMAGE_IN!" not found.
pause
exit /b 1
)
echo Converting "!IMAGE_IN!" to !TARGET_FORMAT!...
:: 2. Execute via PowerShell Bridge
powershell -NoProfile -Command ^
"Add-Type -AssemblyName System.Drawing; " ^
"$img = [System.Drawing.Image]::FromFile('!IMAGE_IN!'); " ^
"$img.Save('!IMAGE_OUT!', [System.Drawing.Imaging.ImageFormat]::!TARGET_FORMAT!); " ^
"$img.Dispose();"
:: 3. Verify Success
if !errorlevel! EQU 0 (
echo.
echo ==========================================
echo CONVERSION SUCCESSFUL!
echo Output saved to: !IMAGE_OUT!
echo ==========================================
) else (
echo [ERROR] Conversion failed with exit code: !errorlevel!
echo The source file may be corrupt, locked, or an unsupported format.
)
pause
Dispose()The $img.Dispose(); command is critical. If omitted, the source file remains locked in memory until the PowerShell session ends. This can cause "file in use" errors if you attempt to move, rename, or delete the source file immediately after conversion.
Supported Output Formats
In the script above, you can change TARGET_FORMAT to any standard .NET image format name:
| Format | Extension | Notes |
|---|---|---|
Jpeg | .jpg | Lossy compressed, best for photos |
Png | .png | Lossless, supports transparency |
Bmp | .bmp | Uncompressed, maximum quality |
Gif | .gif | 256 colors, suitable for simple graphics |
Tiff | .tiff | Lossless, used in printing and scanning |
Bulk Converting an Entire Directory
To convert every PNG in a folder to JPG, wrap the conversion logic in a FOR loop:
@echo off
setlocal enabledelayedexpansion
set "SOURCE_DIR=C:\Photos\Raw"
set "DEST_DIR=C:\Photos\Web"
set "TARGET_FORMAT=Jpeg"
:: Validate source directory
if not exist "!SOURCE_DIR!\" (
echo [ERROR] Source directory not found: !SOURCE_DIR!
pause
exit /b 1
)
:: Create destination directory if missing
if not exist "!DEST_DIR!" mkdir "!DEST_DIR!"
echo Starting bulk conversion...
echo.
set "successCount=0"
set "failCount=0"
for %%F in ("!SOURCE_DIR!\*.png") do (
echo Converting: %%~nxF
set "outFile=!DEST_DIR!\%%~nF.jpg"
powershell -NoProfile -Command ^
"Add-Type -AssemblyName System.Drawing; " ^
"$img = [System.Drawing.Image]::FromFile('%%F'); " ^
"$img.Save('!outFile!', [System.Drawing.Imaging.ImageFormat]::!TARGET_FORMAT!); " ^
"$img.Dispose();"
if !errorlevel! EQU 0 (
set /a "successCount+=1"
) else (
echo [FAILED] %%~nxF
set /a "failCount+=1"
)
)
echo.
echo ==========================================
echo Conversion complete.
echo Succeeded: !successCount!
echo Failed: !failCount!
echo Output: !DEST_DIR!
echo ==========================================
pause
The bulk conversion script uses !outFile! inside the for loop. This requires enabledelayedexpansion which is declared at the top of the script. Without delayed expansion, %outFile% would always evaluate to the same value for every iteration.
Why Convert Images via Script?
- Web Optimization: A script that automatically detects uncompressed
.bmpfiles in a web directory and converts them to.jpgfor faster page loading. - Archiving: Reducing the storage footprint of daily screenshot logs by converting them to heavily compressed formats.
- Standardization: Normalizing all incoming user uploads to a single format before processing.
Important Considerations
The simple .Save() method uses the default JPEG compression ratio (usually 75%). For exact control over JPEG quality levels, a more complex PowerShell script defining EncoderParameters is required:
$encoder = [System.Drawing.Imaging.Encoder]::Quality
$params = New-Object System.Drawing.Imaging.EncoderParameters(1)
$params.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($encoder, 90)
$codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object { $_.FormatID -eq [System.Drawing.Imaging.ImageFormat]::Jpeg.Guid }
$img.Save('output.jpg', $codec, $params)
If you need to perform heavy graphics work (resizing, cropping, adding text, watermarking), the ImageMagick CLI tool is faster and more robust than the .NET bridge:
magick convert "input.png" -quality 90 "output.jpg"
ImageMagick is a third-party download but is the industry standard for command-line image processing.
The .FromFile() method handles spaces in filenames correctly, but files containing single quotes ' in their names will break the PowerShell command. For maximum robustness with arbitrary filenames, pass the paths as arguments to PowerShell instead of embedding them in the command string.
Conclusion
Converting image formats is a high-value file management task that simplifies storage and web distribution. By leaning on the native .NET capabilities exposed through PowerShell, you can orchestrate single or bulk graphic conversions directly from your Batch workflow. This approach guarantees zero reliance on third-party downloads while delivering professional-grade image processing.