Skip to content

Instantly share code, notes, and snippets.

@lambdalisue
Created December 20, 2025 15:36
Show Gist options
  • Select an option

  • Save lambdalisue/0c3c42901d8ed3cda58b3988ea6c984a to your computer and use it in GitHub Desktop.

Select an option

Save lambdalisue/0c3c42901d8ed3cda58b3988ea6c984a to your computer and use it in GitHub Desktop.
Add transparent padding to an icon for macOS Tahoe compatibility
#!/usr/bin/env python3
"""
Add transparent padding to an icon for macOS Tahoe compatibility.
macOS Tahoe automatically adds white borders to icons that extend to the edge.
This script adds transparent padding around the icon to prevent this behavior.
Usage:
python3 add-icon-padding.py input.png output.png [--padding 12]
Arguments:
input.png - Source icon file
output.png - Output icon file with padding
--padding - Padding percentage (default: 12%)
"""
import sys
from PIL import Image
import argparse
def add_padding(input_path: str, output_path: str, padding_percent: int = 12):
"""
Add transparent padding around an icon.
Args:
input_path: Path to input PNG file
output_path: Path to output PNG file
padding_percent: Percentage of padding to add (default 12%)
"""
# Open the original icon
img = Image.open(input_path)
# Ensure RGBA mode for transparency
if img.mode != 'RGBA':
img = img.convert('RGBA')
# Get original dimensions
orig_width, orig_height = img.size
print(f"πŸ“ Original size: {orig_width}x{orig_height}")
# Calculate new dimensions with padding
# padding_percent on each side, so total increase is 2 * padding_percent
scale_factor = 1 + (2 * padding_percent / 100)
new_width = int(orig_width * scale_factor)
new_height = int(orig_height * scale_factor)
print(f"πŸ“ New size with {padding_percent}% padding: {new_width}x{new_height}")
# Create new transparent canvas
new_img = Image.new('RGBA', (new_width, new_height), (0, 0, 0, 0))
# Calculate position to center the original icon
x_offset = (new_width - orig_width) // 2
y_offset = (new_height - orig_height) // 2
print(f"πŸ“ Centering icon with offset: ({x_offset}, {y_offset})")
# Paste the original icon onto the new canvas
new_img.paste(img, (x_offset, y_offset), img)
# Save the result
new_img.save(output_path, 'PNG')
print(f"βœ… Saved padded icon to: {output_path}")
def create_iconset(source_png: str, iconset_dir: str, padding_percent: int = 12):
"""
Create a complete .iconset directory with all required sizes.
Args:
source_png: Path to source PNG (should be large, ideally 1024x1024 or larger)
iconset_dir: Path to .iconset directory to create
padding_percent: Padding percentage
"""
import os
# Icon sizes required for macOS
sizes = [16, 32, 64, 128, 256, 512, 1024]
# Create iconset directory
os.makedirs(iconset_dir, exist_ok=True)
print(f"πŸ“ Creating iconset at: {iconset_dir}")
# Load source image
source_img = Image.open(source_png)
if source_img.mode != 'RGBA':
source_img = source_img.convert('RGBA')
# Calculate padding
scale_factor = 1 + (2 * padding_percent / 100)
for size in sizes:
# Calculate padded size
padded_size = int(size * scale_factor)
# Resize source image to target padded size
resized = source_img.resize((padded_size, padded_size), Image.Resampling.LANCZOS)
# Create canvas for the final size (without padding in filename)
canvas = Image.new('RGBA', (size, size), (0, 0, 0, 0))
# Resize to actual size (this maintains the padding ratio)
final = resized.resize((size, size), Image.Resampling.LANCZOS)
# Save 1x version
output_path = os.path.join(iconset_dir, f"icon_{size}x{size}.png")
final.save(output_path, 'PNG')
print(f" βœ“ Created {size}x{size}")
# Save 2x version
size_2x = size * 2
final_2x = resized.resize((size_2x, size_2x), Image.Resampling.LANCZOS)
output_path_2x = os.path.join(iconset_dir, f"icon_{size}x{size}@2x.png")
final_2x.save(output_path_2x, 'PNG')
print(f" βœ“ Created {size}x{size}@2x")
print(f"\nβœ… Iconset created successfully!")
print(f"Now run: iconutil -c icns {iconset_dir}")
def main():
parser = argparse.ArgumentParser(
description="Add transparent padding to icons for macOS Sequoia"
)
parser.add_argument("input", help="Input PNG file")
parser.add_argument("output", nargs='?', help="Output PNG file (optional if --iconset is used)")
parser.add_argument("--padding", type=int, default=12, help="Padding percentage (default: 12)")
parser.add_argument("--iconset", help="Create a complete .iconset directory")
args = parser.parse_args()
# Check if PIL is available
try:
from PIL import Image
except ImportError:
print("❌ Error: Pillow library is required")
print("Install it with: pip3 install Pillow")
sys.exit(1)
if args.iconset:
# Create iconset mode
create_iconset(args.input, args.iconset, args.padding)
elif args.output:
# Single image mode
add_padding(args.input, args.output, args.padding)
else:
parser.error("Either output file or --iconset must be specified")
if __name__ == "__main__":
main()