Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add to geometrize-cli ability to output png and jpeg #146

Merged
merged 1 commit into from
May 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 32 additions & 40 deletions Sources/geometrize-cli/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Geometrize
import ArgumentParser
import PNG
import JPEG
import BitmapImportExport

struct GeometrizeOptions: ParsableArguments {
@Option(
Expand Down Expand Up @@ -34,47 +35,23 @@ struct GeometrizeOptions: ParsableArguments {
let options = GeometrizeOptions.parseOrExit()

let inputUrl = URL(fileURLWithPath: options.inputPath)
guard ["png", "jpeg", "jpg"].contains(inputUrl.pathExtension.lowercased()) else {
print("Only PNG and JPEG input file formats are supported at the moment.")
exit(1)
}

let targetBitmap: Bitmap
let width, height: Int

let targetBitmap: Bitmap =
switch inputUrl.pathExtension.lowercased() {
case "png":
guard let image: PNG.Image = try .decompress(path: inputUrl.path) else {
print("Cannot read or decode input file \(inputUrl.path).")
exit(1)
}

let rgba: [PNG.RGBA<UInt8>] = image.unpack(as: PNG.RGBA<UInt8>.self)
(width, height) = image.size

let data: [UInt8] = rgba.flatMap({ [$0.r, $0.g, $0.b, $0.a] })
targetBitmap = Bitmap(width: width, height: height, data: data, blending: .white)
try Bitmap(pngUrl: inputUrl)
case "jpeg", "jpg":
guard let image: JPEG.Data.Rectangular<JPEG.Common> = try .decompress(path: inputUrl.path) else {
print("Cannot read or decode input file \(inputUrl.path).")
exit(1)
}

let rgb: [JPEG.RGB] = image.unpack(as: JPEG.RGB.self)
(width, height) = image.size

let data: [UInt8] = rgb.flatMap({ [$0.r, $0.g, $0.b, 255] })
targetBitmap = Bitmap(width: width, height: height, data: data)
try Bitmap(jpegUrl: inputUrl)
default:
print("Only PNG and JPEG input file formats are supported at the moment.")
exit(1)
fatalError("Only PNG and JPEG input file formats are supported at the moment.")
}
let width = targetBitmap.width
let height = targetBitmap.height

let outputUrl = URL(fileURLWithPath: options.outputPath)
guard options.outputPath == "-" || outputUrl.pathExtension.caseInsensitiveCompare("svg") == .orderedSame else {
print("Only SVG output file format is supported at the moment.")
exit(1)
}
guard options.outputPath == "-" || ["svg", "png", "jpeg", "jpg"].contains(outputUrl.pathExtension.lowercased()) else {
fatalError("Only SVG, PNG and JPEG output file formats are supported at the moment.")
}

// TODO: use ExpressibleByArgument?
let shapesStrings = options.shapeTypes.components(separatedBy: .whitespacesAndNewlines)
Expand Down Expand Up @@ -156,14 +133,29 @@ while shapeData.count <= shapeCount {
counter += 1
}

let svg = SVGExporter().export(data: shapeData, width: width, height: height)

do {
if options.outputPath == "-" {
print(svg)
} else {
try svg.write(to: outputUrl, atomically: true, encoding: .utf8)
let `extension` = options.outputPath == "-" ? "svg" : outputUrl.pathExtension.lowercased()
switch `extension` {
case "png":
let exporter = BitmapExporter()
let bitmap = exporter.export(data: shapeData, width: width, height: height)
let pngData = try bitmap.pngData()
try pngData.write(to: outputUrl)
case "jpeg", "jpg":
let exporter = BitmapExporter()
let bitmap = exporter.export(data: shapeData, width: width, height: height)
let jpegData = try bitmap.jpegData()
try jpegData.write(to: outputUrl)
case "svg":
let svg = SVGExporter().export(data: shapeData, width: width, height: height)
if options.outputPath == "-" {
print(svg)
} else {
try svg.write(to: outputUrl, atomically: true, encoding: .utf8)
}
default:
fatalError("File format \(outputUrl.pathExtension) for output is not supported at the moment.")
}
} catch {
print("Cannot write output file. \(error)")
print("Error writing output file: \(error)")
}