Created
May 27, 2024 22:18
-
-
Save fabio914/4eaeefa015548aabd48bbce572642ff1 to your computer and use it in GitHub Desktop.
Command Line tool to add Rounded Corners to images
This file contains 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
// | |
// This is a small command line tool for macOS that takes all images in a directory | |
// and creates versions of these images with rounded corners. Ideal for App Icons. | |
// | |
// Compile with: | |
// $ swiftc roundedCorners.swift | |
// | |
// Usage: | |
// ./roundedCorners imageDirectory | |
// | |
import Foundation | |
import Cocoa | |
let arguments = CommandLine.arguments | |
guard arguments.count >= 2 else { | |
fatalError("Usage: \(arguments[0]) <path of directory with images>") | |
} | |
let currentPathURL = URL(string: FileManager.default.currentDirectoryPath) | |
guard let inputURL = URL(string: arguments[1]) else { | |
fatalError("Invalid input URL") | |
} | |
print("Input URL: \(inputURL)") | |
guard let contents = try? FileManager.default.contentsOfDirectory(at: inputURL, includingPropertiesForKeys: nil) else { | |
fatalError("Unable to access input directory") | |
} | |
guard !contents.isEmpty else { | |
fatalError("Empty directory") | |
} | |
for imageURL in contents { | |
print("Opening: \(imageURL)") | |
if let image = NSImage(contentsOf: imageURL) { | |
if let data = makeRoundedImage(image: image) { | |
let fileName = imageURL.deletingPathExtension().lastPathComponent | |
let newURL = imageURL.deletingLastPathComponent().appending(path: "\(fileName)_rounded.png") | |
print("Saving to: \(newURL)") | |
do { | |
try data.write(to: newURL) | |
} catch { | |
print("Failed to save image! \(error)") | |
} | |
} else { | |
print("Failed to generate image!") | |
} | |
} else { | |
print("Not an image, skipping...") | |
} | |
} | |
func makeRoundedImage(image: NSImage, radiusRatio: CGFloat = (360.0/2048.0)) -> Data? { | |
guard let size = image.pixelSize else { | |
return nil | |
} | |
guard let rep = NSBitmapImageRep( | |
bitmapDataPlanes: nil, | |
pixelsWide: Int(size.width), | |
pixelsHigh: Int(size.height), | |
bitsPerSample: 8, | |
samplesPerPixel: 4, | |
hasAlpha: true, | |
isPlanar: false, | |
colorSpaceName: .calibratedRGB, | |
bytesPerRow: 0, | |
bitsPerPixel: 0 | |
) else { | |
return nil | |
} | |
rep.size = size | |
guard let context = NSGraphicsContext(bitmapImageRep: rep) else { | |
return nil | |
} | |
let rect = CGRect(origin: CGPoint.zero, size: size) | |
let imageLayer = CALayer() | |
imageLayer.frame = rect | |
imageLayer.contents = image.cgImage(forProposedRect: nil, context: nil, hints: nil) | |
imageLayer.masksToBounds = true | |
imageLayer.cornerRadius = (radiusRatio * size.width) | |
imageLayer.render(in: context.cgContext) | |
return rep.representation(using: .png, properties: [:]) | |
} | |
extension NSImage{ | |
var pixelSize: NSSize? { | |
guard let rep = self.representations.first else { return nil } | |
return NSSize(width: rep.pixelsWide, height: rep.pixelsHigh) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment