mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-22 02:28:19 -06:00
some small changes
This commit is contained in:
parent
3a1b6a3435
commit
0dffa5bc99
10
Cargo.toml
10
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "fimg"
|
name = "fimg"
|
||||||
version = "0.4.41"
|
version = "0.4.42"
|
||||||
authors = ["bend-n <bend.n@outlook.com>"]
|
authors = ["bend-n <bend.n@outlook.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -14,19 +14,19 @@ categories = ["multimedia::images", "graphics"]
|
||||||
mattr = "0.0.2"
|
mattr = "0.0.2"
|
||||||
png = { version = "0.17", features = ["unstable"], optional = true }
|
png = { version = "0.17", features = ["unstable"], optional = true }
|
||||||
fontdue = { version = "0.7.3", optional = true }
|
fontdue = { version = "0.7.3", optional = true }
|
||||||
vecto = "0.1.0"
|
vecto = "0.1.1"
|
||||||
umath = "0.0.7"
|
umath = "0.0.7"
|
||||||
fr = { version = "0.1.1", package = "fer", optional = true }
|
fr = { version = "0.1.1", package = "fer", optional = true }
|
||||||
slur = { version = "0.1.0", optional = true }
|
slur = { version = "0.1.0", optional = true }
|
||||||
clipline = "0.1.1"
|
clipline = "0.1.2"
|
||||||
minifb = { version = "0.25.0", default-features = false, features = [
|
minifb = { version = "0.25.0", default-features = false, features = [
|
||||||
"x11",
|
"x11",
|
||||||
"wayland",
|
"wayland",
|
||||||
], optional = true }
|
], optional = true }
|
||||||
wgpu = { version = "0.19.1", default-features = false, optional = true }
|
wgpu = { version = "0.19.1", default-features = false, optional = true }
|
||||||
atools = "0.1.0"
|
atools = "0.1.4"
|
||||||
qwant = { version = "1.0.0", optional = true }
|
qwant = { version = "1.0.0", optional = true }
|
||||||
libc = "0.2.153"
|
libc = "0.2.154"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows = { version = "0.53.0", features = [
|
windows = { version = "0.53.0", features = [
|
||||||
|
|
|
@ -78,6 +78,10 @@ impl<T: Copy, const C: usize> Builder<Box<[T]>, C> {
|
||||||
/// seals the [`Buffer`] trait
|
/// seals the [`Buffer`] trait
|
||||||
mod buf {
|
mod buf {
|
||||||
/// A valid buffer for use in the builder
|
/// A valid buffer for use in the builder
|
||||||
|
#[diagnostic::on_unimplemented(
|
||||||
|
message = "this type is not a buffer",
|
||||||
|
note = "if you think this type is a buffer, please open an issue.\nYou can manually circumvent this warning via Image::new."
|
||||||
|
)]
|
||||||
pub trait Buffer {
|
pub trait Buffer {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn len(&self) -> usize;
|
fn len(&self) -> usize;
|
||||||
|
|
107
src/lib.rs
107
src/lib.rs
|
@ -56,10 +56,8 @@
|
||||||
slice_swap_unchecked,
|
slice_swap_unchecked,
|
||||||
generic_const_exprs,
|
generic_const_exprs,
|
||||||
iter_array_chunks,
|
iter_array_chunks,
|
||||||
split_at_checked,
|
|
||||||
core_intrinsics,
|
core_intrinsics,
|
||||||
slice_as_chunks,
|
slice_as_chunks,
|
||||||
unchecked_math,
|
|
||||||
slice_flatten,
|
slice_flatten,
|
||||||
rustc_private,
|
rustc_private,
|
||||||
portable_simd,
|
portable_simd,
|
||||||
|
@ -320,6 +318,12 @@ impl<T, const CHANNELS: usize> Image<T, CHANNELS> {
|
||||||
// SAFETY: we dont change anything, why check
|
// SAFETY: we dont change anything, why check
|
||||||
unsafe { Image::new(self.width, self.height, f(self.buffer)) }
|
unsafe { Image::new(self.width, self.height, f(self.buffer)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
/// buffer size must be the same.
|
||||||
|
unsafe fn map_into<U: From<T>, const N: usize>(self) -> Image<U, N> {
|
||||||
|
unsafe { self.mapped(Into::into) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const CHANNELS: usize, T: Clone> Image<&[T], CHANNELS> {
|
impl<const CHANNELS: usize, T: Clone> Image<&[T], CHANNELS> {
|
||||||
|
@ -379,7 +383,7 @@ impl<const CHANNELS: usize, const N: usize> Image<[u8; N], CHANNELS> {
|
||||||
/// Box this array image.
|
/// Box this array image.
|
||||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||||
// SAFETY: size not changed
|
// SAFETY: size not changed
|
||||||
unsafe { self.mapped(|b| b.into()) }
|
unsafe { self.map_into() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +391,7 @@ impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
|
||||||
/// Box this image.
|
/// Box this image.
|
||||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||||
// SAFETY: size not changed
|
// SAFETY: size not changed
|
||||||
unsafe { self.mapped(|b| b.into()) }
|
unsafe { self.map_into() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +399,15 @@ impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
|
||||||
/// Box this owned image.
|
/// Box this owned image.
|
||||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||||
// SAFETY: ctor
|
// SAFETY: ctor
|
||||||
unsafe { self.mapped(|b| b.into()) }
|
unsafe { self.map_into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const CHANNELS: usize> Image<Box<[u8]>, CHANNELS> {
|
||||||
|
/// Unbox this vec image.
|
||||||
|
pub fn unbox(self) -> Image<Vec<u8>, CHANNELS> {
|
||||||
|
// SAFETY: ctor
|
||||||
|
unsafe { self.map_into() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,6 +636,16 @@ pub trait WritePng {
|
||||||
fn write(&self, f: &mut impl std::io::Write) -> std::io::Result<()>;
|
fn write(&self, f: &mut impl std::io::Write) -> std::io::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read png.
|
||||||
|
#[cfg(feature = "save")]
|
||||||
|
pub trait ReadPng
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
/// Read a png into an image.
|
||||||
|
fn read(f: &mut impl std::io::Read) -> std::io::Result<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
/// helper macro for defining the save() method.
|
/// helper macro for defining the save() method.
|
||||||
macro_rules! save {
|
macro_rules! save {
|
||||||
($channels:literal == $clr:ident ($clrhuman:literal)) => {
|
($channels:literal == $clr:ident ($clrhuman:literal)) => {
|
||||||
|
@ -663,34 +685,67 @@ macro_rules! save {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
|
macro_rules! read {
|
||||||
|
($n:literal) => {
|
||||||
|
#[cfg(feature = "save")]
|
||||||
|
impl ReadPng for Image<Box<[u8]>, $n> {
|
||||||
|
/// Open a PNG image
|
||||||
|
fn read(f: &mut impl std::io::Read) -> std::io::Result<Self> {
|
||||||
|
use png::Transformations as T;
|
||||||
|
let mut dec = png::Decoder::new(f);
|
||||||
|
match $n {
|
||||||
|
1 | 3 => dec.set_transformations(T::STRIP_16 | T::EXPAND),
|
||||||
|
2 | 4 => dec.set_transformations(T::STRIP_16 | T::ALPHA), // alpha implies expand
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
let mut reader = dec.read_info()?;
|
||||||
|
let mut buf = vec![0; reader.output_buffer_size()].into_boxed_slice();
|
||||||
|
let info = reader.next_frame(&mut buf)?;
|
||||||
|
use png::ColorType::*;
|
||||||
|
macro_rules! n {
|
||||||
|
($x:literal) => {
|
||||||
|
Image::<_, $x>::build(info.width, info.height)
|
||||||
|
.buf(buf)
|
||||||
|
.into()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(match info.color_type {
|
||||||
|
Indexed => unreachable!(), // see EXPAND
|
||||||
|
Grayscale => n![1],
|
||||||
|
GrayscaleAlpha => n![2],
|
||||||
|
Rgb => n![3],
|
||||||
|
Rgba => n![4],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS>
|
||||||
|
where
|
||||||
|
[(); { (CHANNELS <= 4) as usize } - 1]:,
|
||||||
|
{
|
||||||
#[cfg(feature = "save")]
|
#[cfg(feature = "save")]
|
||||||
/// Open a PNG image
|
/// Open a PNG image
|
||||||
pub fn open(f: impl AsRef<std::path::Path>) -> Self {
|
pub fn open(f: impl AsRef<std::path::Path>) -> Self {
|
||||||
use png::Transformations as T;
|
|
||||||
let p = std::fs::File::open(f).unwrap();
|
let p = std::fs::File::open(f).unwrap();
|
||||||
let r = std::io::BufReader::new(p);
|
let r = &mut std::io::BufReader::new(p);
|
||||||
let mut dec = png::Decoder::new(r);
|
use core::intrinsics::transmute_unchecked as t;
|
||||||
|
// SAFETY: ... this is idiotic.
|
||||||
|
unsafe {
|
||||||
match CHANNELS {
|
match CHANNELS {
|
||||||
1 | 3 => dec.set_transformations(T::STRIP_16 | T::EXPAND),
|
1 => t(Image::<Box<_>, 1>::read(r).unwrap().unbox()),
|
||||||
2 | 4 => dec.set_transformations(T::STRIP_16 | T::ALPHA),
|
2 => t(Image::<Box<_>, 2>::read(r).unwrap().unbox()),
|
||||||
_ => (),
|
3 => t(Image::<Box<_>, 3>::read(r).unwrap().unbox()),
|
||||||
}
|
4 => t(Image::<Box<_>, 4>::read(r).unwrap().unbox()),
|
||||||
let mut reader = dec.read_info().unwrap();
|
_ => unreachable!(),
|
||||||
let mut buf = vec![0; reader.output_buffer_size()];
|
|
||||||
let info = reader.next_frame(&mut buf).unwrap();
|
|
||||||
use png::ColorType::*;
|
|
||||||
match info.color_type {
|
|
||||||
Indexed | Grayscale => {
|
|
||||||
assert_eq!(CHANNELS, 1, "indexed | grayscale requires one channel")
|
|
||||||
}
|
|
||||||
Rgb => assert_eq!(CHANNELS, 3, "rgb requires three channels"),
|
|
||||||
Rgba => assert_eq!(CHANNELS, 4, "rgba requires four channels"),
|
|
||||||
GrayscaleAlpha => assert_eq!(CHANNELS, 2, "ya requires two channels"),
|
|
||||||
}
|
|
||||||
Self::build(info.width, info.height).buf(buf)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read!(1);
|
||||||
|
read!(2);
|
||||||
|
read!(3);
|
||||||
|
read!(4);
|
||||||
|
|
||||||
save!(3 == Rgb("RGB"));
|
save!(3 == Rgb("RGB"));
|
||||||
save!(4 == Rgba("RGBA"));
|
save!(4 == Rgba("RGBA"));
|
||||||
|
|
Loading…
Reference in a new issue