Added support of some variants of ImageBuffer types form the image crate (#57).

This commit is contained in:
Kirill Kuzminykh
2026-01-03 01:43:03 +03:00
parent c0072f58ff
commit e2eaf9046e
4 changed files with 114 additions and 2 deletions
+7
View File
@@ -1,3 +1,10 @@
## [Unreleased] - ReleaseDate
### Added
- Added support of some variants of `ImageBuffer` types
form the `image` crate ([#57](https://github.com/Cykooz/fast_image_resize/issues/57)).
## [5.4.0] - 2025-11-28
### Added
+3
View File
@@ -34,6 +34,8 @@ rayon = { version = "1.11", optional = true }
## Enable this feature to implement traits [IntoImageView](crate::IntoImageView) and
## [IntoImageViewMut](crate::IntoImageViewMut) for the
## [DynamicImage](https://docs.rs/image/latest/image/enum.DynamicImage.html)
## type and some variants of
## [ImageBuffer](https://docs.rs/image/latest/image/struct.ImageBuffer.html)
## type from the `image` crate.
image = ["dep:image", "dep:bytemuck"]
## Enable this feature to implement traits [bytemuck::Pod] and
@@ -191,6 +193,7 @@ harness = false
[[bench]]
name = "bench_threads"
harness = false
required-features = ["rayon"]
+67 -1
View File
@@ -4,7 +4,10 @@ use crate::image_view::try_pixel_type;
use crate::images::{TypedImage, TypedImageRef};
use crate::{ImageView, ImageViewMut, IntoImageView, IntoImageViewMut, PixelTrait, PixelType};
use bytemuck::cast_slice_mut;
use image::DynamicImage;
use image::{
DynamicImage, GrayAlphaImage, GrayImage, ImageBuffer, Luma, LumaA, Rgb, Rgb32FImage, RgbImage,
Rgba, Rgba32FImage, RgbaImage,
};
impl IntoImageView for DynamicImage {
fn pixel_type(&self) -> Option<PixelType> {
@@ -77,3 +80,66 @@ fn image_as_bytes_mut(image: &mut DynamicImage) -> &mut [u8] {
_ => &mut [],
}
}
// Implementations for supported versions of ImageBuffer
macro_rules! impl_for_img_buffer {
($img_type:tt, $pixel_type:expr) => {
impl IntoImageView for $img_type {
fn pixel_type(&self) -> Option<PixelType> {
Some($pixel_type)
}
fn width(&self) -> u32 {
self.width()
}
fn height(&self) -> u32 {
self.height()
}
fn image_view<P: PixelTrait>(&self) -> Option<impl ImageView<Pixel = P>> {
if P::pixel_type() == $pixel_type {
let bytes = bytemuck::cast_slice(self.as_raw().as_ref());
return TypedImageRef::<P>::from_buffer(self.width(), self.height(), bytes)
.ok();
}
None
}
}
impl IntoImageViewMut for $img_type {
fn image_view_mut<P: PixelTrait>(&mut self) -> Option<impl ImageViewMut<Pixel = P>> {
if P::pixel_type() == $pixel_type {
return TypedImage::<P>::from_buffer(
self.width(),
self.height(),
cast_slice_mut((*self).deref_mut()),
)
.ok();
}
None
}
}
};
}
impl_for_img_buffer!(GrayImage, PixelType::U8);
impl_for_img_buffer!(GrayAlphaImage, PixelType::U8x2);
impl_for_img_buffer!(RgbImage, PixelType::U8x3);
impl_for_img_buffer!(RgbaImage, PixelType::U8x4);
type Gray16Image = ImageBuffer<Luma<u16>, Vec<u16>>;
impl_for_img_buffer!(Gray16Image, PixelType::U16);
type GrayAlpha16Image = ImageBuffer<LumaA<u16>, Vec<u16>>;
impl_for_img_buffer!(GrayAlpha16Image, PixelType::U16x2);
type Rgb16Image = ImageBuffer<Rgb<u16>, Vec<u16>>;
impl_for_img_buffer!(Rgb16Image, PixelType::U16x3);
type Rgba16Image = ImageBuffer<Rgba<u16>, Vec<u16>>;
impl_for_img_buffer!(Rgba16Image, PixelType::U16x4);
impl_for_img_buffer!(Rgb32FImage, PixelType::F32x3);
impl_for_img_buffer!(Rgba32FImage, PixelType::F32x4);
+37 -1
View File
@@ -3,9 +3,11 @@ use fast_image_resize::images::{
CroppedImage, CroppedImageMut, Image, ImageRef, TypedCroppedImage, TypedCroppedImageMut,
TypedImage, TypedImageRef,
};
use fast_image_resize::pixels::{U8x4, U8};
use fast_image_resize::pixels::{U8x3, U8x4, U8};
use fast_image_resize::{ImageView, IntoImageView, PixelType, ResizeOptions};
mod testing;
#[test]
fn create_image_ref_from_small_buffer() {
let width = 64;
@@ -271,3 +273,37 @@ fn use_bytemuck_to_create_typed_image_from_slice() {
let res = TypedImageRef::new(width, height, pixels);
assert!(res.is_ok());
}
#[cfg(feature = "image")]
mod support_of_image_crate {
use super::*;
use image::{DynamicImage, RgbImage};
use testing::PixelTestingExt;
#[test]
fn use_dynamic_image() {
let width = 64;
let height = 32;
let image_buffer = U8x3::load_small_image();
let src_dynamic_image: DynamicImage = image_buffer.into();
let mut dst_dynamic_image = DynamicImage::new_rgb8(width, height);
let mut resizer = fr::Resizer::new();
let res = resizer.resize(&src_dynamic_image, &mut dst_dynamic_image, None);
assert!(res.is_ok());
}
#[test]
fn use_image_buffer() {
let width = 64;
let height = 32;
let src_image_buffer = U8x3::load_small_image();
let mut dst_image_buffer = RgbImage::new(width, height);
let mut resizer = fr::Resizer::new();
let res = resizer.resize(&src_image_buffer, &mut dst_image_buffer, None);
assert!(res.is_ok());
}
}