Release pipeline after PhotoCraft's: AppImage/deb/rpm/Flatpak/tar.gz for Linux x86_64 and aarch64, FreeBSD, a macOS dmg and CLI zip, Windows x64/x86/arm64 MSI and portable zip (plus the plain x64 exe), web zip, SHA256SUMS.txt; version 0.1.2
Adapted from storytold/photocraft's release.yml and packaging/ (Apache-2.0; ATTRIBUTION.md and NOTICE say so). Packages install the licence files, THIRD-PARTY-LICENSES.txt included. The app icon is drawn by `solvecraft-cli icon` (a blue block with a bore, rendered on a transparent background; .ico too), so no image is committed. Notes: a short header plus GitHub's generated What's Changed. A dry run (Run workflow, publish off) keeps the files as the release-assets artifact. packaging-lint.yml checks the workflows, scripts and metadata. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
90fde44c32
commit
7e0618d64b
29 files changed
+1593
-267
No files matched your search
@@ -8,4 +8,4 @@ mod camera;
|
||||
mod raster;
|
||||
|
||||
pub use camera::{Camera, CameraAnim, Mat4, Quat, StandardView, ease_in_out};
|
||||
pub use raster::{Canvas, Rgb, Scene, SceneLine, SceneMesh, render, render_png};
|
||||
pub use raster::{Canvas, Rgb, Scene, SceneLine, SceneMesh, png, render, render_png, render_transparent};
|
||||
@@ -200,12 +200,38 @@ pub fn render(scene: &Scene, cam: &Camera, w: usize, h: usize) -> Canvas {
|
||||
/// Render to PNG bytes.
|
||||
pub fn render_png(scene: &Scene, cam: &Camera, w: usize, h: usize) -> Option<Vec<u8>> {
|
||||
let c = render(scene, cam, w, h);
|
||||
let img = image::RgbaImage::from_raw(c.w as u32, c.h as u32, c.rgba)?;
|
||||
png(c.w, c.h, c.rgba)
|
||||
}
|
||||
|
||||
/// RGBA pixels (`w × h`) to PNG bytes.
|
||||
pub fn png(w: usize, h: usize, rgba: Vec<u8>) -> Option<Vec<u8>> {
|
||||
let img = image::RgbaImage::from_raw(u32::try_from(w).ok()?, u32::try_from(h).ok()?, rgba)?;
|
||||
let mut buf = std::io::Cursor::new(Vec::new());
|
||||
img.write_to(&mut buf, image::ImageFormat::Png).ok()?;
|
||||
Some(buf.into_inner())
|
||||
}
|
||||
|
||||
/// Render on a transparent background: the scene drawn over black and over white, and the
|
||||
/// alpha recovered from the difference (exact for the anti-aliased edges).
|
||||
pub fn render_transparent(scene: &mut Scene, cam: &Camera, w: usize, h: usize) -> Canvas {
|
||||
let keep = scene.background;
|
||||
scene.background = Some((Rgb(0, 0, 0), Rgb(0, 0, 0)));
|
||||
let black = render(scene, cam, w, h);
|
||||
scene.background = Some((Rgb(255, 255, 255), Rgb(255, 255, 255)));
|
||||
let mut out = render(scene, cam, w, h);
|
||||
scene.background = keep;
|
||||
for (o, b) in out.rgba.as_chunks_mut::<4>().0.iter_mut().zip(black.rgba.as_chunks::<4>().0) {
|
||||
// white - black = 255 (1 - alpha) in every channel; average them.
|
||||
let d: u32 = (0..3).map(|k| u32::from(o[k].saturating_sub(b[k]))).sum();
|
||||
let a = 255.0 - d as f64 / 3.0;
|
||||
for k in 0..3 {
|
||||
o[k] = if a > 0.5 { (f64::from(b[k]) * 255.0 / a).round().clamp(0.0, 255.0) as u8 } else { 0 };
|
||||
}
|
||||
o[3] = a.round().clamp(0.0, 255.0) as u8;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in new issue
Block a user