import AppKit import CoreGraphics import Foundation // Vorlagen kommen manchmal auf weißem statt transparentem Grund. Ohne // Alphakanal hielte `make-vehicle-art.swift` die ganze Fläche für Zeichnung // und färbte den Hintergrund mit ein. Dieses Werkzeug macht daraus einen // echten Alphakanal: reines Weiß wird voll durchsichtig, alles andere bleibt // stehen. Ein weicher Übergang statt einer harten Schwelle verhindert // gezackte Kanten an den (leicht kantengeglätteten) Linien. let arguments = CommandLine.arguments guard arguments.count >= 3, let source = NSImage(contentsOfFile: arguments[1]), let image = source.cgImage(forProposedRect: nil, context: nil, hints: nil) else { print("Quelle nicht lesbar"); exit(1) } let width = image.width, height = image.height let bytesPerRow = width * 4 var pixels = [UInt8](repeating: 0, count: bytesPerRow * height) guard let context = CGContext(data: &pixels, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { print("Puffer nicht anlegbar"); exit(1) } context.draw(image, in: CGRect(x: 0, y: 0, width: width, height: height)) /// Unterhalb davon gilt ein Pixel als reiner Hintergrund, oberhalb als /// sicher Zeichnung. Dazwischen wird linear zwischen 0 und voller Deckkraft /// überblendet, damit Kanten nicht ausgefranst wirken. let whiteFloor = 230.0 let whiteCeiling = 250.0 for index in stride(from: 0, to: pixels.count, by: 4) { // Quelle ist opak (kein Alphakanal), also stehen hier die Rohfarben. let r = Double(pixels[index]) let g = Double(pixels[index + 1]) let b = Double(pixels[index + 2]) let whiteness = min(r, g, b) let t = min(1, max(0, (whiteness - whiteFloor) / (whiteCeiling - whiteFloor))) let alpha = 1 - t guard alpha > 0.004 else { pixels[index] = 0; pixels[index + 1] = 0; pixels[index + 2] = 0; pixels[index + 3] = 0 continue } // Premultipliziert ablegen. pixels[index] = UInt8(r * alpha) pixels[index + 1] = UInt8(g * alpha) pixels[index + 2] = UInt8(b * alpha) pixels[index + 3] = UInt8(alpha * 255) } guard let result = context.makeImage() else { print("Bild leer"); exit(1) } let rep = NSBitmapImageRep(cgImage: result) guard let png = rep.representation(using: .png, properties: [:]) else { print("PNG nicht erzeugbar"); exit(1) } try png.write(to: URL(fileURLWithPath: arguments[2])) print("\(arguments[2]): fertig")