Files
CavesOfSwift/Sources/JolkEngine/Loaders/NSImageLoader.swift
2024-05-09 20:52:01 +10:00

53 lines
1.7 KiB
Swift

import AppKit
enum ImageLoaderError: Error
{
case loadFailed(_ message: String)
}
struct NSImageLoader: LoaderProtocol
{
typealias T = Image
func load(url: URL) -> T?
{
guard let image = try? NSImageLoader.loadImage(url: url) else { return nil }
return image
}
func load(url: URL, content: inout ContentManager) -> T? { return load(url: url) }
static func loadImage(url: URL) throws -> Image
{
try autoreleasepool
{
// Open as a Core Graphics image
guard let nsImg = NSImage(contentsOf: url),
let image = nsImg.cgImage(forProposedRect: nil, context: nil, hints: nil)
else { throw ImageLoaderError.loadFailed("Failed to open image \"\(url.absoluteString)\"") }
// Convert to 8-bit ARGB (SRGB) w/ premultiplied alpha
let alphaInfo = image.alphaInfo == .none ? CGImageAlphaInfo.noneSkipLast : CGImageAlphaInfo.premultipliedLast
guard let colourspace = CGColorSpace(name: CGColorSpace.sRGB),
let context = CGContext(data: nil,
width: image.width,
height: image.height,
bitsPerComponent: 8,
bytesPerRow: image.width * 4,
space: colourspace,
bitmapInfo: alphaInfo.rawValue | CGBitmapInfo.byteOrder32Big.rawValue)
else { throw ImageLoaderError.loadFailed("Coudn't create graphics context") }
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(image.height))
context.concatenate(flipVertical)
context.draw(image, in: CGRect(x: 0, y: 0, width: image.width, height: image.height))
guard let data = context.data else { throw ImageLoaderError.loadFailed("what") }
return Image(
pixels: Data(bytes: data, count: 4 * image.width * image.height),
width: image.width,
height: image.height)
}
}
}