mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 02:28:19 -06:00
add Image::show
This commit is contained in:
parent
16fbab6ca2
commit
dd74d73361
|
@ -19,6 +19,10 @@ umath = "0.0.7"
|
||||||
fr = { version = "0.1.1", package = "fer", optional = true }
|
fr = { version = "0.1.1", package = "fer", optional = true }
|
||||||
stackblur-iter = { version = "0.2.0", features = ["simd"], optional = true }
|
stackblur-iter = { version = "0.2.0", features = ["simd"], optional = true }
|
||||||
clipline = "0.1.1"
|
clipline = "0.1.1"
|
||||||
|
minifb = { version = "0.25.0", default-features = false, features = [
|
||||||
|
"x11",
|
||||||
|
"wayland",
|
||||||
|
], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
iai = { git = "https://github.com/bend-n/iai.git" }
|
iai = { git = "https://github.com/bend-n/iai.git" }
|
||||||
|
@ -53,6 +57,7 @@ scale = ["fr"]
|
||||||
save = ["png"]
|
save = ["png"]
|
||||||
text = ["fontdue"]
|
text = ["fontdue"]
|
||||||
blur = ["stackblur-iter"]
|
blur = ["stackblur-iter"]
|
||||||
|
real-show = ["minifb"]
|
||||||
default = ["save", "scale"]
|
default = ["save", "scale"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
@ -47,6 +47,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
for y in ymin..ymax {
|
for y in ymin..ymax {
|
||||||
for x in xmin..xmax {
|
for x in xmin..xmax {
|
||||||
// algorithm from https://web.archive.org/web/20050408192410/http://sw-shader.sourceforge.net/rasterizer.html, but im too dumb to implement the faster ones
|
// algorithm from https://web.archive.org/web/20050408192410/http://sw-shader.sourceforge.net/rasterizer.html, but im too dumb to implement the faster ones
|
||||||
|
// SAFETY: nNaN
|
||||||
if unsafe {
|
if unsafe {
|
||||||
(x1 - x2) * (F::new(y as f32) - y1) + (-(y1 - y2) * (F::new(x as f32) - x1))
|
(x1 - x2) * (F::new(y as f32) - y1) + (-(y1 - y2) * (F::new(x as f32) - x1))
|
||||||
> 0.
|
> 0.
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -35,6 +35,17 @@
|
||||||
//! - [`Image::repeated`]
|
//! - [`Image::repeated`]
|
||||||
//! - [`Image::overlay`](Overlay), [`Image::overlay_at`](OverlayAt), [`Image::overlay_blended`](BlendingOverlay)
|
//! - [`Image::overlay`](Overlay), [`Image::overlay_at`](OverlayAt), [`Image::overlay_blended`](BlendingOverlay)
|
||||||
//! - [`Image::blur`]
|
//! - [`Image::blur`]
|
||||||
|
//!
|
||||||
|
//! ## feature flags
|
||||||
|
//!
|
||||||
|
//! - `scale`: enables the [`scale`] module.
|
||||||
|
//! - `save`: enables [`Image::save`], via the [`png`](https://crates.io/crates/png) crate.
|
||||||
|
//! - `text`: enables [`Image::text`], via the [`fontdue`](https://crates.io/crates/fontdue) crate.
|
||||||
|
//! - `blur`: enables [`Image::blur`], via the [`stackblur`](https://crates.io/crates/stackblur-iter) crate.
|
||||||
|
//! - `real-show`: [`Image::show`], if the `save` feature is enabled, will, by default, simply open the appropriate image viewing program.
|
||||||
|
//! if, for some reason, this is inadequate/you dont have a good image viewer, enable the `real-show` feature to make [`Image::show`] open up a window of its own.
|
||||||
|
//! without the `real-show` feature, [`Image::show`] will save itself to your temp directory, which you may not want.
|
||||||
|
//! - `default`: \[`save`, `scale`\].
|
||||||
#![feature(
|
#![feature(
|
||||||
slice_swap_unchecked,
|
slice_swap_unchecked,
|
||||||
generic_const_exprs,
|
generic_const_exprs,
|
||||||
|
@ -75,6 +86,8 @@ mod overlay;
|
||||||
pub mod pixels;
|
pub mod pixels;
|
||||||
#[cfg(feature = "scale")]
|
#[cfg(feature = "scale")]
|
||||||
pub mod scale;
|
pub mod scale;
|
||||||
|
#[cfg(any(feature = "save", feature = "real-show"))]
|
||||||
|
mod show;
|
||||||
pub use cloner::ImageCloner;
|
pub use cloner::ImageCloner;
|
||||||
pub use overlay::{BlendingOverlay, ClonerOverlay, ClonerOverlayAt, Overlay, OverlayAt};
|
pub use overlay::{BlendingOverlay, ClonerOverlay, ClonerOverlayAt, Overlay, OverlayAt};
|
||||||
pub use r#dyn::DynImage;
|
pub use r#dyn::DynImage;
|
||||||
|
|
125
src/show.rs
Normal file
125
src/show.rs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
use crate::Image;
|
||||||
|
|
||||||
|
#[cfg(feature = "real-show")]
|
||||||
|
mod real {
|
||||||
|
use crate::Image;
|
||||||
|
use minifb::{Key, Window};
|
||||||
|
|
||||||
|
pub fn show(i: Image<&[u32], 1>) {
|
||||||
|
let mut win = Window::new(
|
||||||
|
"show",
|
||||||
|
i.width() as usize,
|
||||||
|
i.height() as usize,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
win.limit_update_rate(Some(std::time::Duration::from_millis(100)));
|
||||||
|
while win.is_open() && !win.is_key_down(Key::Q) && !win.is_key_down(Key::Escape) {
|
||||||
|
win.update_with_buffer(&i.buffer, i.width() as usize, i.height() as usize)
|
||||||
|
.expect("window update fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "real-show"))]
|
||||||
|
mod fake {
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
macro_rules! c {
|
||||||
|
($p:literal) => {
|
||||||
|
std::process::Command::new($p)
|
||||||
|
};
|
||||||
|
($p:literal $($args:expr)+) => {
|
||||||
|
std::process::Command::new($p).args([$($args,)+])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) use c;
|
||||||
|
|
||||||
|
pub fn has(c: &'static str) -> bool {
|
||||||
|
complete(c!("which").arg(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn complete(c: &mut Command) -> bool {
|
||||||
|
c.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.status()
|
||||||
|
.expect("ok")
|
||||||
|
.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! show {
|
||||||
|
($me:expr) => {
|
||||||
|
let file = std::env::temp_dir().join("viewing.png");
|
||||||
|
$me.save(&file);
|
||||||
|
#[cfg(target_family = "windows")]
|
||||||
|
assert!(fake::complete(fake::c!("start" "%Temp%/viewing.png")), "command should complete successfully.");
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
assert!(
|
||||||
|
if fake::has("feh") { fake::complete(fake::c!("feh" file))
|
||||||
|
} else if fake::has("xdg-open") { fake::complete(fake::c!("xdg-open" file))
|
||||||
|
} else if fake::has("gio") { fake::complete(fake::c!("gio" file))
|
||||||
|
} else if fake::has("gnome-open") { fake::complete(fake::c!("gnome-open" file))
|
||||||
|
} else if fake::has("kde-open") { fake::complete(fake::c!("kde-open" file))
|
||||||
|
} else if fake::has("open") { fake::complete(fake::c!("open" file))
|
||||||
|
} else { panic!("no image viewer found, please enable the `real-show` feature.") },
|
||||||
|
"command should complete successfully.");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
pub(crate) use show;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn r(i: &Image<Box<[u32]>, 1>) -> Image<&[u32], 1> {
|
||||||
|
// SAFETY: ctor
|
||||||
|
unsafe { Image::new(i.width, i.height, &*i.buffer) }
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! show {
|
||||||
|
($buf:ty) => {
|
||||||
|
show!($buf, 1);
|
||||||
|
show!($buf, 2);
|
||||||
|
show!($buf, 3);
|
||||||
|
show!($buf, 4);
|
||||||
|
};
|
||||||
|
($buf:ty, $n:literal) => {
|
||||||
|
impl Image<$buf, $n> {
|
||||||
|
/// Open a window showing this image.
|
||||||
|
/// Blocks until the window finishes.
|
||||||
|
///
|
||||||
|
/// This is like [`dbg!`] for images.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// if the window is un creatable
|
||||||
|
pub fn show(self) -> Self {
|
||||||
|
#[cfg(feature = "real-show")]
|
||||||
|
real::show(r(&self.as_ref().into()));
|
||||||
|
#[cfg(not(feature = "real-show"))]
|
||||||
|
fake::show!(self);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
show!(Vec<u8>);
|
||||||
|
show!(Box<[u8]>);
|
||||||
|
show!(&[u8]);
|
||||||
|
|
||||||
|
impl Image<Box<[u32]>, 1> {
|
||||||
|
/// Open a window showing this image.
|
||||||
|
/// Blocks until the window finishes.
|
||||||
|
///
|
||||||
|
/// This is like [`dbg!`] for images.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// if the window is un creatable
|
||||||
|
pub fn show(self) -> Self {
|
||||||
|
#[cfg(feature = "real-show")]
|
||||||
|
real::show(r(&self));
|
||||||
|
#[cfg(not(feature = "real-show"))]
|
||||||
|
fake::show!(Image::<Box<[u8]>, 4>::from(r(&self)));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue