1use crate::alpha_check::has_non_constant_cap_alpha_rgba_f32;
30#[cfg(feature = "nightly_f16")]
31use crate::alpha_handle_f16::{premultiply_alpha_rgba_f16, unpremultiply_alpha_rgba_f16};
32use crate::alpha_handle_f32::{premultiply_alpha_rgba_f32, unpremultiply_alpha_rgba_f32};
33use crate::alpha_handle_u16::{premultiply_alpha_rgba_u16, unpremultiply_alpha_rgba_u16};
34use crate::alpha_handle_u8::{premultiply_alpha_rgba, unpremultiply_alpha_rgba};
35use crate::pic_scale_error::{PicScaleBufferMismatch, PicScaleError};
36use crate::ImageSize;
37#[cfg(feature = "nightly_f16")]
38use core::f16;
39use rayon::ThreadPool;
40use std::borrow::Cow;
41use std::fmt::Debug;
42
43#[derive(Debug, Clone)]
53pub struct ImageStore<'a, T, const N: usize>
54where
55 T: Clone + Copy + Debug,
56{
57 pub buffer: std::borrow::Cow<'a, [T]>,
58 pub channels: usize,
60 pub width: usize,
62 pub height: usize,
64 pub stride: usize,
66 pub bit_depth: usize,
68}
69
70#[derive(Debug)]
80pub struct ImageStoreMut<'a, T, const N: usize>
81where
82 T: Clone + Copy + Debug,
83{
84 pub buffer: BufferStore<'a, T>,
85 pub channels: usize,
87 pub width: usize,
89 pub height: usize,
91 pub stride: usize,
93 pub bit_depth: usize,
95}
96
97pub(crate) trait CheckStoreDensity {
98 fn should_have_bit_depth(&self) -> bool;
99}
100
101#[derive(Debug)]
102pub enum BufferStore<'a, T: Copy + Debug> {
103 Borrowed(&'a mut [T]),
104 Owned(Vec<T>),
105}
106
107impl<T: Copy + Debug> BufferStore<'_, T> {
108 #[allow(clippy::should_implement_trait)]
109 pub fn borrow(&self) -> &[T] {
110 match self {
111 Self::Borrowed(p_ref) => p_ref,
112 Self::Owned(vec) => vec,
113 }
114 }
115
116 #[allow(clippy::should_implement_trait)]
117 pub fn borrow_mut(&mut self) -> &mut [T] {
118 match self {
119 Self::Borrowed(p_ref) => p_ref,
120 Self::Owned(vec) => vec,
121 }
122 }
123}
124
125impl<'a, T, const N: usize> ImageStore<'a, T, N>
126where
127 T: Clone + Copy + Debug + Default,
128{
129 pub fn new(
130 slice_ref: Vec<T>,
131 width: usize,
132 height: usize,
133 ) -> Result<ImageStore<'a, T, N>, PicScaleError> {
134 let expected_size = width * height * N;
135 if slice_ref.len() != width * height * N {
136 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
137 expected: expected_size,
138 width,
139 height,
140 channels: N,
141 slice_len: slice_ref.len(),
142 }));
143 }
144 Ok(ImageStore::<T, N> {
145 buffer: std::borrow::Cow::Owned(slice_ref),
146 channels: N,
147 width,
148 height,
149 stride: width * N,
150 bit_depth: 0,
151 })
152 }
153
154 pub fn borrow(
155 slice_ref: &'a [T],
156 width: usize,
157 height: usize,
158 ) -> Result<ImageStore<'a, T, N>, PicScaleError> {
159 let expected_size = width * height * N;
160 if slice_ref.len() != width * height * N {
161 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
162 expected: expected_size,
163 width,
164 height,
165 channels: N,
166 slice_len: slice_ref.len(),
167 }));
168 }
169 Ok(ImageStore::<T, N> {
170 buffer: Cow::Borrowed(slice_ref),
171 channels: N,
172 width,
173 height,
174 stride: width * N,
175 bit_depth: 0,
176 })
177 }
178
179 pub fn alloc(width: usize, height: usize) -> ImageStore<'a, T, N> {
180 let vc = vec![T::default(); width * N * height];
181 ImageStore::<T, N> {
182 buffer: std::borrow::Cow::Owned(vc),
183 channels: N,
184 width,
185 height,
186 stride: width * N,
187 bit_depth: 0,
188 }
189 }
190}
191
192impl<const N: usize> CheckStoreDensity for ImageStoreMut<'_, u8, N> {
193 fn should_have_bit_depth(&self) -> bool {
194 false
195 }
196}
197
198impl<const N: usize> CheckStoreDensity for ImageStoreMut<'_, f32, N> {
199 fn should_have_bit_depth(&self) -> bool {
200 false
201 }
202}
203
204#[cfg(feature = "nightly_f16")]
205impl<const N: usize> CheckStoreDensity for ImageStoreMut<'_, f16, N> {
206 fn should_have_bit_depth(&self) -> bool {
207 false
208 }
209}
210
211impl<const N: usize> CheckStoreDensity for ImageStoreMut<'_, u16, N> {
212 fn should_have_bit_depth(&self) -> bool {
213 true
214 }
215}
216
217impl<T, const N: usize> ImageStoreMut<'_, T, N>
218where
219 T: Clone + Copy + Debug + Default,
220{
221 pub(crate) fn validate(&self) -> Result<(), PicScaleError> {
222 let expected_size = self.stride() * self.height;
223 if self.buffer.borrow().len() != self.stride() * self.height {
224 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
225 expected: expected_size,
226 width: self.width,
227 height: self.height,
228 channels: N,
229 slice_len: self.buffer.borrow().len(),
230 }));
231 }
232 if self.stride < self.width * N {
233 return Err(PicScaleError::InvalidStride(self.width * N, self.stride));
234 }
235 Ok(())
236 }
237}
238
239impl<T, const N: usize> ImageStore<'_, T, N>
240where
241 T: Clone + Copy + Debug + Default,
242{
243 pub(crate) fn validate(&self) -> Result<(), PicScaleError> {
244 let expected_size = self.stride() * self.height;
245 if self.buffer.as_ref().len() != self.stride() * self.height {
246 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
247 expected: expected_size,
248 width: self.width,
249 height: self.height,
250 channels: N,
251 slice_len: self.buffer.as_ref().len(),
252 }));
253 }
254 if self.stride < self.width * N {
255 return Err(PicScaleError::InvalidStride(self.width * N, self.stride));
256 }
257 Ok(())
258 }
259}
260
261impl<'a, T, const N: usize> ImageStoreMut<'a, T, N>
262where
263 T: Clone + Copy + Debug + Default,
264{
265 pub fn new(
269 slice_ref: Vec<T>,
270 width: usize,
271 height: usize,
272 ) -> Result<ImageStoreMut<'a, T, N>, PicScaleError> {
273 let expected_size = width * height * N;
274 if slice_ref.len() != width * height * N {
275 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
276 expected: expected_size,
277 width,
278 height,
279 channels: N,
280 slice_len: slice_ref.len(),
281 }));
282 }
283 Ok(ImageStoreMut::<T, N> {
284 buffer: BufferStore::Owned(slice_ref),
285 channels: N,
286 width,
287 height,
288 stride: width * N,
289 bit_depth: 0,
290 })
291 }
292
293 pub fn borrow(
297 slice_ref: &'a mut [T],
298 width: usize,
299 height: usize,
300 ) -> Result<ImageStoreMut<'a, T, N>, PicScaleError> {
301 let expected_size = width * height * N;
302 if slice_ref.len() != width * height * N {
303 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
304 expected: expected_size,
305 width,
306 height,
307 channels: N,
308 slice_len: slice_ref.len(),
309 }));
310 }
311 Ok(ImageStoreMut::<T, N> {
312 buffer: BufferStore::Borrowed(slice_ref),
313 channels: N,
314 width,
315 height,
316 stride: width * N,
317 bit_depth: 0,
318 })
319 }
320
321 pub fn alloc(width: usize, height: usize) -> ImageStoreMut<'a, T, N> {
325 let vc = vec![T::default(); width * N * height];
326 ImageStoreMut::<T, N> {
327 buffer: BufferStore::Owned(vc),
328 channels: N,
329 width,
330 height,
331 stride: width * N,
332 bit_depth: 0,
333 }
334 }
335
336 pub fn alloc_with_depth(
338 width: usize,
339 height: usize,
340 bit_depth: usize,
341 ) -> ImageStoreMut<'a, T, N> {
342 let vc = vec![T::default(); width * N * height];
343 ImageStoreMut::<T, N> {
344 buffer: BufferStore::Owned(vc),
345 channels: N,
346 width,
347 height,
348 stride: width * N,
349 bit_depth,
350 }
351 }
352}
353
354impl<T, const N: usize> ImageStoreMut<'_, T, N>
355where
356 T: Clone + Copy + Debug,
357{
358 #[inline]
362 pub fn stride(&self) -> usize {
363 if self.stride == 0 {
364 return self.width * N;
365 }
366 self.stride
367 }
368}
369
370impl<T, const N: usize> ImageStore<'_, T, N>
371where
372 T: Clone + Copy + Debug,
373{
374 #[inline]
378 pub fn stride(&self) -> usize {
379 if self.stride == 0 {
380 return self.width * N;
381 }
382 self.stride
383 }
384}
385
386impl<'a, T, const N: usize> ImageStore<'a, T, N>
387where
388 T: Clone + Copy + Debug,
389{
390 pub fn get_size(&self) -> ImageSize {
392 ImageSize::new(self.width, self.height)
393 }
394
395 pub fn as_bytes(&self) -> &[T] {
396 match &self.buffer {
397 Cow::Borrowed(br) => br,
398 Cow::Owned(v) => v.as_ref(),
399 }
400 }
401
402 pub fn from_slice(
403 slice_ref: &'a [T],
404 width: usize,
405 height: usize,
406 ) -> Result<ImageStore<'a, T, N>, PicScaleError> {
407 let expected_size = width * height * N;
408 if slice_ref.len() != width * height * N {
409 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
410 expected: expected_size,
411 width,
412 height,
413 channels: N,
414 slice_len: slice_ref.len(),
415 }));
416 }
417 Ok(ImageStore::<T, N> {
418 buffer: std::borrow::Cow::Borrowed(slice_ref),
419 channels: N,
420 width,
421 height,
422 stride: width * N,
423 bit_depth: 0,
424 })
425 }
426
427 pub fn copied<'b>(&self) -> ImageStore<'b, T, N> {
428 ImageStore::<T, N> {
429 buffer: std::borrow::Cow::Owned(self.buffer.as_ref().to_vec()),
430 channels: N,
431 width: self.width,
432 height: self.height,
433 stride: self.width * N,
434 bit_depth: self.bit_depth,
435 }
436 }
437
438 pub fn copied_to_mut(&self, into: &mut ImageStoreMut<T, N>) {
439 let into_stride = into.stride();
440 for (src_row, dst_row) in self
441 .buffer
442 .as_ref()
443 .chunks_exact(self.stride())
444 .zip(into.buffer.borrow_mut().chunks_exact_mut(into_stride))
445 {
446 for (&src, dst) in src_row.iter().zip(dst_row.iter_mut()) {
447 *dst = src;
448 }
449 }
450 }
451}
452
453impl<'a, T, const N: usize> ImageStoreMut<'a, T, N>
454where
455 T: Clone + Copy + Debug,
456{
457 pub fn get_size(&self) -> ImageSize {
459 ImageSize::new(self.width, self.height)
460 }
461
462 pub fn as_bytes(&self) -> &[T] {
463 match &self.buffer {
464 BufferStore::Borrowed(p) => p,
465 BufferStore::Owned(v) => v,
466 }
467 }
468
469 pub fn from_slice(
470 slice_ref: &'a mut [T],
471 width: usize,
472 height: usize,
473 ) -> Result<ImageStoreMut<'a, T, N>, PicScaleError> {
474 let expected_size = width * height * N;
475 if slice_ref.len() != width * height * N {
476 return Err(PicScaleError::BufferMismatch(PicScaleBufferMismatch {
477 expected: expected_size,
478 width,
479 height,
480 channels: N,
481 slice_len: slice_ref.len(),
482 }));
483 }
484 Ok(ImageStoreMut::<T, N> {
485 buffer: BufferStore::Borrowed(slice_ref),
486 channels: N,
487 width,
488 height,
489 stride: width * N,
490 bit_depth: 0,
491 })
492 }
493
494 pub fn copied<'b>(&self) -> ImageStoreMut<'b, T, N> {
495 ImageStoreMut::<T, N> {
496 buffer: BufferStore::Owned(self.buffer.borrow().to_vec()),
497 channels: N,
498 width: self.width,
499 height: self.height,
500 stride: self.width * N,
501 bit_depth: self.bit_depth,
502 }
503 }
504
505 pub fn to_immutable(&self) -> ImageStore<'_, T, N> {
506 ImageStore::<T, N> {
507 buffer: std::borrow::Cow::Owned(self.buffer.borrow().to_owned()),
508 channels: N,
509 width: self.width,
510 height: self.height,
511 stride: self.width * N,
512 bit_depth: self.bit_depth,
513 }
514 }
515}
516
517pub(crate) trait AssociateAlpha<T: Clone + Copy + Debug, const N: usize> {
518 fn premultiply_alpha(&self, into: &mut ImageStoreMut<'_, T, N>, pool: &Option<ThreadPool>);
519 fn is_alpha_premultiplication_needed(&self) -> bool;
520}
521
522pub(crate) trait UnassociateAlpha<T: Clone + Copy + Debug, const N: usize> {
523 fn unpremultiply_alpha(&mut self, pool: &Option<ThreadPool>);
524}
525
526impl AssociateAlpha<u8, 4> for ImageStore<'_, u8, 4> {
527 fn premultiply_alpha(&self, into: &mut ImageStoreMut<'_, u8, 4>, pool: &Option<ThreadPool>) {
528 let dst_stride = into.stride();
529 let dst = into.buffer.borrow_mut();
530 let src = self.buffer.as_ref();
531 premultiply_alpha_rgba(
532 dst,
533 dst_stride,
534 src,
535 self.width,
536 self.height,
537 self.stride(),
538 pool,
539 );
540 }
541
542 #[cfg(not(any(
543 any(target_arch = "x86_64", target_arch = "x86"),
544 all(target_arch = "aarch64", target_feature = "neon")
545 )))]
546 fn is_alpha_premultiplication_needed(&self) -> bool {
547 use crate::alpha_check::has_non_constant_cap_alpha_rgba8;
548 has_non_constant_cap_alpha_rgba8(self.buffer.as_ref(), self.width, self.stride())
549 }
550
551 #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
552 fn is_alpha_premultiplication_needed(&self) -> bool {
553 use crate::neon::neon_has_non_constant_cap_alpha_rgba8;
554 neon_has_non_constant_cap_alpha_rgba8(self.buffer.as_ref(), self.width, self.stride())
555 }
556
557 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
558 fn is_alpha_premultiplication_needed(&self) -> bool {
559 use crate::alpha_check::has_non_constant_cap_alpha_rgba8;
560 #[cfg(feature = "sse")]
561 use crate::sse::sse_has_non_constant_cap_alpha_rgba8;
562 #[cfg(all(target_arch = "x86_64", feature = "nightly_avx512"))]
563 if std::arch::is_x86_feature_detected!("avx512bw") {
564 use crate::avx512::avx512_has_non_constant_cap_alpha_rgba8;
565 return avx512_has_non_constant_cap_alpha_rgba8(
566 self.buffer.as_ref(),
567 self.width,
568 self.stride(),
569 );
570 }
571 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
572 if std::arch::is_x86_feature_detected!("avx2") {
573 use crate::avx2::avx_has_non_constant_cap_alpha_rgba8;
574 return avx_has_non_constant_cap_alpha_rgba8(
575 self.buffer.as_ref(),
576 self.width,
577 self.stride(),
578 );
579 }
580 #[cfg(feature = "sse")]
581 if std::arch::is_x86_feature_detected!("sse4.1") {
582 return sse_has_non_constant_cap_alpha_rgba8(
583 self.buffer.as_ref(),
584 self.width,
585 self.stride(),
586 );
587 }
588 has_non_constant_cap_alpha_rgba8(self.buffer.as_ref(), self.width, self.stride())
589 }
590}
591
592impl UnassociateAlpha<u8, 4> for ImageStoreMut<'_, u8, 4> {
593 fn unpremultiply_alpha(&mut self, pool: &Option<ThreadPool>) {
594 let src_stride = self.stride();
595 let dst = self.buffer.borrow_mut();
596 unpremultiply_alpha_rgba(dst, self.width, self.height, src_stride, pool);
597 }
598}
599
600impl AssociateAlpha<u16, 4> for ImageStore<'_, u16, 4> {
601 fn premultiply_alpha(&self, into: &mut ImageStoreMut<'_, u16, 4>, pool: &Option<ThreadPool>) {
602 let dst_stride = into.stride();
603 let dst = into.buffer.borrow_mut();
604 let src = self.buffer.as_ref();
605 premultiply_alpha_rgba_u16(
606 dst,
607 dst_stride,
608 src,
609 self.width,
610 self.height,
611 self.stride(),
612 into.bit_depth,
613 pool,
614 );
615 }
616
617 #[cfg(not(any(
618 any(target_arch = "x86_64", target_arch = "x86"),
619 all(target_arch = "aarch64", target_feature = "neon")
620 )))]
621 fn is_alpha_premultiplication_needed(&self) -> bool {
622 use crate::alpha_check::has_non_constant_cap_alpha_rgba16;
623 has_non_constant_cap_alpha_rgba16(self.buffer.as_ref(), self.width, self.stride())
624 }
625
626 #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
627 fn is_alpha_premultiplication_needed(&self) -> bool {
628 use crate::neon::neon_has_non_constant_cap_alpha_rgba16;
629 neon_has_non_constant_cap_alpha_rgba16(self.buffer.as_ref(), self.width, self.stride())
630 }
631
632 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
633 fn is_alpha_premultiplication_needed(&self) -> bool {
634 use crate::alpha_check::has_non_constant_cap_alpha_rgba16;
635 #[cfg(feature = "sse")]
636 use crate::sse::sse_has_non_constant_cap_alpha_rgba16;
637 #[cfg(all(target_arch = "x86_64", feature = "avx"))]
638 if std::arch::is_x86_feature_detected!("avx2") {
639 use crate::avx2::avx_has_non_constant_cap_alpha_rgba16;
640 return avx_has_non_constant_cap_alpha_rgba16(
641 self.buffer.as_ref(),
642 self.width,
643 self.stride(),
644 );
645 }
646 #[cfg(feature = "sse")]
647 if std::arch::is_x86_feature_detected!("sse4.1") {
648 return sse_has_non_constant_cap_alpha_rgba16(
649 self.buffer.as_ref(),
650 self.width,
651 self.stride(),
652 );
653 }
654 has_non_constant_cap_alpha_rgba16(self.buffer.as_ref(), self.width, self.stride())
655 }
656}
657
658impl AssociateAlpha<f32, 4> for ImageStore<'_, f32, 4> {
659 fn premultiply_alpha(&self, into: &mut ImageStoreMut<'_, f32, 4>, pool: &Option<ThreadPool>) {
660 let src_stride = self.stride();
661 let dst_stride = into.stride();
662 let dst = into.buffer.borrow_mut();
663 let src = self.buffer.as_ref();
664 premultiply_alpha_rgba_f32(
665 dst,
666 dst_stride,
667 src,
668 src_stride,
669 self.width,
670 self.height,
671 pool,
672 );
673 }
674
675 fn is_alpha_premultiplication_needed(&self) -> bool {
676 has_non_constant_cap_alpha_rgba_f32(self.buffer.as_ref(), self.width, self.stride())
677 }
678}
679
680#[cfg(feature = "nightly_f16")]
681impl AssociateAlpha<f16, 4> for ImageStore<'_, f16, 4> {
682 fn premultiply_alpha(&self, into: &mut ImageStoreMut<'_, f16, 4>, pool: &Option<ThreadPool>) {
683 let src_stride = self.stride();
684 let dst_stride = into.stride();
685 let dst = into.buffer.borrow_mut();
686 let src = self.buffer.as_ref();
687 premultiply_alpha_rgba_f16(
688 dst,
689 dst_stride,
690 src,
691 src_stride,
692 self.width,
693 self.height,
694 pool,
695 );
696 }
697
698 fn is_alpha_premultiplication_needed(&self) -> bool {
699 true
700 }
701}
702
703impl UnassociateAlpha<u16, 4> for ImageStoreMut<'_, u16, 4> {
704 fn unpremultiply_alpha(&mut self, pool: &Option<ThreadPool>) {
705 let src_stride = self.stride();
706 let in_place = self.buffer.borrow_mut();
707 unpremultiply_alpha_rgba_u16(
708 in_place,
709 src_stride,
710 self.width,
711 self.height,
712 self.bit_depth,
713 pool,
714 );
715 }
716}
717
718impl UnassociateAlpha<f32, 4> for ImageStoreMut<'_, f32, 4> {
719 fn unpremultiply_alpha(&mut self, pool: &Option<ThreadPool>) {
720 let stride = self.stride();
721 let dst = self.buffer.borrow_mut();
722 unpremultiply_alpha_rgba_f32(dst, stride, self.width, self.height, pool);
723 }
724}
725
726#[cfg(feature = "nightly_f16")]
727impl UnassociateAlpha<f16, 4> for ImageStoreMut<'_, f16, 4> {
728 fn unpremultiply_alpha(&mut self, pool: &Option<ThreadPool>) {
729 let stride = self.stride();
730 let dst = self.buffer.borrow_mut();
731 unpremultiply_alpha_rgba_f16(dst, stride, self.width, self.height, pool);
732 }
733}
734
735pub type Planar8ImageStore<'a> = ImageStore<'a, u8, 1>;
736pub type Planar8ImageStoreMut<'a> = ImageStoreMut<'a, u8, 1>;
737pub type CbCr8ImageStore<'a> = ImageStore<'a, u8, 2>;
738pub type CbCr8ImageStoreMut<'a> = ImageStoreMut<'a, u8, 2>;
739pub type Rgba8ImageStore<'a> = ImageStore<'a, u8, 4>;
740pub type Rgba8ImageStoreMut<'a> = ImageStoreMut<'a, u8, 4>;
741pub type Rgb8ImageStore<'a> = ImageStore<'a, u8, 3>;
742pub type Rgb8ImageStoreMut<'a> = ImageStoreMut<'a, u8, 3>;
743
744pub type Planar16ImageStore<'a> = ImageStore<'a, u16, 1>;
745pub type Planar16ImageStoreMut<'a> = ImageStoreMut<'a, u16, 1>;
746pub type CbCr16ImageStore<'a> = ImageStore<'a, u16, 2>;
747pub type CbCr16ImageStoreMut<'a> = ImageStoreMut<'a, u16, 2>;
748pub type Rgba16ImageStore<'a> = ImageStore<'a, u16, 4>;
749pub type Rgba16ImageStoreMut<'a> = ImageStoreMut<'a, u16, 4>;
750pub type Rgb16ImageStore<'a> = ImageStore<'a, u16, 3>;
751pub type Rgb16ImageStoreMut<'a> = ImageStoreMut<'a, u16, 3>;
752
753#[cfg(feature = "nightly_f16")]
754pub type PlanarF16ImageStore<'a> = ImageStore<'a, f16, 1>;
755#[cfg(feature = "nightly_f16")]
756pub type PlanarF16ImageStoreMut<'a> = ImageStoreMut<'a, f16, 1>;
757#[cfg(feature = "nightly_f16")]
758pub type CbCrF16ImageStore<'a> = ImageStore<'a, f16, 2>;
759#[cfg(feature = "nightly_f16")]
760pub type CbCrF16ImageStoreMut<'a> = ImageStoreMut<'a, f16, 2>;
761#[cfg(feature = "nightly_f16")]
762pub type RgbaF16ImageStore<'a> = ImageStore<'a, f16, 4>;
763#[cfg(feature = "nightly_f16")]
764pub type RgbaF16ImageStoreMut<'a> = ImageStoreMut<'a, f16, 4>;
765#[cfg(feature = "nightly_f16")]
766pub type RgbF16ImageStore<'a> = ImageStore<'a, f16, 3>;
767#[cfg(feature = "nightly_f16")]
768pub type RgbF16ImageStoreMut<'a> = ImageStoreMut<'a, f16, 3>;
769
770pub type PlanarF32ImageStore<'a> = ImageStore<'a, f32, 1>;
771pub type PlanarF32ImageStoreMut<'a> = ImageStoreMut<'a, f32, 1>;
772pub type CbCrF32ImageStore<'a> = ImageStore<'a, f32, 2>;
773pub type CbCrF32ImageStoreMut<'a> = ImageStoreMut<'a, f32, 2>;
774pub type RgbaF32ImageStore<'a> = ImageStore<'a, f32, 4>;
775pub type RgbaF32ImageStoreMut<'a> = ImageStoreMut<'a, f32, 4>;
776pub type RgbF32ImageStore<'a> = ImageStore<'a, f32, 3>;
777pub type RgbF32ImageStoreMut<'a> = ImageStoreMut<'a, f32, 3>;
778
779#[cfg(test)]
780mod tests {
781 use super::*;
782
783 #[test]
784 fn image_store_alpha_test_rgba8() {
785 let image_size = 256usize;
786 let mut image = vec![0u8; image_size * image_size * 4];
787 image[3 + 150 * 4] = 75;
788 let store = ImageStore::<u8, 4>::from_slice(&image, image_size, image_size).unwrap();
789 let has_alpha = store.is_alpha_premultiplication_needed();
790 assert_eq!(true, has_alpha);
791 }
792
793 #[test]
794 fn check_alpha_not_exists_rgba8() {
795 let image_size = 256usize;
796 let image = vec![255u8; image_size * image_size * 4];
797 let store = ImageStore::<u8, 4>::from_slice(&image, image_size, image_size).unwrap();
798 let has_alpha = store.is_alpha_premultiplication_needed();
799 assert_eq!(false, has_alpha);
800 }
801}