update at 2026-03-16 09:00:35

This commit is contained in:
douboer@gmail.com
2026-03-16 09:00:35 +08:00
parent 4b280073d4
commit 3d8dba12aa
24 changed files with 974 additions and 233 deletions

View File

@@ -18,6 +18,7 @@ trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT INT TERM
sleep 1
/usr/bin/swift "$CALENDAR_DIR/scripts/export-kindle-background.swift" "$URL" "$OUT_PNG" "$OUT_REGION"
node "$CALENDAR_DIR/scripts/generate-dashboard-manifest.mjs" >/dev/null
cat "$OUT_REGION"

View File

@@ -2,6 +2,8 @@
import AppKit
import Foundation
import ImageIO
import UniformTypeIdentifiers
import WebKit
enum ExportError: Error, CustomStringConvertible {
@@ -29,7 +31,8 @@ final class SnapshotExporter: NSObject, WKNavigationDelegate {
private let pngOutputURL: URL
private let regionOutputURL: URL
private let completion: (Result<Void, Error>) -> Void
private let targetSize = CGSize(width: 1024, height: 600)
// Kindle Voyage
private let targetSize = CGSize(width: 1072, height: 1448)
private lazy var window: NSWindow = {
let window = NSWindow(
@@ -129,16 +132,52 @@ final class SnapshotExporter: NSObject, WKNavigationDelegate {
image.draw(in: NSRect(origin: .zero, size: targetSize))
normalizedImage.unlockFocus()
guard
let tiffRepresentation = normalizedImage.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffRepresentation),
let pngData = bitmap.representation(using: .png, properties: [:])
else {
guard let sourceCGImage = normalizedImage.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
throw ExportError.pngEncodingFailed(url.path)
}
let width = Int(targetSize.width)
let height = Int(targetSize.height)
let colorSpace = CGColorSpaceCreateDeviceGray()
// 8-bit PNG
guard let context = CGContext(
data: nil,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: 0,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.none.rawValue
) else {
throw ExportError.pngEncodingFailed(url.path)
}
context.setFillColor(gray: 1, alpha: 1)
context.fill(CGRect(x: 0, y: 0, width: width, height: height))
context.interpolationQuality = .high
context.draw(sourceCGImage, in: CGRect(x: 0, y: 0, width: width, height: height))
guard let grayscaleImage = context.makeImage() else {
throw ExportError.pngEncodingFailed(url.path)
}
try FileManager.default.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true)
try pngData.write(to: url)
guard let destination = CGImageDestinationCreateWithURL(
url as CFURL,
UTType.png.identifier as CFString,
1,
nil
) else {
throw ExportError.pngEncodingFailed(url.path)
}
CGImageDestinationAddImage(destination, grayscaleImage, nil)
guard CGImageDestinationFinalize(destination) else {
throw ExportError.pngEncodingFailed(url.path)
}
}
private func saveRegion(region: [String: NSNumber]) throws {