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 }
|
||||
stackblur-iter = { version = "0.2.0", features = ["simd"], optional = true }
|
||||
clipline = "0.1.1"
|
||||
minifb = { version = "0.25.0", default-features = false, features = [
|
||||
"x11",
|
||||
"wayland",
|
||||
], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
iai = { git = "https://github.com/bend-n/iai.git" }
|
||||
|
@ -53,6 +57,7 @@ scale = ["fr"]
|
|||
save = ["png"]
|
||||
text = ["fontdue"]
|
||||
blur = ["stackblur-iter"]
|
||||
real-show = ["minifb"]
|
||||
default = ["save", "scale"]
|
||||
|
||||
[profile.release]
|
||||
|
|
|
@ -47,6 +47,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
|
|||
for y in ymin..ymax {
|
||||
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
|
||||
// SAFETY: nNaN
|
||||
if unsafe {
|
||||
(x1 - x2) * (F::new(y as f32) - y1) + (-(y1 - y2) * (F::new(x as f32) - x1))
|
||||
> 0.
|
||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -35,6 +35,17 @@
|
|||
//! - [`Image::repeated`]
|
||||
//! - [`Image::overlay`](Overlay), [`Image::overlay_at`](OverlayAt), [`Image::overlay_blended`](BlendingOverlay)
|
||||
//! - [`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(
|
||||
slice_swap_unchecked,
|
||||
generic_const_exprs,
|
||||
|
@ -75,6 +86,8 @@ mod overlay;
|
|||
pub mod pixels;
|
||||
#[cfg(feature = "scale")]
|
||||
pub mod scale;
|
||||
#[cfg(any(feature = "save", feature = "real-show"))]
|
||||
mod show;
|
||||
pub use cloner::ImageCloner;
|
||||
pub use overlay::{BlendingOverlay, ClonerOverlay, ClonerOverlayAt, Overlay, OverlayAt};
|
||||
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