mirror of
https://github.com/bend-n/fimg.git
synced 2024-12-21 18: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]
|
||||
name = "fimg"
|
||||
version = "0.4.41"
|
||||
version = "0.4.42"
|
||||
authors = ["bend-n <bend.n@outlook.com>"]
|
||||
license = "MIT"
|
||||
edition = "2021"
|
||||
|
@ -14,19 +14,19 @@ categories = ["multimedia::images", "graphics"]
|
|||
mattr = "0.0.2"
|
||||
png = { version = "0.17", features = ["unstable"], optional = true }
|
||||
fontdue = { version = "0.7.3", optional = true }
|
||||
vecto = "0.1.0"
|
||||
vecto = "0.1.1"
|
||||
umath = "0.0.7"
|
||||
fr = { version = "0.1.1", package = "fer", 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 = [
|
||||
"x11",
|
||||
"wayland",
|
||||
], 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 }
|
||||
libc = "0.2.153"
|
||||
libc = "0.2.154"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.53.0", features = [
|
||||
|
|
|
@ -78,6 +78,10 @@ impl<T: Copy, const C: usize> Builder<Box<[T]>, C> {
|
|||
/// seals the [`Buffer`] trait
|
||||
mod buf {
|
||||
/// 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 {
|
||||
#[doc(hidden)]
|
||||
fn len(&self) -> usize;
|
||||
|
|
105
src/lib.rs
105
src/lib.rs
|
@ -56,10 +56,8 @@
|
|||
slice_swap_unchecked,
|
||||
generic_const_exprs,
|
||||
iter_array_chunks,
|
||||
split_at_checked,
|
||||
core_intrinsics,
|
||||
slice_as_chunks,
|
||||
unchecked_math,
|
||||
slice_flatten,
|
||||
rustc_private,
|
||||
portable_simd,
|
||||
|
@ -320,6 +318,12 @@ impl<T, const CHANNELS: usize> Image<T, CHANNELS> {
|
|||
// SAFETY: we dont change anything, why check
|
||||
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> {
|
||||
|
@ -379,7 +383,7 @@ impl<const CHANNELS: usize, const N: usize> Image<[u8; N], CHANNELS> {
|
|||
/// Box this array image.
|
||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||
// 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.
|
||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||
// 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.
|
||||
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
|
||||
// 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<()>;
|
||||
}
|
||||
|
||||
/// 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.
|
||||
macro_rules! save {
|
||||
($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")]
|
||||
/// Open a PNG image
|
||||
pub fn open(f: impl AsRef<std::path::Path>) -> Self {
|
||||
use png::Transformations as T;
|
||||
let p = std::fs::File::open(f).unwrap();
|
||||
let r = std::io::BufReader::new(p);
|
||||
let mut dec = png::Decoder::new(r);
|
||||
match CHANNELS {
|
||||
1 | 3 => dec.set_transformations(T::STRIP_16 | T::EXPAND),
|
||||
2 | 4 => dec.set_transformations(T::STRIP_16 | T::ALPHA),
|
||||
_ => (),
|
||||
}
|
||||
let mut reader = dec.read_info().unwrap();
|
||||
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")
|
||||
let r = &mut std::io::BufReader::new(p);
|
||||
use core::intrinsics::transmute_unchecked as t;
|
||||
// SAFETY: ... this is idiotic.
|
||||
unsafe {
|
||||
match CHANNELS {
|
||||
1 => t(Image::<Box<_>, 1>::read(r).unwrap().unbox()),
|
||||
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()),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
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!(4 == Rgba("RGBA"));
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue