Skip to content

Instantly share code, notes, and snippets.

@h8rt3rmin8r
Last active January 25, 2026 14:30
Show Gist options
  • Select an option

  • Save h8rt3rmin8r/0addbf750d2d6eeb65094bf10bd20ef2 to your computer and use it in GitHub Desktop.

Select an option

Save h8rt3rmin8r/0addbf750d2d6eeb65094bf10bd20ef2 to your computer and use it in GitHub Desktop.
Converts a directory of icon images into a JSON dataset containing metadata, dimensions, and base64 strings (intended for web development usage).
<#
.SYNOPSIS
Converts a directory of icon images into a JSON dataset containing metadata, dimensions, and base64 strings.
.DESCRIPTION
This script iterates through a specified directory of image files. For each file, it generates a custom
PSObject containing the filename, size, dimensions, and a data object with the Base64 string.
The final result is exported to a JSON file.
Requirements:
- .NET Assembly System.Drawing (Standard in Windows PowerShell; requires libgdiplus on Linux/macOS for PS Core).
.PARAMETER Directory
The full or relative path to the directory containing the icon files.
Validation: Path must exist and be a container (directory).
(Belongs to Parameter Set: Default)
.PARAMETER Include
(Optional) A list of file extensions or wildcard patterns to process.
Defaults to: "png", "jpg", "svg", "ico".
Behavior:
- If a string contains wildcards (e.g., "icon_*"), it is used as-is.
- If a string has no wildcards (e.g., "png"), it is treated as an extension (*.png).
(Belongs to Parameter Set: Default)
.PARAMETER Output
(Optional) The full path for the output JSON file.
(Belongs to Parameter Set: Default)
.PARAMETER Help
Displays the full help documentation for this script.
(Belongs to Parameter Set: HelpText)
.EXAMPLE
.\Convert-IconsToJson.ps1 -Directory ".\icons"
Process "png, jpg, svg, ico" files in the icons directory and output to ".\icons.json".
.EXAMPLE
.\Convert-IconsToJson.ps1 -Directory ".\assets" -Include "png", "icon_*"
Process all .png files AND any files starting with "icon_" in the assets directory.
#>
[CmdletBinding(DefaultParameterSetName = 'Default')]
param(
[Parameter(
Mandatory = $true,
Position = 0,
ParameterSetName = 'Default',
HelpMessage = "Path to the icons directory."
)]
[ValidateScript({
if (Test-Path $_ -PathType Container) { return $true }
throw "The path '$_' does not exist or is not a directory."
})]
[Alias("d")]
[string]$Directory,
[Parameter(
Mandatory = $false,
ParameterSetName = 'Default',
HelpMessage = "File patterns to include (e.g., 'png', 'icon_*')."
)]
[Alias("i")]
[string[]]$Include = @("png", "jpg", "svg", "ico"),
[Parameter(
Mandatory = $false,
ParameterSetName = 'Default',
HelpMessage = "Path for the output JSON file."
)]
[Alias("o")]
[string]$Output,
[Parameter(
Mandatory = $true,
ParameterSetName = 'HelpText',
HelpMessage = "Show script usage and help."
)]
[Alias("h")]
[switch]$Help
)
BEGIN {
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# Load System.Drawing for dimension extraction
try {
Add-Type -AssemblyName System.Drawing
}
catch {
Write-Warning "Could not load System.Drawing. Dimension extraction may fail."
}
# MIME Type mapping for common icon formats
$MimeMap = @{
'7z' = 'application/x-7z-compressed'
'aac' = 'audio/aac'
'avi' = 'video/x-msvideo'
'bmp' = 'image/bmp'
'css' = 'text/css'
'csv' = 'text/csv'
'db' = 'application/octet-stream'
'doc' = 'application/msword'
'eot' = 'application/vnd.ms-fontobject'
'gif' = 'image/gif'
'gz' = 'application/gzip'
'gzip' = 'application/gzip'
'htm' = 'text/html'
'html' = 'text/html'
'ico' = 'image/x-icon'
'jpeg' = 'image/jpeg'
'jpg' = 'image/jpeg'
'js' = 'application/javascript'
'json' = 'application/json'
'm3u8' = 'application/vnd.apple.mpegurl'
'm4a' = 'audio/mp4'
'mkv' = 'video/x-matroska'
'mp3' = 'audio/mpeg'
'mp4' = 'video/mp4'
'pdf' = 'application/pdf'
'php' = 'text/x-php'
'png' = 'image/png'
'psd' = 'image/vnd.adobe.photoshop'
'rar' = 'application/x-rar-compressed'
'sql' = 'application/sql'
'sqlite' = 'application/x-sqlite3'
'svg' = 'image/svg+xml'
'svgz' = 'image/svg+xml'
'tif' = 'image/tiff'
'tiff' = 'image/tiff'
'ttf' = 'font/ttf'
'txt' = 'text/plain'
'wav' = 'audio/wav'
'webm' = 'video/webm'
'webp' = 'image/webp'
'woff' = 'application/font-woff'
'woff2' = 'application/font-woff2'
'zip' = 'application/zip'
}
}
PROCESS {
switch ($PSCmdlet.ParameterSetName) {
'HelpText' {
if ($Help) {
## We have to use the $Help variable to get around PS analysis warnings in VS Code
Get-Help $MyInvocation.MyCommand.Path -Full
return
}
}
'Default' {
try {
# 1. Resolve and Normalize Paths
$RootItem = Get-Item -Path $Directory
$ResolvedPath = $RootItem.FullName
$DirName = $RootItem.Name
if ([string]::IsNullOrWhiteSpace($Output)) {
$Output = Join-Path -Path $PWD -ChildPath "$DirName.json"
} else {
$OutputInfo = [System.IO.FileInfo]$Output
# -LiteralPath ensures paths with brackets [] are handled correctly
if (-not (Test-Path -LiteralPath $OutputInfo.DirectoryName -PathType Container -ErrorAction SilentlyContinue)) {
New-Item -ItemType Directory -Path $OutputInfo.DirectoryName -Force | Out-Null
}
}
# 2. Normalize Include Patterns
Write-Verbose "Normalizing include patterns..."
$SearchPatterns = $Include | ForEach-Object {
$Item = $_.Trim().ToLower()
if ($Item.Contains('*')) {
$Item
} else {
if ($Item.StartsWith(".")) { "*$Item" } else { "*.$Item" }
}
}
Write-Verbose "Input Directory: $ResolvedPath"
Write-Verbose "Search Patterns: $($SearchPatterns -join ', ')"
Write-Verbose "Output File: $Output"
# 3. Gather Files
Write-Verbose "Scanning directory for files..."
## Force array to prevent StrictMode errors on count 0 or 1
$Files = @(Get-ChildItem -Path "$ResolvedPath\*" -Include $SearchPatterns -File)
if ($Files.Count -eq 0) {
Write-Warning "No files found in '$ResolvedPath' matching patterns: $($SearchPatterns -join ', ')"
return
}
Write-Verbose "Found $($Files.Count) files. Beginning processing..."
## Initialize index counter
$Index = 0
# 4. Process Files
$IconList = foreach ($File in $Files) {
Write-Verbose "Processing [$Index]: $($File.Name)"
$Ext = $File.Extension.TrimStart('.').ToLower()
$MimeType = if ($MimeMap.ContainsKey($Ext)) { $MimeMap[$Ext] } else { "application/octet-stream" }
$Prefix = "data:$MimeType;base64,"
# A. Read Bytes
try {
$Bytes = [System.IO.File]::ReadAllBytes($File.FullName)
$Base64String = [System.Convert]::ToBase64String($Bytes)
}
catch {
Write-Error "Failed to read file '$($File.Name)': $_"
continue
}
# B. Get Dimensions
$Dimensions = $null
try {
$ImageObj = [System.Drawing.Image]::FromFile($File.FullName)
$Dimensions = "{0}x{1}" -f $ImageObj.Width, $ImageObj.Height
}
catch {
Write-Verbose "Could not determine dimensions for '$($File.Name)'."
$Dimensions = "Unknown"
}
finally {
if ($null -ne $ImageObj) {
$ImageObj.Dispose()
}
}
# C. Construct Object (UPDATED STRUCTURE)
[PSCustomObject]@{
index = $Index++
title = $File.BaseName
file = [PSCustomObject]@{
name = $File.Name
extension = $Ext
size = $File.Length
dimensions = $Dimensions
}
data = [PSCustomObject]@{
prefix = $Prefix
base64 = $Base64String
}
}
}
# 5. Export to JSON
Write-Verbose "Encoding data to JSON..."
$JsonPayload = $IconList | ConvertTo-Json -Depth 10
Write-Verbose "Writing to disk..."
$JsonPayload | Set-Content -Path $Output -Encoding UTF8
Write-Host "Success! Processed $($IconList.Count) icons. Data saved to: $Output" -ForegroundColor Green
}
catch {
Write-Error "A fatal error occurred: $_"
}
}
}
}
END {
if ($PSCmdlet.ParameterSetName -eq 'Default') {
Write-Verbose "Script execution completed."
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment