mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-07 17:01:09 +00:00
- Updated versions of dependencies.
- Added test for creating TypedImage from slice with using `bytemuck`.
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
## [Unreleased] - ReleaseDate
|
||||
|
||||
### Added
|
||||
|
||||
- Added `bytemuck` feature and implemented some `bytemuck` traits for the `Pixel` type
|
||||
([#56](https://github.com/Cykooz/fast_image_resize/pull/56)).
|
||||
|
||||
## [5.3.0] - 2025-09-02
|
||||
|
||||
### Added
|
||||
|
||||
Generated
+370
-509
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -23,10 +23,10 @@ exclude = ["/data", "/.github"]
|
||||
cfg-if = "1.0"
|
||||
num-traits = "0.2.19"
|
||||
thiserror = "2.0"
|
||||
document-features = "0.2.11"
|
||||
document-features = "0.2.12"
|
||||
# Optional dependencies
|
||||
image = { version = "0.25.6", optional = true, default-features = false }
|
||||
bytemuck = { version = "1.23", optional = true }
|
||||
image = { version = "0.25.9", optional = true, default-features = false }
|
||||
bytemuck = { version = "1.24", optional = true }
|
||||
rayon = { version = "1.11", optional = true }
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ rayon = { version = "1.11", optional = true }
|
||||
## type from the `image` crate.
|
||||
image = ["dep:image", "dep:bytemuck"]
|
||||
## Enable this feature to implement traits [bytemuck::Pod] and
|
||||
## [bytemuck::Zeroable] for `Pixel` type.
|
||||
## [bytemuck::Zeroable] for the `Pixel` type.
|
||||
bytemuck = ["dep:bytemuck"]
|
||||
## This feature enables image processing in the ` rayon ` thread pool.
|
||||
rayon = ["dep:rayon", "resize/rayon", "image/rayon"]
|
||||
for_testing = ["image", "image/png"]
|
||||
for_testing = ["image", "image/png", "bytemuck"]
|
||||
only_u8x4 = [] # This can be used to experiment with the crate's code.
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ incremental = true
|
||||
opt-level = 3
|
||||
|
||||
|
||||
# release build for procmacros - same config as debug build for procmacros
|
||||
# release build for procmacros - the same config as debug build for procmacros
|
||||
[profile.release.build-override]
|
||||
opt-level = 2
|
||||
debug = false # when possible
|
||||
|
||||
@@ -133,7 +133,7 @@ pub(crate) fn precompute_coefficients(
|
||||
let cur_index = coeffs.len();
|
||||
let mut ww: f64 = 0.0;
|
||||
|
||||
// Optimisation for follow for-cycle:
|
||||
// Optimization for follow for-cycle:
|
||||
// (x + 0.5) - in_center => x - (in_center - 0.5) => x - center
|
||||
let center = in_center - 0.5;
|
||||
|
||||
@@ -144,7 +144,7 @@ pub(crate) fn precompute_coefficients(
|
||||
for x in x_min..x_max {
|
||||
let w: f64 = filter((x as f64 - center) * recip_filter_scale);
|
||||
if x == bound_start && w == 0. {
|
||||
// Don't use zero coefficients at the start of bound;
|
||||
// Don't use zero coefficients at the start of the bound;
|
||||
bound_start += 1;
|
||||
} else {
|
||||
coeffs.push(w);
|
||||
@@ -155,7 +155,7 @@ pub(crate) fn precompute_coefficients(
|
||||
if bound_end <= bound_start || c != 0. {
|
||||
break;
|
||||
}
|
||||
// Don't use zero coefficients at the end of bound;
|
||||
// Don't use zero coefficients at the end of the bound;
|
||||
bound_end -= 1;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ pub(crate) fn precompute_coefficients(
|
||||
// The sum of weights must be equal to 1.0.
|
||||
coeffs[cur_index..].iter_mut().for_each(|w| *w /= ww);
|
||||
}
|
||||
// Remaining values should stay empty if they are used despite x_max.
|
||||
// The remaining values should stay empty if they are used despite x_max.
|
||||
coeffs.resize(cur_index + window_size, 0.);
|
||||
bounds.push(Bound {
|
||||
start: bound_start,
|
||||
|
||||
+17
-13
@@ -40,7 +40,7 @@ impl PixelType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if given buffer is aligned by the alignment of pixel.
|
||||
/// Returns `true` if the given buffer has the same alignment as the pixel.
|
||||
pub(crate) fn is_aligned(&self, buffer: &[u8]) -> bool {
|
||||
match self {
|
||||
Self::U8 => true,
|
||||
@@ -64,7 +64,7 @@ pub trait GetCount {
|
||||
fn count() -> usize;
|
||||
}
|
||||
|
||||
/// Generic type to represent the number of components in single pixel.
|
||||
/// Generic type to represent the number of components in a single pixel.
|
||||
pub struct Count<const N: usize>;
|
||||
|
||||
impl<const N: usize> GetCount for Count<N> {
|
||||
@@ -87,7 +87,7 @@ impl<const N: usize> GetCountOfValues for Values<N> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about one component of pixel.
|
||||
/// Information about one component of a pixel.
|
||||
pub trait PixelComponent
|
||||
where
|
||||
Self: Sized + Copy + Debug + PartialEq + 'static,
|
||||
@@ -123,7 +123,7 @@ mod private {
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
/// Inner trait that provides additional information about pixel type.
|
||||
/// Inner trait that provides additional information about a pixel type.
|
||||
///
|
||||
/// Don't use this trait in your code. You must use the "child"
|
||||
/// trait [PixelTrait](crate::PixelTrait) instead.
|
||||
@@ -166,7 +166,7 @@ pub trait InnerPixel:
|
||||
size_of::<Self>()
|
||||
}
|
||||
|
||||
/// Create slice of pixel's components from slice of pixels
|
||||
/// Create a slice of pixel's components from a slice of pixels
|
||||
fn components(buf: &[Self]) -> &[Self::Component] {
|
||||
let size = buf.len() * Self::count_of_components();
|
||||
let components_ptr = buf.as_ptr() as *const Self::Component;
|
||||
@@ -210,22 +210,26 @@ where
|
||||
|
||||
// SAFETY: bytemuck derives are tripped by the use of generic arguments.
|
||||
// However, since Pixel<T, _, _> is repr(C) it introduces no padding after T nor
|
||||
// imposes any additional limitations on T. Hence, if T is Zeroable, Pixel is
|
||||
// imposes any additional limitations on T. Hence, if T is Zeroable, Pixel is
|
||||
// Zeroable.
|
||||
#[cfg(feature = "bytemuck")]
|
||||
unsafe impl<T: bytemuck::Zeroable, C, const COUNT_OF_COMPONENTS: usize>
|
||||
bytemuck::Zeroable for Pixel<T, C, COUNT_OF_COMPONENTS>
|
||||
unsafe impl<T: bytemuck::Zeroable, C, const COUNT_OF_COMPONENTS: usize> bytemuck::Zeroable
|
||||
for Pixel<T, C, COUNT_OF_COMPONENTS>
|
||||
where
|
||||
T: Sized + Copy + Clone + PartialEq + Default + 'static,
|
||||
C: PixelComponent {}
|
||||
C: PixelComponent,
|
||||
{
|
||||
}
|
||||
|
||||
// SAFETY: As above. If T is Pod than Pixel<T> is Pod.
|
||||
// SAFETY: As above. If T is Pod, then Pixel<T> is Pod.
|
||||
#[cfg(feature = "bytemuck")]
|
||||
unsafe impl<T: bytemuck::Pod, C, const COUNT_OF_COMPONENTS: usize>
|
||||
bytemuck::Pod for Pixel<T, C, COUNT_OF_COMPONENTS>
|
||||
unsafe impl<T: bytemuck::Pod, C, const COUNT_OF_COMPONENTS: usize> bytemuck::Pod
|
||||
for Pixel<T, C, COUNT_OF_COMPONENTS>
|
||||
where
|
||||
T: Sized + Copy + Clone + PartialEq + Default + 'static,
|
||||
C: PixelComponent {}
|
||||
C: PixelComponent,
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! pixel_struct {
|
||||
($name:ident, $type:tt, $comp_type:tt, $comp_count:literal, $pixel_type:expr, $doc:expr) => {
|
||||
|
||||
@@ -244,3 +244,21 @@ fn cropped_image_mut() {
|
||||
// Bottom border
|
||||
assert_eq!(dst_pixels[22 * row_size..], black_block);
|
||||
}
|
||||
|
||||
#[cfg(feature = "bytemuck")]
|
||||
#[test]
|
||||
fn use_bytemuck_to_create_typed_image_from_slice() {
|
||||
use bytemuck::{cast_slice, cast_slice_mut};
|
||||
|
||||
let width = 64;
|
||||
let height = 32;
|
||||
let mut buffer = vec![0u32; 65 * 32];
|
||||
|
||||
let pixels_mut: &mut [U8x4] = cast_slice_mut(&mut buffer);
|
||||
let res = TypedImage::from_pixels_slice(width, height, pixels_mut);
|
||||
assert!(res.is_ok());
|
||||
|
||||
let pixels: &[U8x4] = cast_slice(&buffer);
|
||||
let res = TypedImageRef::new(width, height, pixels);
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
|
||||
+28
-28
@@ -396,13 +396,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn downscale_u8() {
|
||||
type P = U8;
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [2920348]);
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [2939241]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[2923555],
|
||||
[2942035],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -410,13 +410,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn upscale_u8() {
|
||||
type P = U8;
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [1148754010]);
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [1156367834]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[1148811829],
|
||||
[1156403174],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -424,13 +424,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn downscale_u8x2() {
|
||||
type P = U8x2;
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [2920348, 6121802]);
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [2939241, 6121802]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[2923555, 6122718],
|
||||
[2942035, 6122718],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -441,14 +441,14 @@ mod not_u8x4 {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Nearest,
|
||||
CpuExtensions::None,
|
||||
[1146218632, 2364895380],
|
||||
[1151087734, 2364895380],
|
||||
);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[1146284886, 2364890085],
|
||||
[1151139254, 2364890085],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -508,13 +508,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn downscale_u16() {
|
||||
type P = U16;
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [750529436]);
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [755389581]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[751401243],
|
||||
[756141850],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -522,13 +522,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn upscale_u16() {
|
||||
type P = U16;
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [295229780570]);
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [297147816110]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[295246940755],
|
||||
[297159428939],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -539,14 +539,14 @@ mod not_u8x4 {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Nearest,
|
||||
CpuExtensions::None,
|
||||
[750529436, 1573303114],
|
||||
[755389581, 1573303114],
|
||||
);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[751401243, 1573563971],
|
||||
[756141850, 1573563971],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -557,14 +557,14 @@ mod not_u8x4 {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Nearest,
|
||||
CpuExtensions::None,
|
||||
[294578188424, 607778112660],
|
||||
[295819031151, 607778112660],
|
||||
);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[294597368766, 607776760273],
|
||||
[295834912005, 607776760273],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -645,13 +645,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn downscale_i32() {
|
||||
type P = I32;
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [24593724281554]);
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [24753100746016]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[36889044005199],
|
||||
[31386938242305],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -659,13 +659,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn upscale_i32() {
|
||||
type P = I32;
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [9674237252903955]);
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [9737127426058749]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[11090415545881916],
|
||||
[10691007188019666],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -674,13 +674,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn downscale_f32() {
|
||||
type P = F32;
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [28891951209032]);
|
||||
P::downscale_test(ResizeAlg::Nearest, CpuExtensions::None, [34175415677930]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[41687319249443],
|
||||
[40529868772858],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -688,13 +688,13 @@ mod not_u8x4 {
|
||||
#[test]
|
||||
fn upscale_f32() {
|
||||
type P = F32;
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [11165019414549868]);
|
||||
P::upscale_test(ResizeAlg::Nearest, CpuExtensions::None, [13281344839147584]);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[12506894762090128],
|
||||
[14128512150723561],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -706,14 +706,14 @@ mod not_u8x4 {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Nearest,
|
||||
CpuExtensions::None,
|
||||
[28891951209032, 26023210300788],
|
||||
[34175415677930, 26023210301282],
|
||||
);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::downscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[41687319249443, 29873206892121],
|
||||
[40529868772858, 29873206894014],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -724,14 +724,14 @@ mod not_u8x4 {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Nearest,
|
||||
CpuExtensions::None,
|
||||
[9941292360529429, 10060767588318486],
|
||||
[9944784041015554, 10060767588513729],
|
||||
);
|
||||
|
||||
for cpu_extensions in P::cpu_extensions() {
|
||||
P::upscale_test(
|
||||
ResizeAlg::Convolution(FilterType::Lanczos3),
|
||||
cpu_extensions,
|
||||
[10426687457795354, 10465695788378423],
|
||||
[10424760317415172, 10465695787559382],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user