Last active
March 1, 2024 08:20
-
-
Save gwy15/8ac3280b2a360fe9484b34f61ee263be to your computer and use it in GitHub Desktop.
swift script that converts adobe generated HDR avifs compatible with iOS and mac devices
This file contains hidden or 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
import Cocoa | |
import CoreImage | |
// Constants for command line arguments | |
struct CommandLineArguments { | |
let path: String | |
let compressionRatio: CGFloat | |
} | |
// Parses the command line arguments and returns a struct | |
func parseCommandLineArguments() -> CommandLineArguments { | |
let arguments = CommandLine.arguments | |
let path = arguments.count > 1 ? arguments[1] : "." | |
let compressionRatio = arguments.count > 2 ? CGFloat(Double(arguments[2]) ?? 0.7) : 0.7 | |
return CommandLineArguments( | |
path: path, | |
compressionRatio: compressionRatio | |
) | |
} | |
// Function to check if the path is a directory and process accordingly | |
func processPath(_ path: String, compressionRatio: CGFloat) { | |
let fileManager = FileManager.default | |
var isDirectory: ObjCBool = false | |
let imageExtensions = [".avif"] | |
if fileManager.fileExists(atPath: path, isDirectory: &isDirectory) { | |
if isDirectory.boolValue { | |
// It's a directory, process all non-heic files | |
do { | |
let files = try fileManager.contentsOfDirectory(atPath: path) | |
for file in files { | |
let filePath = (path as NSString).appendingPathComponent(file) | |
if imageExtensions.contains(where: file.hasSuffix) { | |
processFile(filePath, compressionRatio: compressionRatio) | |
} | |
} | |
} catch { | |
print("Error reading contents of directory: \(error)") | |
} | |
} else { | |
// It's a file, process the single file | |
processFile(path, compressionRatio: compressionRatio) | |
} | |
} else { | |
print("The provided path does not exist.") | |
} | |
} | |
// Function to process a single file | |
func processFile(_ filePath: String, compressionRatio: CGFloat) { | |
guard let colorSpace = CGColorSpace(name: CGColorSpace.itur_2100_HLG) else { | |
print("Couldn't create a color space.") | |
exit(1) | |
} | |
let context = CIContext(options: [.workingColorSpace: colorSpace]) | |
let inputURL = URL(fileURLWithPath: filePath) | |
let outputURL = inputURL.deletingPathExtension().appendingPathExtension("heic") | |
print(inputURL.path, " -> ", outputURL.path) | |
guard let image = CIImage(contentsOf: inputURL, options: [.expandToHDR: true]) else { | |
print("Couldn't create an image from \(inputURL.path).") | |
exit(1) | |
} | |
let options = [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: compressionRatio] | |
do { | |
try context.writeHEIF10Representation(of: image, to: outputURL, colorSpace: image.colorSpace!, options: options) | |
} catch { | |
print("Failed to write the image with error: \(error)") | |
exit(1) | |
} | |
} | |
// Main function to execute the conversion process | |
func main() { | |
let args = parseCommandLineArguments() | |
guard !args.path.isEmpty else { | |
print("Usage: <path> [compressionRatio]") | |
return | |
} | |
processPath(args.path, compressionRatio: args.compressionRatio) | |
} | |
// Run the main function | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment