- Renamed TypedImage into TypedImageRef.

- Renamed `TypedImageMut` into `TypedImage`.
This commit is contained in:
Kirill Kuzminykh
2024-05-06 22:36:05 +03:00
parent 895ffc3f0c
commit 568af7f889
9 changed files with 124 additions and 116 deletions
+2 -2
View File
@@ -26,7 +26,7 @@ A lot of breaking changes have been done in this release:
- `resize_typed()` accepts references to `impl ImageView` and `impl ImageViewMut`.
- Resize methods also accept the `options` argument.
With the help of this argument, you can specify:
- resize algorithm;
- resize algorithm (default: Lanczos3);
- how to crop the source image;
- whether to multiply the source image by the alpha channel and
divide the destination image by the alpha channel.
@@ -40,7 +40,7 @@ A lot of breaking changes have been done in this release:
Now you can create and use zero-sized images.
- `Image` (embedded implementation of image container) moved from root of
the crate into module `images`.
- Added new image containers: `ImageRef`, `TypedImage`, `TypedImageMut`,
- Added new image containers: `ImageRef`, `TypedImageRef`, `TypedImage`,
`CroppedImage` and `CroppedImageMut`.
- Added optional feature "image".
It adds implementation of traits `IntoImageView` and `IntoImageViewMut` for the
+28 -42
View File
@@ -1,4 +1,4 @@
use crate::images::{TypedImage, TypedImageMut};
use crate::images::{BufferContainer, TypedImage, TypedImageRef};
use crate::pixels::InnerPixel;
use crate::{
ImageBufferError, ImageView, ImageViewMut, IntoImageView, IntoImageViewMut, PixelTrait,
@@ -15,7 +15,7 @@ pub struct ImageRef<'a> {
}
impl<'a> ImageRef<'a> {
/// Create an image with from slice with pixels data.
/// Create an image from slice with pixels-data.
pub fn new(
width: u32,
height: u32,
@@ -63,12 +63,12 @@ impl<'a> ImageRef<'a> {
self.buffer.into()
}
/// Get typed version of the image.
pub fn typed_image<P: InnerPixel>(&self) -> Option<TypedImage<P>> {
/// Get the typed version of the image.
pub fn typed_image<P: InnerPixel>(&self) -> Option<TypedImageRef<P>> {
if P::pixel_type() != self.pixel_type {
return None;
}
let typed_image = TypedImage::from_buffer(self.width, self.height, self.buffer).unwrap();
let typed_image = TypedImageRef::from_buffer(self.width, self.height, self.buffer).unwrap();
Some(typed_image)
}
}
@@ -91,27 +91,12 @@ impl<'a> IntoImageView for ImageRef<'a> {
}
}
#[derive(Debug)]
enum BufferContainer<'a> {
MutU8(&'a mut [u8]),
VecU8(Vec<u8>),
}
impl<'a> BufferContainer<'a> {
fn as_vec(&self) -> Vec<u8> {
match self {
Self::MutU8(slice) => slice.to_vec(),
Self::VecU8(vec) => vec.clone(),
}
}
}
/// Simple dynamic container of image data that provides [IntoImageView] and [IntoImageViewMut].
#[derive(Debug)]
pub struct Image<'a> {
width: u32,
height: u32,
buffer: BufferContainer<'a>,
buffer: BufferContainer<'a, u8>,
pixel_type: PixelType,
}
@@ -119,7 +104,7 @@ impl Image<'static> {
/// Create an empty image with given dimensions and pixel type.
pub fn new(width: u32, height: u32, pixel_type: PixelType) -> Self {
let pixels_count = width as usize * height as usize;
let buffer = BufferContainer::VecU8(vec![0; pixels_count * pixel_type.size()]);
let buffer = BufferContainer::Owned(vec![0; pixels_count * pixel_type.size()]);
Self {
width,
height,
@@ -145,7 +130,7 @@ impl Image<'static> {
Ok(Self {
width,
height,
buffer: BufferContainer::VecU8(buffer),
buffer: BufferContainer::Owned(buffer),
pixel_type,
})
}
@@ -169,7 +154,7 @@ impl<'a> Image<'a> {
Ok(Self {
width,
height,
buffer: BufferContainer::MutU8(buffer),
buffer: BufferContainer::Borrowed(buffer),
pixel_type,
})
}
@@ -193,8 +178,8 @@ impl<'a> Image<'a> {
#[inline]
pub fn buffer(&self) -> &[u8] {
match &self.buffer {
BufferContainer::MutU8(p) => p,
BufferContainer::VecU8(v) => v,
BufferContainer::Borrowed(p) => p,
BufferContainer::Owned(v) => v,
}
}
@@ -202,16 +187,16 @@ impl<'a> Image<'a> {
#[inline]
pub fn buffer_mut(&mut self) -> &mut [u8] {
match &mut self.buffer {
BufferContainer::MutU8(p) => p,
BufferContainer::VecU8(ref mut v) => v.as_mut_slice(),
BufferContainer::Borrowed(p) => p,
BufferContainer::Owned(ref mut v) => v.as_mut_slice(),
}
}
#[inline]
pub fn into_vec(self) -> Vec<u8> {
match self.buffer {
BufferContainer::MutU8(p) => p.into(),
BufferContainer::VecU8(v) => v,
BufferContainer::Borrowed(p) => p.into(),
BufferContainer::Owned(v) => v,
}
}
@@ -220,27 +205,28 @@ impl<'a> Image<'a> {
Image {
width: self.width,
height: self.height,
buffer: BufferContainer::VecU8(self.buffer.as_vec()),
buffer: BufferContainer::Owned(self.buffer.as_vec()),
pixel_type: self.pixel_type,
}
}
/// Get typed version of the image.
pub fn typed_image<P: InnerPixel>(&self) -> Option<TypedImage<P>> {
if P::pixel_type() != self.pixel_type {
return None;
}
let typed_image = TypedImage::from_buffer(self.width, self.height, self.buffer()).unwrap();
Some(typed_image)
}
/// Get typed mutable version of the image.
pub fn typed_image_mut<P: InnerPixel>(&mut self) -> Option<TypedImageMut<P>> {
pub fn typed_image<P: InnerPixel>(&self) -> Option<TypedImageRef<P>> {
if P::pixel_type() != self.pixel_type {
return None;
}
let typed_image =
TypedImageMut::from_buffer(self.width, self.height, self.buffer_mut()).unwrap();
TypedImageRef::from_buffer(self.width, self.height, self.buffer()).unwrap();
Some(typed_image)
}
/// Get typed mutable version of the image.
pub fn typed_image_mut<P: InnerPixel>(&mut self) -> Option<TypedImage<P>> {
if P::pixel_type() != self.pixel_type {
return None;
}
let typed_image =
TypedImage::from_buffer(self.width, self.height, self.buffer_mut()).unwrap();
Some(typed_image)
}
}
+8 -4
View File
@@ -4,7 +4,7 @@ use bytemuck::cast_slice_mut;
use image::DynamicImage;
use crate::image_view::try_pixel_type;
use crate::images::{TypedImage, TypedImageMut};
use crate::images::{TypedImage, TypedImageRef};
use crate::pixels::InnerPixel;
use crate::{ImageView, ImageViewMut, IntoImageView, IntoImageViewMut, PixelType};
@@ -34,8 +34,12 @@ impl IntoImageView for DynamicImage {
fn image_view<P: InnerPixel>(&self) -> Option<impl ImageView<Pixel = P>> {
if let Ok(pixel_type) = try_pixel_type(self) {
if P::pixel_type() == pixel_type {
return TypedImage::<P>::from_buffer(self.width(), self.height(), self.as_bytes())
.ok();
return TypedImageRef::<P>::from_buffer(
self.width(),
self.height(),
self.as_bytes(),
)
.ok();
}
}
None
@@ -46,7 +50,7 @@ impl IntoImageViewMut for DynamicImage {
fn image_view_mut<P: InnerPixel>(&mut self) -> Option<impl ImageViewMut<Pixel = P>> {
if let Ok(pixel_type) = try_pixel_type(self) {
if P::pixel_type() == pixel_type {
return TypedImageMut::<P>::from_buffer(
return TypedImage::<P>::from_buffer(
self.width(),
self.height(),
image_as_bytes_mut(self),
+31
View File
@@ -1,4 +1,6 @@
//! Contains different types of images and wrappers for them.
use std::fmt::Debug;
pub use cropped_image::*;
pub use dyn_image::*;
pub use typed_image::*;
@@ -9,3 +11,32 @@ mod typed_image;
#[cfg(feature = "image")]
mod image_crate;
#[derive(Debug)]
enum BufferContainer<'a, T: Copy + Debug> {
Borrowed(&'a mut [T]),
Owned(Vec<T>),
}
impl<'a, T: Copy + Debug> BufferContainer<'a, T> {
fn as_vec(&self) -> Vec<T> {
match self {
Self::Borrowed(slice) => slice.to_vec(),
Self::Owned(vec) => vec.clone(),
}
}
pub fn borrow(&self) -> &[T] {
match self {
Self::Borrowed(p_ref) => p_ref,
Self::Owned(vec) => vec,
}
}
pub fn borrow_mut(&mut self) -> &mut [T] {
match self {
Self::Borrowed(p_ref) => p_ref,
Self::Owned(vec) => vec,
}
}
}
+18 -41
View File
@@ -1,42 +1,19 @@
use std::fmt::Debug;
use crate::images::BufferContainer;
use crate::pixels::InnerPixel;
use crate::{ImageBufferError, ImageView, ImageViewMut, InvalidPixelsSliceSize};
/// Generic reference to image data that provides [ImageView].
#[derive(Debug)]
enum PixelsContainer<'a, P> {
Borrowed(&'a mut [P]),
Owned(Vec<P>),
}
impl<'a, P: InnerPixel> PixelsContainer<'a, P> {
pub fn borrow(&self) -> &[P] {
match self {
PixelsContainer::Borrowed(p_ref) => p_ref,
PixelsContainer::Owned(vec) => vec,
}
}
pub fn borrow_mut(&mut self) -> &mut [P] {
match self {
PixelsContainer::Borrowed(p_ref) => p_ref,
PixelsContainer::Owned(vec) => vec,
}
}
}
/// Generic image container that provides [ImageView].
#[derive(Debug)]
pub struct TypedImage<'a, P> {
pub struct TypedImageRef<'a, P> {
width: u32,
height: u32,
pixels: &'a [P],
}
impl<'a, P> TypedImage<'a, P> {
pub fn from_pixels(
width: u32,
height: u32,
pixels: &'a [P],
) -> Result<Self, InvalidPixelsSliceSize> {
impl<'a, P> TypedImageRef<'a, P> {
pub fn new(width: u32, height: u32, pixels: &'a [P]) -> Result<Self, InvalidPixelsSliceSize> {
let pixels_count = width as usize * height as usize;
if pixels.len() < pixels_count {
return Err(InvalidPixelsSliceSize);
@@ -54,11 +31,11 @@ impl<'a, P> TypedImage<'a, P> {
buffer: &'a [u8],
) -> Result<Self, ImageBufferError> {
let pixels = align_buffer_to(buffer)?;
Self::from_pixels(width, height, pixels).map_err(|_| ImageBufferError::InvalidBufferSize)
Self::new(width, height, pixels).map_err(|_| ImageBufferError::InvalidBufferSize)
}
}
unsafe impl<'a, P: InnerPixel> ImageView for TypedImage<'a, P> {
unsafe impl<'a, P: InnerPixel> ImageView for TypedImageRef<'a, P> {
type Pixel = P;
fn width(&self) -> u32 {
@@ -108,26 +85,26 @@ unsafe impl<'a, P: InnerPixel> ImageView for TypedImage<'a, P> {
}
}
/// Generic mutable image container that provides [ImageView] and [ImageViewMut].
/// Generic image container that provides [ImageView] and [ImageViewMut].
#[derive(Debug)]
pub struct TypedImageMut<'a, P: Default + Copy> {
pub struct TypedImage<'a, P: Default + Copy + Debug> {
width: u32,
height: u32,
pixels: PixelsContainer<'a, P>,
pixels: BufferContainer<'a, P>,
}
impl<P: Default + Copy> TypedImageMut<'static, P> {
impl<P: Default + Copy + Debug> TypedImage<'static, P> {
pub fn new(width: u32, height: u32) -> Self {
let pixels_count = width as usize * height as usize;
Self {
width,
height,
pixels: PixelsContainer::Owned(vec![P::default(); pixels_count]),
pixels: BufferContainer::Owned(vec![P::default(); pixels_count]),
}
}
}
impl<'a, P: InnerPixel> TypedImageMut<'a, P> {
impl<'a, P: InnerPixel> TypedImage<'a, P> {
pub fn from_pixels(
width: u32,
height: u32,
@@ -140,7 +117,7 @@ impl<'a, P: InnerPixel> TypedImageMut<'a, P> {
Ok(Self {
width,
height,
pixels: PixelsContainer::Borrowed(pixels),
pixels: BufferContainer::Borrowed(pixels),
})
}
@@ -158,7 +135,7 @@ impl<'a, P: InnerPixel> TypedImageMut<'a, P> {
}
}
unsafe impl<'a, P: InnerPixel> ImageView for TypedImageMut<'a, P> {
unsafe impl<'a, P: InnerPixel> ImageView for TypedImage<'a, P> {
type Pixel = P;
fn width(&self) -> u32 {
@@ -184,7 +161,7 @@ unsafe impl<'a, P: InnerPixel> ImageView for TypedImageMut<'a, P> {
}
}
unsafe impl<'a, P: InnerPixel> ImageViewMut for TypedImageMut<'a, P> {
unsafe impl<'a, P: InnerPixel> ImageViewMut for TypedImage<'a, P> {
fn iter_rows_mut(&mut self, start_row: u32) -> impl Iterator<Item = &mut [Self::Pixel]> {
let width = self.width as usize;
if width == 0 {
+3 -3
View File
@@ -1,7 +1,7 @@
use crate::convolution::{self, FilterType};
use crate::crop_box::CroppedSrcImageView;
use crate::image_view::{try_pixel_type, ImageView, ImageViewMut, IntoImageView, IntoImageViewMut};
use crate::images::TypedImageMut;
use crate::images::TypedImage;
use crate::pixels::{self, InnerPixel};
use crate::{
CpuExtensions, CropBox, DifferentDimensionsError, MulDiv, PixelTrait, PixelType, ResizeError,
@@ -500,7 +500,7 @@ fn get_temp_image_from_buffer<P: PixelTrait>(
buffer: &mut Vec<u8>,
width: u32,
height: u32,
) -> TypedImageMut<P> {
) -> TypedImage<P> {
let pixels_count = width as usize * height as usize;
// Add pixel size as gap for alignment of resulted buffer.
let buf_size = pixels_count * P::size() + P::size();
@@ -508,7 +508,7 @@ fn get_temp_image_from_buffer<P: PixelTrait>(
buffer.resize(buf_size, 0);
}
let pixels = unsafe { buffer.align_to_mut::<P>().1 };
TypedImageMut::from_pixels(width, height, &mut pixels[0..pixels_count]).unwrap()
TypedImage::from_pixels(width, height, &mut pixels[0..pixels_count]).unwrap()
}
fn resample_nearest<P: InnerPixel>(
+4 -4
View File
@@ -1,4 +1,4 @@
use fast_image_resize::images::{Image, TypedImage, TypedImageMut};
use fast_image_resize::images::{Image, TypedImage, TypedImageRef};
use fast_image_resize::{CpuExtensions, MulDiv, PixelTrait};
use testing::{cpu_ext_into_str, PixelTestingExt};
@@ -83,8 +83,8 @@ fn mul_div_alpha_test<P: PixelTrait>(
.collect();
let mut dst_pixels = src_pixels.clone();
let src_image = TypedImage::from_pixels(width, height, &src_pixels).unwrap();
let mut dst_image = TypedImageMut::from_pixels(width, height, &mut dst_pixels).unwrap();
let src_image = TypedImageRef::new(width, height, &src_pixels).unwrap();
let mut dst_image = TypedImage::from_pixels(width, height, &mut dst_pixels).unwrap();
let mut alpha_mul_div: MulDiv = Default::default();
unsafe {
@@ -125,7 +125,7 @@ fn mul_div_alpha_test<P: PixelTrait>(
// Inplace
let mut src_pixels_clone = src_pixels.clone();
let mut image = TypedImageMut::from_pixels(width, height, &mut src_pixels_clone).unwrap();
let mut image = TypedImage::from_pixels(width, height, &mut src_pixels_clone).unwrap();
match oper {
Oper::Mul => alpha_mul_div
+26 -16
View File
@@ -1,5 +1,5 @@
use fast_image_resize as fr;
use fast_image_resize::images::{CroppedImageMut, Image, ImageRef, TypedImage, TypedImageMut};
use fast_image_resize::images::{CroppedImageMut, Image, ImageRef, TypedImage, TypedImageRef};
use fast_image_resize::pixels::{U8x4, U8};
use fast_image_resize::{ImageView, ResizeOptions};
@@ -26,19 +26,6 @@ fn create_image_from_small_buffer() {
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
}
#[test]
fn create_typed_image_from_small_buffer() {
let width = 64;
let height = 32;
let mut buffer = vec![0; 64 * 30];
let res = TypedImageMut::<U8>::from_buffer(width, height, &mut buffer);
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
let res = TypedImage::<U8>::from_buffer(width, height, &buffer);
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
}
#[test]
fn create_image_from_big_buffer() {
let width = 64;
@@ -52,16 +39,39 @@ fn create_image_from_big_buffer() {
assert!(res.is_ok());
}
#[test]
fn create_type_image_ref_from_small_buffer() {
let width = 64;
let height = 32;
let buffer = vec![U8::new(0); 64 * 30];
let res = TypedImageRef::<U8>::new(width, height, &buffer);
assert!(matches!(res, Err(fr::InvalidPixelsSliceSize)));
}
#[test]
fn create_typed_image_from_small_buffer() {
let width = 64;
let height = 32;
let mut buffer = vec![0; 64 * 30];
let res = TypedImage::<U8>::from_buffer(width, height, &mut buffer);
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
let res = TypedImageRef::<U8>::from_buffer(width, height, &buffer);
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
}
#[test]
fn create_typed_image_from_big_buffer() {
let width = 64;
let height = 32;
let mut buffer = vec![0; 65 * 32];
let res = TypedImageMut::<U8>::from_buffer(width, height, &mut buffer);
let res = TypedImage::<U8>::from_buffer(width, height, &mut buffer);
assert!(res.is_ok());
let res = TypedImage::<U8>::from_buffer(width, height, &buffer);
let res = TypedImageRef::<U8>::from_buffer(width, height, &buffer);
assert!(res.is_ok());
}
+4 -4
View File
@@ -3,7 +3,7 @@ use std::fmt::Debug;
use image::io::Reader as ImageReader;
use fast_image_resize::images::{Image, TypedImage, TypedImageMut};
use fast_image_resize::images::{Image, TypedImage, TypedImageRef};
use fast_image_resize::pixels::*;
use fast_image_resize::{
testing as fr_testing, CpuExtensions, CropBoxError, Filter, FilterType, IntoImageView,
@@ -44,8 +44,8 @@ fn resize_to_same_size() {
.collect();
let src_image = Image::from_vec_u8(width, height, buffer, PixelType::U8x4).unwrap();
let mut dst_image = Image::new(width, height, PixelType::U8x4);
let src_view: TypedImage<U8x4> = src_image.typed_image().unwrap();
let mut dst_view: TypedImageMut<U8x4> = dst_image.typed_image_mut().unwrap();
let src_view: TypedImageRef<U8x4> = src_image.typed_image().unwrap();
let mut dst_view: TypedImage<U8x4> = dst_image.typed_image_mut().unwrap();
let mut resizer = Resizer::new();
resizer
.resize_typed(&src_view, &mut dst_view, None)
@@ -70,7 +70,7 @@ fn resize_to_same_size_after_cropping() {
let src_view = src_image.typed_image::<U8x4>().unwrap();
let mut dst_image = Image::new(width, height, PixelType::U8x4);
let mut dst_view: TypedImageMut<U8x4> = dst_image.typed_image_mut().unwrap();
let mut dst_view: TypedImage<U8x4> = dst_image.typed_image_mut().unwrap();
let mut resizer = Resizer::new();
let options = ResizeOptions::new().crop(10., 10., width as _, height as _);
resizer