forked from fritob/Camper-Monitor
Neigung am Fahrzeug darstellen
Neben der Libelle gibt es jetzt eine zweite Darstellung: die Neigung am Fahrzeug selbst, mit den Zeichnungen aus dem Ursprungsprojekt. Umschaltbar und über Starts hinweg gemerkt. Seitenansicht für längs, Heckansicht für quer. Die Heckansicht ist bewusst gewählt, nicht die Frontansicht: sie teilt die Blickrichtung des Fahrers, links im Bild ist also links am Fahrzeug. Von vorne betrachtet wäre es seitenverkehrt und damit beim Ausrichten irreführend. Die Zeichnungen sind weiss gefüllt mit dunklen Linien. Als Schablone eingefärbt wurde daraus eine massive Fläche, weil alles Deckende zur Tintfarbe wird - Fenster, Räder und Konturen verschwanden. Tools/ make-vehicle-art übersetzt deshalb die Helligkeit in Deckkraft: dunkle Linien voll deckend, helle Karosserie nur angedeutet. Eingefärbt bleibt die Zeichnung erhalten und passt sich Hell- wie Dunkeldarstellung an. Die Neigung wird dreifach überhöht gezeigt, sonst wären zwei Grad am Fahrzeug kaum auszumachen. Das steht als Hinweis darunter, zusammen mit der Klarstellung, dass die Gradzahlen echt sind - sonst nähme man den Bildwinkel für den tatsächlichen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import AppKit
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
|
||||
// Die Zeichnungen sind weiss gefüllt mit dunklen Linien und Fenstern. Als
|
||||
// Schablone eingefärbt geht beides verloren, weil alles Deckende zur
|
||||
// Tintfarbe wird - übrig bleibt eine massive Fläche.
|
||||
//
|
||||
// Deshalb wird die Helligkeit in Deckkraft übersetzt: dunkle Linien werden
|
||||
// voll deckend, die helle Karosserie nur angedeutet. Eingefärbt ergibt das
|
||||
// eine gefüllte Form, in der die Details erhalten bleiben.
|
||||
|
||||
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))
|
||||
|
||||
/// Wie stark die Fläche noch durchscheint.
|
||||
let fill = 0.22
|
||||
var changed = 0
|
||||
|
||||
for index in stride(from: 0, to: pixels.count, by: 4) {
|
||||
let alpha = Double(pixels[index + 3]) / 255
|
||||
guard alpha > 0.02 else {
|
||||
pixels[index] = 0; pixels[index + 1] = 0; pixels[index + 2] = 0; pixels[index + 3] = 0
|
||||
continue
|
||||
}
|
||||
// Premultipliziert: erst zurückrechnen, um die echte Helligkeit zu sehen.
|
||||
let r = Double(pixels[index]) / 255 / alpha
|
||||
let g = Double(pixels[index + 1]) / 255 / alpha
|
||||
let b = Double(pixels[index + 2]) / 255 / alpha
|
||||
let brightness = min(1, max(0, 0.299 * r + 0.587 * g + 0.114 * b))
|
||||
|
||||
let newAlpha = alpha * (fill + (1 - fill) * (1 - brightness))
|
||||
// Die Farbe selbst spielt keine Rolle, sie wird ohnehin eingefärbt.
|
||||
let value = UInt8(newAlpha * 255)
|
||||
pixels[index] = value; pixels[index + 1] = value; pixels[index + 2] = value
|
||||
pixels[index + 3] = value
|
||||
changed += 1
|
||||
}
|
||||
|
||||
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]): \(changed) Bildpunkte umgesetzt")
|
||||
Reference in New Issue
Block a user