mirror of
https://github.com/l1npengtul/nokhwa.git
synced 2026-07-04 02:27:26 +00:00
fix compile errors except for ffmpeg
This commit is contained in:
@@ -8,7 +8,7 @@ use bytemuck::try_cast_slice_mut;
|
|||||||
use crate::pixel_destination::PixelDestination;
|
use crate::pixel_destination::PixelDestination;
|
||||||
|
|
||||||
pub trait Decoder {
|
pub trait Decoder {
|
||||||
type Config: Clone + Debug;
|
type Config: Clone + Debug + ConfigHasResolution;
|
||||||
type OutputMeta: Clone + Debug;
|
type OutputMeta: Clone + Debug;
|
||||||
const SUPPORTED_DESTINATIONS: &'static [PixelDestination];
|
const SUPPORTED_DESTINATIONS: &'static [PixelDestination];
|
||||||
|
|
||||||
@@ -27,10 +27,7 @@ pub trait Decoder {
|
|||||||
where
|
where
|
||||||
<P as Pixel>::Subpixel: NonFloatScalarWidth
|
<P as Pixel>::Subpixel: NonFloatScalarWidth
|
||||||
{
|
{
|
||||||
let destination = match PixelDestination::get_by_pixel::<P>() {
|
let Some(destination) = PixelDestination::get_by_pixel::<P>() else { return Err(NokhwaError::DecoderUnknownDestinationPixelFormat(P::COLOR_MODEL, P::Subpixel::WIDTH_BYTES)) };
|
||||||
Some(dest) => dest,
|
|
||||||
None => return Err(NokhwaError::DecoderUnknownDestinationPixelFormat(P::COLOR_MODEL, P::Subpixel::WIDTH_BYTES))
|
|
||||||
};
|
|
||||||
|
|
||||||
if !Self::supports_destination(destination) {
|
if !Self::supports_destination(destination) {
|
||||||
return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination))
|
return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination))
|
||||||
@@ -43,13 +40,29 @@ pub trait Decoder {
|
|||||||
|
|
||||||
self.decode_to_buffer(to_decode, cast_slice, destination)
|
self.decode_to_buffer(to_decode, cast_slice, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<P: Pixel>(
|
fn decode<P: Pixel>(
|
||||||
&mut self,
|
&mut self,
|
||||||
to_decode: FrameBuffer,
|
to_decode: FrameBuffer<'_>,
|
||||||
) -> Result<DecodedImage<P, Self::OutputMeta>, NokhwaError>
|
) -> Result<DecodedImage<P, Self::OutputMeta>, NokhwaError>
|
||||||
where
|
where
|
||||||
<P as Pixel>::Subpixel: NonFloatScalarWidth;
|
<P as Pixel>::Subpixel: NonFloatScalarWidth,
|
||||||
|
{
|
||||||
|
let resolution = self.config().resolution();
|
||||||
|
let min_size_alloc = self.output_decoder_min_size_pixel::<P>(resolution)?;
|
||||||
|
let mut out_buffer: Vec<P::Subpixel> = vec![P::Subpixel::DEFAULT_MIN_VALUE; min_size_alloc];
|
||||||
|
let meta = self.decode_to_pixel_buffer::<P>(to_decode, &mut out_buffer)?;
|
||||||
|
Ok(DecodedImage::new(
|
||||||
|
ImageBuffer::from_vec(
|
||||||
|
resolution.width(),
|
||||||
|
resolution.height(),
|
||||||
|
out_buffer,
|
||||||
|
)
|
||||||
|
.ok_or(NokhwaError::Decoder(
|
||||||
|
"failed to convert into an image buffer".to_string(),
|
||||||
|
))?,
|
||||||
|
meta,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fn output_decoder_min_size_pixel<P>(&self, resolution: Resolution) -> Result<usize, NokhwaError> where
|
fn output_decoder_min_size_pixel<P>(&self, resolution: Resolution) -> Result<usize, NokhwaError> where
|
||||||
P: Pixel,
|
P: Pixel,
|
||||||
@@ -58,9 +71,29 @@ pub trait Decoder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> Result<usize, NokhwaError>;
|
fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> Result<usize, NokhwaError> {
|
||||||
|
if !Self::supports_destination(destination_format) {
|
||||||
|
return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))
|
||||||
|
}
|
||||||
|
|
||||||
|
let px_size = match destination_format {
|
||||||
|
PixelDestination::Rgb8 | PixelDestination::Bgr8 => 3_u32,
|
||||||
|
PixelDestination::Rgba8 | PixelDestination::Bgra8 | PixelDestination::LumaA16 => 4_u32,
|
||||||
|
PixelDestination::Rgb16 | PixelDestination::Bgr16 => 3_u32 * 2_u32,
|
||||||
|
PixelDestination::Rgba16 | PixelDestination::Bgra16 => 4_u32 * 2_u32,
|
||||||
|
PixelDestination::Luma8 => 1_u32,
|
||||||
|
PixelDestination::LumaA8 | PixelDestination::Luma16 => 2_u32,
|
||||||
|
};
|
||||||
|
let reso = resolution.width() * resolution.height();
|
||||||
|
Ok((reso as usize) * (px_size as usize))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
fn supports_destination(pixel_destination: PixelDestination) -> bool {
|
fn supports_destination(pixel_destination: PixelDestination) -> bool {
|
||||||
Self::SUPPORTED_DESTINATIONS.contains(&pixel_destination)
|
Self::SUPPORTED_DESTINATIONS.contains(&pixel_destination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ConfigHasResolution {
|
||||||
|
fn resolution(&self) -> Resolution;
|
||||||
|
}
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ define_frame_format_with_groups! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FrameFormat {
|
impl FrameFormat {
|
||||||
|
#[must_use]
|
||||||
pub fn is_custom(&self) -> bool {
|
pub fn is_custom(&self) -> bool {
|
||||||
if let FrameFormat::Custom(_) = self {
|
if let FrameFormat::Custom(_) = self {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub enum PixelDestination {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PixelDestination {
|
impl PixelDestination {
|
||||||
|
#[must_use]
|
||||||
pub fn get_by_pixel<P>() -> Option<Self>
|
pub fn get_by_pixel<P>() -> Option<Self>
|
||||||
where
|
where
|
||||||
P: Pixel,
|
P: Pixel,
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ impl<'a> StreamHandle<'a> {
|
|||||||
return Err(NokhwaError::ReadFrameError(why));
|
return Err(NokhwaError::ReadFrameError(why));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Error(e) => return Err(NokhwaError::ReadFrameError(e.to_string())),
|
Event::Error(e) => return Err(NokhwaError::ReadFrameError(e.clone())),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ impl CameraIndex {
|
|||||||
pub fn as_string(&self) -> String {
|
pub fn as_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
CameraIndex::Index(i) => i.to_string(),
|
CameraIndex::Index(i) => i.to_string(),
|
||||||
CameraIndex::String(s) | CameraIndex::Stable(s) => s.to_string(),
|
CameraIndex::String(s) | CameraIndex::Stable(s) => s.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ edition = "2024"
|
|||||||
ffmpeg = ["ffmpeg-the-third"]
|
ffmpeg = ["ffmpeg-the-third"]
|
||||||
yuyv = ["dcv-color-primitives", "yuv"]
|
yuyv = ["dcv-color-primitives", "yuv"]
|
||||||
mjpeg = ["zune-jpeg", "zune-core"]
|
mjpeg = ["zune-jpeg", "zune-core"]
|
||||||
luma = ["itertools", "nokhwa-iter-extensions", "itermore"]
|
luma = ["nokhwa-iter-extensions", "itermore"]
|
||||||
#static = ["ffmpeg-the-third/static"]
|
static = ["ffmpeg-the-third/static"]
|
||||||
#async = []
|
#async = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -19,7 +19,7 @@ version = "0.2"
|
|||||||
path = "../nokhwa-core"
|
path = "../nokhwa-core"
|
||||||
|
|
||||||
[dependencies.ffmpeg-the-third]
|
[dependencies.ffmpeg-the-third]
|
||||||
version = "4.0.0+ffmpeg-8.0"
|
version = "4.0.0"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.yuv]
|
[dependencies.yuv]
|
||||||
@@ -38,10 +38,6 @@ optional = true
|
|||||||
version = "0.5.0-rc2"
|
version = "0.5.0-rc2"
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.itertools]
|
|
||||||
version = "0.14"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.itermore]
|
[dependencies.itermore]
|
||||||
version = "0.8"
|
version = "0.8"
|
||||||
features = ["array_chunks"]
|
features = ["array_chunks"]
|
||||||
|
|||||||
@@ -12,11 +12,12 @@ use ffmpeg_the_third::ffi::{
|
|||||||
use ffmpeg_the_third::packet::{Borrow, Ref};
|
use ffmpeg_the_third::packet::{Borrow, Ref};
|
||||||
use ffmpeg_the_third::{Frame, decoder, packet::Packet};
|
use ffmpeg_the_third::{Frame, decoder, packet::Packet};
|
||||||
use nokhwa_core::codec::Codec;
|
use nokhwa_core::codec::Codec;
|
||||||
use nokhwa_core::decoder::{Decoder, ImageBuffer, Pixel, Primitive};
|
use nokhwa_core::decoder::{ConfigHasResolution, Decoder, Pixel};
|
||||||
use nokhwa_core::error::NokhwaError;
|
use nokhwa_core::error::NokhwaError;
|
||||||
use nokhwa_core::frame_buffer::FrameBuffer;
|
use nokhwa_core::frame_buffer::FrameBuffer;
|
||||||
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
|
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
|
||||||
use nokhwa_core::image::{DecodedImage, NonFloatScalarWidth};
|
use nokhwa_core::image::{NonFloatScalarWidth};
|
||||||
|
use nokhwa_core::pixel_destination::PixelDestination;
|
||||||
use nokhwa_core::types::{CameraFormat, FrameRate, Resolution};
|
use nokhwa_core::types::{CameraFormat, FrameRate, Resolution};
|
||||||
|
|
||||||
pub struct FfmpegDecoder {
|
pub struct FfmpegDecoder {
|
||||||
@@ -56,7 +57,8 @@ impl FfmpegDecoder {
|
|||||||
impl Decoder for FfmpegDecoder {
|
impl Decoder for FfmpegDecoder {
|
||||||
type Config = <FfmpegCodec as Codec>::Config;
|
type Config = <FfmpegCodec as Codec>::Config;
|
||||||
type OutputMeta = <FfmpegCodec as Codec>::WrittenMeta;
|
type OutputMeta = <FfmpegCodec as Codec>::WrittenMeta;
|
||||||
type DestinationFormatHint = AVPixelFormat;
|
const SUPPORTED_DESTINATIONS: &'static [PixelDestination] = &[];
|
||||||
|
|
||||||
|
|
||||||
fn config(&self) -> &Self::Config {
|
fn config(&self) -> &Self::Config {
|
||||||
self.codec.config()
|
self.codec.config()
|
||||||
@@ -71,7 +73,7 @@ impl Decoder for FfmpegDecoder {
|
|||||||
&mut self,
|
&mut self,
|
||||||
to_decode: FrameBuffer,
|
to_decode: FrameBuffer,
|
||||||
mut buffer: impl AsMut<[u8]>,
|
mut buffer: impl AsMut<[u8]>,
|
||||||
_destination_format: Option<Self::DestinationFormatHint>,
|
_destination_format: PixelDestination,
|
||||||
) -> Result<Self::OutputMeta, NokhwaError> {
|
) -> Result<Self::OutputMeta, NokhwaError> {
|
||||||
// TODO: add an extra zippy happy path for rgb/bgr/luma
|
// TODO: add an extra zippy happy path for rgb/bgr/luma
|
||||||
let (frame, metadata) = self.receive_decoded_frame(to_decode)?;
|
let (frame, metadata) = self.receive_decoded_frame(to_decode)?;
|
||||||
@@ -188,54 +190,6 @@ impl Decoder for FfmpegDecoder {
|
|||||||
Ok(decoded_meta)
|
Ok(decoded_meta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<P: Pixel>(
|
|
||||||
&mut self,
|
|
||||||
to_decode: FrameBuffer,
|
|
||||||
) -> Result<DecodedImage<P, Self::OutputMeta>, NokhwaError>
|
|
||||||
where
|
|
||||||
<P as Pixel>::Subpixel: NonFloatScalarWidth,
|
|
||||||
{
|
|
||||||
let min_size = self.output_decoder_min_size_pixel::<P>(self.config().resolution);
|
|
||||||
let mut buffer: Vec<P::Subpixel> = vec![<P::Subpixel>::DEFAULT_MIN_VALUE; min_size];
|
|
||||||
let meta = self.decode_to_buffer(
|
|
||||||
to_decode,
|
|
||||||
try_cast_slice_mut(&mut buffer)
|
|
||||||
.map_err(|why| NokhwaError::DecoderInvalidBuffer(why.to_string()))?,
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
Ok(DecodedImage::new(
|
|
||||||
ImageBuffer::from_vec(
|
|
||||||
self.codec.config.resolution.width(),
|
|
||||||
self.codec.config.resolution.height(),
|
|
||||||
buffer,
|
|
||||||
)
|
|
||||||
.ok_or(NokhwaError::Decoder(
|
|
||||||
"Failed to create Image Buffer".to_string(),
|
|
||||||
))?,
|
|
||||||
meta,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_decoder_min_size(
|
|
||||||
&self,
|
|
||||||
resolution: Resolution,
|
|
||||||
destination_format: Self::DestinationFormatHint,
|
|
||||||
) -> usize {
|
|
||||||
let size = unsafe {
|
|
||||||
av_image_get_buffer_size(
|
|
||||||
destination_format,
|
|
||||||
resolution.width() as i32,
|
|
||||||
resolution.height() as i32,
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
size as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buffer_takes_destination_hint(&self) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_sws_context(
|
fn create_sws_context(
|
||||||
@@ -261,53 +215,6 @@ fn create_sws_context(
|
|||||||
Ok(new_sws)
|
Ok(new_sws)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pixel_to_destination_px_fmt<P: Pixel>() -> Option<AVPixelFormat>
|
|
||||||
where
|
|
||||||
<P as Pixel>::Subpixel: NonFloatScalarWidth,
|
|
||||||
{
|
|
||||||
match P::COLOR_MODEL {
|
|
||||||
"RGB" => match <<P as Pixel>::Subpixel>::WIDTH_BYTES {
|
|
||||||
1 => Some(AVPixelFormat::AV_PIX_FMT_RGB24),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
|
|
||||||
"RGBA" => match <<P as Pixel>::Subpixel>::WIDTH_BYTES {
|
|
||||||
1 => Some(AVPixelFormat::AV_PIX_FMT_RGBA),
|
|
||||||
2 => Some(switch_endian(
|
|
||||||
AVPixelFormat::AV_PIX_FMT_RGBA64LE,
|
|
||||||
AVPixelFormat::AV_PIX_FMT_RGBA64BE,
|
|
||||||
)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
"BGR" => match <<P as Pixel>::Subpixel>::WIDTH_BYTES {
|
|
||||||
1 => Some(AVPixelFormat::AV_PIX_FMT_BGR24),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
|
|
||||||
"BGRA" => match <<P as Pixel>::Subpixel>::WIDTH_BYTES {
|
|
||||||
1 => Some(AVPixelFormat::AV_PIX_FMT_BGRA),
|
|
||||||
2 => Some(switch_endian(
|
|
||||||
AVPixelFormat::AV_PIX_FMT_BGRA64LE,
|
|
||||||
AVPixelFormat::AV_PIX_FMT_BGRA64BE,
|
|
||||||
)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
"Y" => match <<P as Pixel>::Subpixel>::WIDTH_BYTES {
|
|
||||||
1 => Some(AVPixelFormat::AV_PIX_FMT_GRAY8),
|
|
||||||
2 => Some(switch_endian(
|
|
||||||
AVPixelFormat::AV_PIX_FMT_GRAY16LE,
|
|
||||||
AVPixelFormat::AV_PIX_FMT_GRAY16BE,
|
|
||||||
)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
"YA" => match <<P as Pixel>::Subpixel>::WIDTH_BYTES {
|
|
||||||
1 => Some(AVPixelFormat::AV_PIX_FMT_GRAY8A),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Sws {
|
pub struct Sws {
|
||||||
pub sws: *mut SwsContext,
|
pub sws: *mut SwsContext,
|
||||||
pub source_pixel_format: AVPixelFormat,
|
pub source_pixel_format: AVPixelFormat,
|
||||||
@@ -686,6 +593,12 @@ pub struct FfmpegDecoderConfig {
|
|||||||
pub video_delay: i32,
|
pub video_delay: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConfigHasResolution for FfmpegDecoderConfig {
|
||||||
|
fn resolution(&self) -> Resolution {
|
||||||
|
self.resolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FfmpegDecoderConfig {
|
impl FfmpegDecoderConfig {
|
||||||
pub fn with_camera_format(camera_format: &CameraFormat) -> Self {
|
pub fn with_camera_format(camera_format: &CameraFormat) -> Self {
|
||||||
FfmpegDecoderConfig::from(*camera_format)
|
FfmpegDecoderConfig::from(*camera_format)
|
||||||
|
|||||||
+117
-133
@@ -1,20 +1,16 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::mem::swap;
|
use bytemuck::{cast_slice, cast_slice_mut};
|
||||||
use bytemuck::{cast_mut, cast_slice, cast_slice_mut, try_cast_slice_mut};
|
use nokhwa_core::decoder::{ConfigHasResolution, Decoder};
|
||||||
use image::Pixel;
|
|
||||||
use itertools::Itertools;
|
|
||||||
use nokhwa_core::decoder::Decoder;
|
|
||||||
use nokhwa_core::error::NokhwaError;
|
use nokhwa_core::error::NokhwaError;
|
||||||
use nokhwa_core::frame_buffer::FrameBuffer;
|
use nokhwa_core::frame_buffer::FrameBuffer;
|
||||||
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
|
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
|
||||||
use nokhwa_core::image::{DecodedImage, NonFloatScalarWidth};
|
|
||||||
use nokhwa_core::types::{CameraFormat, Resolution};
|
|
||||||
use nokhwa_iter_extensions::duplicate::IterDuplicateConst;
|
use nokhwa_iter_extensions::duplicate::IterDuplicateConst;
|
||||||
use nokhwa_iter_extensions::interweave::IterInterweave;
|
use nokhwa_iter_extensions::interweave::IterInterweave;
|
||||||
use itermore::{IterArrayChunks};
|
use itermore::{IterArrayChunks};
|
||||||
use nokhwa_core::pixel_destination::PixelDestination;
|
use nokhwa_core::pixel_destination::PixelDestination;
|
||||||
|
use nokhwa_core::types::{CameraFormat, Resolution};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct LumaDecoder {
|
pub struct LumaDecoder {
|
||||||
@@ -44,29 +40,15 @@ impl Decoder for LumaDecoder {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_to_buffer(&mut self, mut to_decode: FrameBuffer, mut buffer: impl AsMut<[u8]>, destination_format: PixelDestination) -> Result<Self::OutputMeta, NokhwaError> {
|
fn decode_to_buffer(&mut self, to_decode: FrameBuffer, mut buffer: impl AsMut<[u8]>, destination_format: PixelDestination) -> Result<Self::OutputMeta, NokhwaError> {
|
||||||
let destination_hint = match destination_format {
|
let format = self.config().custom_frame_format_map.as_ref().and_then(|m| {
|
||||||
Some(h) => h,
|
|
||||||
None => return Err(NokhwaError::DecoderDestinationHintRequired)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (width, max_value) = match self.config().format {
|
|
||||||
FrameFormat::Luma_8 => (1, u8::MAX as u32),
|
|
||||||
FrameFormat::Luma_10 => (2, 2_u32.pow(10)),
|
|
||||||
FrameFormat::Luma_12 => (2, 2_u32.pow(12)),
|
|
||||||
FrameFormat::Luma_14 => (2, 2_u32.pow(14)),
|
|
||||||
FrameFormat::Luma_16 | FrameFormat::Depth_16 => (2, u16::MAX as u32),
|
|
||||||
fmt => return Err(NokhwaError::DecoderUnsupportedFrameFormat(fmt))
|
|
||||||
};
|
|
||||||
|
|
||||||
let format = self.config().custom_frame_format_map.as_ref().map(|m| {
|
|
||||||
match self.config().format {
|
match self.config().format {
|
||||||
FrameFormat::Custom(cfmt) => {
|
FrameFormat::Custom(cfmt) => {
|
||||||
m.get(&cfmt).copied()
|
m.get(&cfmt).copied()
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}).flatten().unwrap_or(self.config().format);
|
}).unwrap_or(self.config().format);
|
||||||
|
|
||||||
let r = filter_to_u8(self.config().channel_filters.red);
|
let r = filter_to_u8(self.config().channel_filters.red);
|
||||||
let g = filter_to_u8(self.config().channel_filters.green);
|
let g = filter_to_u8(self.config().channel_filters.green);
|
||||||
@@ -82,18 +64,20 @@ impl Decoder for LumaDecoder {
|
|||||||
|
|
||||||
match format {
|
match format {
|
||||||
FrameFormat::Luma_8 => {
|
FrameFormat::Luma_8 => {
|
||||||
match destination_hint {
|
match destination_format {
|
||||||
PixelDestination::Luma8 => {
|
PixelDestination::Luma8 => {
|
||||||
if to_decode.len() != buffer.len() {
|
if to_decode.len() != buffer.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
match to_decode.consume().0 {
|
match to_decode.consume().0 {
|
||||||
Cow::Borrowed(data) => {
|
Cow::Borrowed(data) => {
|
||||||
buffer.copy_from_slice(data)
|
buffer.copy_from_slice(data);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Cow::Owned(mut owned) => {
|
Cow::Owned(mut owned) => {
|
||||||
buffer.swap_with_slice(owned.as_mut_slice())
|
buffer.swap_with_slice(owned.as_mut_slice());
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,52 +85,56 @@ impl Decoder for LumaDecoder {
|
|||||||
let default_alpha = u8::MAX * a;
|
let default_alpha = u8::MAX * a;
|
||||||
|
|
||||||
if (to_decode.len() * 2) != buffer.len() {
|
if (to_decode.len() * 2) != buffer.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
to_decode.buffer().into_iter().interweave(&default_alpha, false).enumerate()
|
to_decode.buffer().iter().interweave::<0>(&default_alpha, false).enumerate()
|
||||||
.for_each(|(len, data)| {
|
.for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*buffer.get_unchecked_mut(len) = *data;
|
*buffer.get_unchecked_mut(len) = *data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
PixelDestination::Rgb8 => {
|
PixelDestination::Rgb8 => {
|
||||||
if (to_decode.len() * 3) != buffer.len() {
|
if (to_decode.len() * 3) != buffer.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
|
to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
|
||||||
let px_r = &pixel[0_usize] * r;
|
let px_r = *pixel[0_usize] * r;
|
||||||
let px_g = &pixel[1_usize] * g;
|
let px_g = *pixel[1_usize] * g;
|
||||||
let px_b = &pixel[2_usize] * b;
|
let px_b = *pixel[2_usize] * b;
|
||||||
[px_r, px_g, px_b]
|
[px_r, px_g, px_b]
|
||||||
}).flatten().enumerate().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*buffer.get_unchecked_mut(len) = *data;
|
*buffer.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
PixelDestination::Rgba8 => {
|
PixelDestination::Rgba8 => {
|
||||||
if (to_decode.len() * 4) != buffer.len() {
|
if (to_decode.len() * 4) != buffer.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
|
to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
|
||||||
let px_r = &pixel[0_usize] * r;
|
let px_r = *pixel[0_usize] * r;
|
||||||
let px_g = &pixel[1_usize] * g;
|
let px_g = *pixel[1_usize] * g;
|
||||||
let px_b = &pixel[2_usize] * b;
|
let px_b = *pixel[2_usize] * b;
|
||||||
let px_a = 255 * b;
|
let px_a = 255 * b;
|
||||||
[px_r, px_g, px_b, px_a]
|
[px_r, px_g, px_b, px_a]
|
||||||
}).flatten().enumerate().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*buffer.get_unchecked_mut(len) = *data;
|
*buffer.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
PixelDestination::Rgb16 => {
|
PixelDestination::Rgb16 => {
|
||||||
if (to_decode.len() * 6) != buffer.len() {
|
if (to_decode.len() * 6) != buffer.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let temp_buffer = cast_slice_mut::<u8, u16>(buffer);
|
let temp_buffer = cast_slice_mut::<u8, u16>(buffer);
|
||||||
@@ -159,20 +147,21 @@ impl Decoder for LumaDecoder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
|
to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
|
||||||
let px_r = (&pixel[0_usize] as u16) * r_u16 * factor;
|
let px_r = (*pixel[0_usize] as u16) * r_u16 * factor;
|
||||||
let px_g = (&pixel[1_usize] as u16) * g_u16 * factor;
|
let px_g = (*pixel[1_usize] as u16) * g_u16 * factor;
|
||||||
let px_b = (&pixel[2_usize] as u16) * b_u16 * factor;
|
let px_b = (*pixel[2_usize] as u16) * b_u16 * factor;
|
||||||
[px_r, px_g, px_b]
|
[px_r, px_g, px_b]
|
||||||
}).flatten().enumerate().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*temp_buffer.get_unchecked_mut(len) = *data;
|
*temp_buffer.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
}); Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
PixelDestination::Rgba16 => {
|
PixelDestination::Rgba16 => {
|
||||||
if (to_decode.len() * 8) != buffer.len() {
|
if (to_decode.len() * 8) != buffer.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let temp_buffer = cast_slice_mut::<u8, u16>(buffer);
|
let temp_buffer = cast_slice_mut::<u8, u16>(buffer);
|
||||||
@@ -185,23 +174,24 @@ impl Decoder for LumaDecoder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode.buffer().into_iter().duplicate_const::<3>().arrays::<3>().map(|pixel| {
|
to_decode.buffer().iter().duplicate_const::<3>().arrays::<3>().flat_map(|pixel| {
|
||||||
let px_r = (&pixel[0_usize] as u16) * r_u16 * factor;
|
let px_r = (*pixel[0_usize] as u16) * r_u16 * factor;
|
||||||
let px_g = (&pixel[1_usize] as u16) * g_u16 * factor;
|
let px_g = (*pixel[1_usize] as u16) * g_u16 * factor;
|
||||||
let px_b = (&pixel[2_usize] as u16) * b_u16 * factor;
|
let px_b = (*pixel[2_usize] as u16) * b_u16 * factor;
|
||||||
let px_a = u16::MAX * a_u16;
|
let px_a = u16::MAX * a_u16;
|
||||||
[px_r, px_g, px_b, px_a]
|
[px_r, px_g, px_b, px_a]
|
||||||
}).flatten().enumerate().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*temp_buffer.get_unchecked_mut(len) = *data;
|
*temp_buffer.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
}); Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
PixelDestination::Luma16 => {
|
PixelDestination::Luma16 => {
|
||||||
let buffer_u16 = cast_slice_mut::<u8, u16>(buffer);
|
let buffer_u16 = cast_slice_mut::<u8, u16>(buffer);
|
||||||
|
|
||||||
if to_decode.len() != buffer_u16.len() {
|
if to_decode.len() != buffer_u16.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let factor = match self.config().mode {
|
let factor = match self.config().mode {
|
||||||
@@ -209,21 +199,22 @@ impl Decoder for LumaDecoder {
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode.buffer().into_iter().map(|px| {
|
to_decode.buffer().iter().map(|px| {
|
||||||
(*px as u16) << factor
|
(*px as u16) << factor
|
||||||
}).enumerate()
|
}).enumerate()
|
||||||
.for_each(|(len, data)| {
|
.for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*buffer_u16.get_unchecked_mut(len) = *data;
|
*buffer_u16.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
}); Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
PixelDestination::LumaA16 => {
|
PixelDestination::LumaA16 => {
|
||||||
let default_alpha = u16::MAX * a_u16;
|
let default_alpha = u16::MAX * a_u16;
|
||||||
let buffer_u16 = cast_slice_mut::<u8, u16>(buffer);
|
let buffer_u16 = cast_slice_mut::<u8, u16>(buffer);
|
||||||
|
|
||||||
if (to_decode.len() * 2) != buffer_u16.len() {
|
if (to_decode.len() * 2) != buffer_u16.len() {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!"))
|
return Err(NokhwaError::DecoderInvalidBuffer("Lengths differ!".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let factor = match self.config().mode {
|
let factor = match self.config().mode {
|
||||||
@@ -231,38 +222,28 @@ impl Decoder for LumaDecoder {
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode.buffer().into_iter().map(|px| {
|
to_decode.buffer().iter().map(|px| {
|
||||||
(*px as u16) << factor
|
(*px as u16) << factor
|
||||||
}).interweave(&default_alpha, false).enumerate()
|
}).interweave::<0>(default_alpha, false).enumerate()
|
||||||
.for_each(|(len, data)| {
|
.for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*buffer_u16.get_unchecked_mut(len) = *data;
|
*buffer_u16.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
}); Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
fmt => Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(fmt))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::Luma_10 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 10),
|
FrameFormat::Luma_10 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 10),
|
||||||
FrameFormat::Luma_12 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 12),
|
FrameFormat::Luma_12 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 12),
|
||||||
FrameFormat::Luma_14 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 14),
|
FrameFormat::Luma_14 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 14),
|
||||||
FrameFormat::Luma_16 | FrameFormat::Depth_16 => convert_u16_type_buffers(to_decode, buffer, destination_hint, self.config().mode, self.config().channel_filters, 16),
|
FrameFormat::Luma_16 | FrameFormat::Depth_16 => convert_u16_type_buffers(to_decode, buffer, destination_format, self.config().mode, self.config().channel_filters, 16),
|
||||||
fmt => {
|
fmt => {
|
||||||
return Err(NokhwaError::DecoderUnsupportedFrameFormat(fmt))
|
Err(NokhwaError::DecoderUnsupportedFrameFormat(fmt))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<P: Pixel>(&mut self, to_decode: FrameBuffer) -> Result<DecodedImage<P, Self::OutputMeta>, NokhwaError>
|
|
||||||
where
|
|
||||||
<P as Pixel>::Subpixel: NonFloatScalarWidth
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_decoder_min_size(&self, resolution: Resolution, destination_format: PixelDestination) -> usize {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_to_u8(filter: bool) -> u8 {
|
fn filter_to_u8(filter: bool) -> u8 {
|
||||||
@@ -288,9 +269,9 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
let b_u16 = filter_to_u16(channel_filters.blue);
|
let b_u16 = filter_to_u16(channel_filters.blue);
|
||||||
let a_u16 = filter_to_u16(channel_filters.alpha);
|
let a_u16 = filter_to_u16(channel_filters.alpha);
|
||||||
|
|
||||||
let r = filter_to_u8(channel_filters.red);
|
// let r = filter_to_u8(channel_filters.red);
|
||||||
let g = filter_to_u8(channel_filters.green);
|
// let g = filter_to_u8(channel_filters.green);
|
||||||
let b = filter_to_u8(channel_filters.blue);
|
// let b = filter_to_u8(channel_filters.blue);
|
||||||
let a = filter_to_u8(channel_filters.alpha);
|
let a = filter_to_u8(channel_filters.alpha);
|
||||||
|
|
||||||
match hint {
|
match hint {
|
||||||
@@ -308,12 +289,12 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode_u16.into_iter().map(|px| {
|
to_decode_u16.iter().map(|px| {
|
||||||
(*px >> factor) as u8
|
(*px >> factor) as u8
|
||||||
}).enumerate()
|
}).enumerate()
|
||||||
.for_each(|(len, data)| {
|
.for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination.get_unchecked_mut(len) = *data;
|
*destination.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -332,12 +313,12 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode_u16.into_iter().map(|px| {
|
to_decode_u16.iter().map(|px| {
|
||||||
(*px >> factor) as u8
|
(*px >> factor) as u8
|
||||||
}).interweave(255 * a, false).enumerate()
|
}).interweave::<0>(255 * a, false).enumerate()
|
||||||
.for_each(|(len, data)| {
|
.for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination.get_unchecked_mut(len) = *data;
|
*destination.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -356,14 +337,14 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
|
to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
|
||||||
let px_r = (&px[0_usize] >> factor) * r;
|
let px_r = (*px[0_usize] >> factor) * r_u16;
|
||||||
let px_g = (&px[1_usize] >> factor) * g;
|
let px_g = (*px[1_usize] >> factor) * g_u16;
|
||||||
let px_b = (&px[2_usize] >> factor)* b;
|
let px_b = (*px[2_usize] >> factor)* b_u16;
|
||||||
[px_r as u8, px_g as u8, px_b as u8]
|
[px_r as u8, px_g as u8, px_b as u8]
|
||||||
}).flatten().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination.get_unchecked_mut(len) = *data;
|
*destination.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -382,15 +363,15 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
|
to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
|
||||||
let px_r = (&px[0_usize] >> factor) * r_u16 ;
|
let px_r = (*px[0_usize] >> factor) * r_u16 ;
|
||||||
let px_g = (&px[1_usize] >> factor) * g_u16 ;
|
let px_g = (*px[1_usize] >> factor) * g_u16 ;
|
||||||
let px_b = (&px[2_usize] >> factor) * b_u16 ;
|
let px_b = (*px[2_usize] >> factor) * b_u16 ;
|
||||||
let px_a = u8::MAX * a;
|
let px_a = u8::MAX * a;
|
||||||
[px_r as u8, px_g as u8, px_b as u8, px_a]
|
[px_r as u8, px_g as u8, px_b as u8, px_a]
|
||||||
}).flatten().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination.get_unchecked_mut(len) = *data;
|
*destination.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -410,14 +391,14 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
|
to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
|
||||||
let px_r = (&px[0_usize] >> factor) * r_u16;
|
let px_r = (*px[0_usize] >> factor) * r_u16;
|
||||||
let px_g = (&px[1_usize] >> factor) * g_u16;
|
let px_g = (*px[1_usize] >> factor) * g_u16;
|
||||||
let px_b = (&px[2_usize] >> factor) * b_u16;
|
let px_b = (*px[2_usize] >> factor) * b_u16;
|
||||||
[px_r, px_g, px_b]
|
[px_r, px_g, px_b]
|
||||||
}).flatten().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination_buffer_u16.get_unchecked_mut(len) = *data;
|
*destination_buffer_u16.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -437,15 +418,15 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
ConvertMode::Clipped => 0,
|
ConvertMode::Clipped => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
to_decode_u16.into_iter().duplicate_const::<3>().array_chunks::<3>().map(|px| {
|
to_decode_u16.iter().duplicate_const::<3>().arrays::<3>().flat_map(|px| {
|
||||||
let px_r = (&px[0_usize] >> factor) * r_u16;
|
let px_r = (*px[0_usize] >> factor) * r_u16;
|
||||||
let px_g = (&px[1_usize] >> factor) * g_u16;
|
let px_g = (*px[1_usize] >> factor) * g_u16;
|
||||||
let px_b = (&px[2_usize] >> factor) * b_u16;
|
let px_b = (*px[2_usize] >> factor) * b_u16;
|
||||||
let px_a = u16::MAX * a_u16;
|
let px_a = u16::MAX * a_u16;
|
||||||
[px_r, px_g, px_b, px_a]
|
[px_r, px_g, px_b, px_a]
|
||||||
}).flatten().for_each(|(len, data)| {
|
}).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination_buffer_u16.get_unchecked_mut(len) = *data;
|
*destination_buffer_u16.get_unchecked_mut(len) = data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -473,9 +454,9 @@ fn convert_u16_type_buffers(to_decode: FrameBuffer, destination: &mut [u8], hint
|
|||||||
let to_decode_u16 = cast_slice::<u8, u16>(to_decode.buffer());
|
let to_decode_u16 = cast_slice::<u8, u16>(to_decode.buffer());
|
||||||
let destination_buffer_u16 = cast_slice_mut::<u8, u16>(destination);
|
let destination_buffer_u16 = cast_slice_mut::<u8, u16>(destination);
|
||||||
|
|
||||||
to_decode_u16.into_iter().interweave(&(u16::MAX * a_u16), false).enumerate().for_each(|(len, data)| {
|
to_decode_u16.iter().interweave::<0>(&(u16::MAX * a_u16), false).enumerate().for_each(|(len, data)| {
|
||||||
unsafe {
|
unsafe {
|
||||||
*destination.get_unchecked_mut(len) = *data;
|
*destination_buffer_u16.get_unchecked_mut(len) = *data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -491,38 +472,41 @@ pub struct LumaConfig {
|
|||||||
pub mode: ConvertMode,
|
pub mode: ConvertMode,
|
||||||
pub channel_filters: ChannelFilters,
|
pub channel_filters: ChannelFilters,
|
||||||
pub format: FrameFormat,
|
pub format: FrameFormat,
|
||||||
pub custom_frame_format_map: Option<HashMap<CustomFrameFormat, FrameFormat>>
|
pub custom_frame_format_map: Option<HashMap<CustomFrameFormat, FrameFormat>>,
|
||||||
|
pub resolution: Resolution,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<FrameFormat> for LumaConfig {
|
impl ConfigHasResolution for LumaConfig {
|
||||||
|
fn resolution(&self) -> Resolution {
|
||||||
|
self.resolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<CameraFormat> for LumaConfig {
|
||||||
type Error = NokhwaError;
|
type Error = NokhwaError;
|
||||||
|
|
||||||
fn try_from(value: FrameFormat) -> Result<Self, Self::Error> {
|
fn try_from(value: CameraFormat) -> Result<Self, Self::Error> {
|
||||||
if !FrameFormat::BRIGHTNESS_LUMA.contains(&value) {
|
if !FrameFormat::BRIGHTNESS_LUMA.contains(&value.format()) {
|
||||||
return Err(NokhwaError::DecoderUnsupportedFrameFormat(value))
|
return Err(NokhwaError::DecoderUnsupportedFrameFormat(value.format()))
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(LumaConfig {
|
Ok(LumaConfig {
|
||||||
mode: ConvertMode::default(),
|
mode: ConvertMode::default(),
|
||||||
channel_filters: ChannelFilters::default(),
|
channel_filters: ChannelFilters::default(),
|
||||||
format: value,
|
format: value.format(),
|
||||||
custom_frame_format_map: None,
|
custom_frame_format_map: None,
|
||||||
|
resolution: value.resolution(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Default, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub enum ConvertMode {
|
pub enum ConvertMode {
|
||||||
|
#[default]
|
||||||
Scaled,
|
Scaled,
|
||||||
Clipped
|
Clipped
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ConvertMode {
|
|
||||||
fn default() -> Self {
|
|
||||||
ConvertMode::Scaled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct ChannelFilters {
|
pub struct ChannelFilters {
|
||||||
pub red: bool,
|
pub red: bool,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use nokhwa_core::decoder::{Decoder, ImageBuffer, Pixel};
|
use nokhwa_core::decoder::{ConfigHasResolution, Decoder, ImageBuffer, Pixel};
|
||||||
use nokhwa_core::error::NokhwaError;
|
use nokhwa_core::error::NokhwaError;
|
||||||
use nokhwa_core::frame_buffer::FrameBuffer;
|
use nokhwa_core::frame_buffer::FrameBuffer;
|
||||||
use nokhwa_core::image::Primitive;
|
use nokhwa_core::image::Primitive;
|
||||||
@@ -51,7 +51,7 @@ impl Decoder for MJpegDecoder {
|
|||||||
|
|
||||||
let colorspace = convert_destination_to_colorspace(destination_format).ok_or(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))?;
|
let colorspace = convert_destination_to_colorspace(destination_format).ok_or(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))?;
|
||||||
|
|
||||||
let mut config = self.config.decoder_options.jpeg_set_out_colorspace(colorspace);
|
let config = self.config.decoder_options.jpeg_set_out_colorspace(colorspace);
|
||||||
|
|
||||||
decoder.set_options(config);
|
decoder.set_options(config);
|
||||||
decoder.decode_into(buffer).map_err(err_to_err)?;
|
decoder.decode_into(buffer).map_err(err_to_err)?;
|
||||||
@@ -89,23 +89,6 @@ impl Decoder for MJpegDecoder {
|
|||||||
))?;
|
))?;
|
||||||
Ok(DecodedImage::new(image_buffer, output_metadata))
|
Ok(DecodedImage::new(image_buffer, output_metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_decoder_min_size(
|
|
||||||
&self,
|
|
||||||
resolution: Resolution,
|
|
||||||
destination_format: PixelDestination,
|
|
||||||
) -> Result<usize, NokhwaError> {
|
|
||||||
let stride = match destination_format {
|
|
||||||
PixelDestination::Rgb8 => 3,
|
|
||||||
PixelDestination::Rgba8 => 4,
|
|
||||||
PixelDestination::Bgr8 => 3,
|
|
||||||
PixelDestination::Bgra8 => 4,
|
|
||||||
PixelDestination::Luma8 => 1,
|
|
||||||
PixelDestination::LumaA8 => 2,
|
|
||||||
fmt => return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(fmt))
|
|
||||||
};
|
|
||||||
Ok((resolution.width() * resolution.height() * stride) as usize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@@ -137,6 +120,12 @@ pub struct MJpegOptions {
|
|||||||
pub decoder_options: DecoderOptions,
|
pub decoder_options: DecoderOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConfigHasResolution for MJpegOptions {
|
||||||
|
fn resolution(&self) -> Resolution {
|
||||||
|
self.resolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn err_to_err(decode_errors: DecodeErrors) -> NokhwaError {
|
fn err_to_err(decode_errors: DecodeErrors) -> NokhwaError {
|
||||||
match decode_errors {
|
match decode_errors {
|
||||||
DecodeErrors::Format(fmt) => NokhwaError::Decoder(fmt),
|
DecodeErrors::Format(fmt) => NokhwaError::Decoder(fmt),
|
||||||
|
|||||||
+56
-95
@@ -1,11 +1,10 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use bytemuck::{cast_slice, cast_slice_mut, try_cast_slice_mut};
|
use bytemuck::{cast_slice, cast_slice_mut};
|
||||||
|
|
||||||
use nokhwa_core::decoder::{Decoder, ImageBuffer, Pixel, Primitive};
|
use nokhwa_core::decoder::{ConfigHasResolution, Decoder};
|
||||||
use nokhwa_core::error::NokhwaError;
|
use nokhwa_core::error::NokhwaError;
|
||||||
use nokhwa_core::frame_buffer::FrameBuffer;
|
use nokhwa_core::frame_buffer::FrameBuffer;
|
||||||
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
|
use nokhwa_core::frame_format::{CustomFrameFormat, FrameFormat};
|
||||||
use nokhwa_core::image::{DecodedImage, NonFloatScalarWidth};
|
|
||||||
use nokhwa_core::types::{CameraFormat, Resolution};
|
use nokhwa_core::types::{CameraFormat, Resolution};
|
||||||
use yuv::{
|
use yuv::{
|
||||||
YuvBiPlanarImage, YuvConversionMode, YuvPackedImage, YuvPlanarImage, YuvRange,
|
YuvBiPlanarImage, YuvConversionMode, YuvPackedImage, YuvPlanarImage, YuvRange,
|
||||||
@@ -53,13 +52,12 @@ impl Decoder for YUVDecoder {
|
|||||||
return Err(NokhwaError::DecoderUnsupportedFrameFormat(config.yuv_type));
|
return Err(NokhwaError::DecoderUnsupportedFrameFormat(config.yuv_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(custom_map) = &config.custom_frame_format_map {
|
if let Some(custom_map) = &config.custom_frame_format_map
|
||||||
if let Some((src, dest)) = custom_map.iter().find(|(_, value)| {
|
&& let Some((src, dest)) = custom_map.iter().find(|(_, value)| {
|
||||||
FrameFormat::YCBCR.contains(value)
|
FrameFormat::YCBCR.contains(value)
|
||||||
}) {
|
}) {
|
||||||
return Err(NokhwaError::DecoderUnsupportedCustomFrameFormatDestination(*src, *dest))
|
return Err(NokhwaError::DecoderUnsupportedCustomFrameFormatDestination(*src, *dest))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.config = config;
|
self.config = config;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -71,29 +69,23 @@ impl Decoder for YUVDecoder {
|
|||||||
mut buffer: impl AsMut<[u8]>,
|
mut buffer: impl AsMut<[u8]>,
|
||||||
destination_format: PixelDestination,
|
destination_format: PixelDestination,
|
||||||
) -> Result<Self::OutputMeta, NokhwaError> {
|
) -> Result<Self::OutputMeta, NokhwaError> {
|
||||||
let destination_format = match destination_format {
|
let format = self.config().custom_frame_format_map.as_ref().and_then(|m| {
|
||||||
Some(df) => df,
|
match self.config().yuv_type {
|
||||||
None => return Err(NokhwaError::DecoderDestinationHintRequired),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let yuv_format = self.config().custom_frame_format_map.as_ref().map(|m| {
|
|
||||||
match self.config.yuv_type {
|
|
||||||
FrameFormat::Custom(cfmt) => {
|
FrameFormat::Custom(cfmt) => {
|
||||||
m.get(&cfmt).copied()
|
m.get(&cfmt).copied()
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}).flatten().unwrap_or(self.config.yuv_type);
|
}).unwrap_or(self.config().yuv_type);
|
||||||
|
|
||||||
|
|
||||||
let buffer = buffer.as_mut();
|
let buffer = buffer.as_mut();
|
||||||
if buffer.len() < self.output_decoder_min_size(self.config.resolution, destination_format) {
|
if buffer.len() < self.output_decoder_min_size(self.config.resolution, destination_format)? {
|
||||||
return Err(NokhwaError::DecoderInvalidBuffer("Too small!".to_string()));
|
return Err(NokhwaError::DecoderInvalidBuffer("Too small!".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let stride = figure_out_stride(yuv_format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))?;
|
let stride = figure_out_stride(format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(format))?;
|
||||||
let byte_width = figure_out_byte_width(yuv_format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))?;
|
let byte_width = figure_out_byte_width(format).ok_or(NokhwaError::DecoderUnsupportedFrameFormat(format))?;
|
||||||
|
|
||||||
|
|
||||||
let stride_3px = 3 *
|
let stride_3px = 3 *
|
||||||
@@ -103,10 +95,10 @@ impl Decoder for YUVDecoder {
|
|||||||
let stride_4px_2w = 8 * self.config.resolution.width();
|
let stride_4px_2w = 8 * self.config.resolution.width();
|
||||||
|
|
||||||
// todo: clean up ts into a macro </3
|
// todo: clean up ts into a macro </3
|
||||||
let decode_status = match stride {
|
let decode_status = match stride {
|
||||||
Stride::Packed(stride) => {
|
Stride::Packed(stride) => {
|
||||||
let image = prepare_to_packed_image(&to_decode, self.config.resolution, byte_width, stride);
|
let image = prepare_to_packed_image(&to_decode, self.config.resolution, stride);
|
||||||
match yuv_format {
|
match format {
|
||||||
FrameFormat::Ayuv_32 => {
|
FrameFormat::Ayuv_32 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(ayuv_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.premultiply_alpha)),
|
PixelDestination::Rgb8 => Some(ayuv_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.premultiply_alpha)),
|
||||||
@@ -117,41 +109,45 @@ impl Decoder for YUVDecoder {
|
|||||||
FrameFormat::Yuyv_4_2_2 => {
|
FrameFormat::Yuyv_4_2_2 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuyv422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb8 => Some(yuyv422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba8 => Some(yuyv422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba8 => Some(yuyv422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgb16 => Some(yuyv422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb16 => Some(yuyv422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba16 => Some(yuyv422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba16 => Some(yuyv422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgr8 => Some(yuyv422_to_bgr(&image, buffer, stride_4px_2w, self.config.range, self.config.matrix)),
|
PixelDestination::Bgr8 => Some(yuyv422_to_bgr(&image, buffer, stride_4px_2w, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgra8 => Some(yuyv422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgra8 => Some(yuyv422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::Uyvy_4_2_2 => {
|
FrameFormat::Uyvy_4_2_2 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(uyvy422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb8 => Some(uyvy422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba8 => Some(uyvy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba8 => Some(uyvy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgb16 => Some(uyvy422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb16 => Some(uyvy422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba16 => Some(uyvy422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba16 => Some(uyvy422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgr8 => Some(uyvy422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgr8 => Some(uyvy422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgra8 => Some(uyvy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgra8 => Some(uyvy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::Vyuy_4_2_2 => {
|
FrameFormat::Vyuy_4_2_2 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(vyuy422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb8 => Some(vyuy422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba8 => Some(vyuy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba8 => Some(vyuy422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgb16 => Some(vyuy422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb16 => Some(vyuy422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba16 => Some(vyuy422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba16 => Some(vyuy422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgr8 => Some(vyuy422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgr8 => Some(vyuy422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgra8 => Some(vyuy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgra8 => Some(vyuy422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::Yvyu_4_2_2 => {
|
FrameFormat::Yvyu_4_2_2 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yvyu422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb8 => Some(yvyu422_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba8 => Some(yvyu422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba8 => Some(yvyu422_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgb16 => Some(yvyu422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb16 => Some(yvyu422_to_rgb_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba16 => Some(yvyu422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba16 => Some(yvyu422_to_rgba_p16(&convert_packed_image_to_u16(image), cast_slice_mut(buffer), stride_3px_2w, 16, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgr8 => Some(yvyu422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgr8 => Some(yvyu422_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgra8 => Some(yvyu422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgra8 => Some(yvyu422_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -159,64 +155,64 @@ impl Decoder for YUVDecoder {
|
|||||||
return Err(NokhwaError::NotImplementedError("etto blehhh! ()".to_string()))
|
return Err(NokhwaError::NotImplementedError("etto blehhh! ()".to_string()))
|
||||||
}
|
}
|
||||||
// shouldnt happen
|
// shouldnt happen
|
||||||
return Err(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))
|
return Err(NokhwaError::DecoderUnsupportedFrameFormat(format))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stride::Semi(y_stride, uv_stride) => {
|
Stride::Semi(y_stride, uv_stride) => {
|
||||||
let image = prepare_to_semi_planar_image(&to_decode, self.config.resolution, byte_width, y_stride, uv_stride);
|
let image = prepare_to_semi_planar_image(&to_decode, self.config.resolution, byte_width, y_stride, uv_stride);
|
||||||
match yuv_format {
|
match format {
|
||||||
FrameFormat::NV24 => {
|
FrameFormat::NV24 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv_nv24_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(yuv_nv24_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(yuv_nv24_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(yuv_nv24_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(yuv_nv24_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(yuv_nv24_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(yuv_nv24_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(yuv_nv24_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::NV42 => {
|
FrameFormat::NV42 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv_nv42_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(yuv_nv42_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(yuv_nv42_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(yuv_nv42_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(yuv_nv42_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(yuv_nv42_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(yuv_nv42_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(yuv_nv42_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::NV16 => {
|
FrameFormat::NV16 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv_nv16_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(yuv_nv16_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(yuv_nv16_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(yuv_nv16_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(yuv_nv16_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(yuv_nv16_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(yuv_nv16_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(yuv_nv16_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::NV61 => {
|
FrameFormat::NV61 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv_nv61_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(yuv_nv61_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(yuv_nv61_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(yuv_nv61_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(yuv_nv61_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(yuv_nv61_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(yuv_nv61_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(yuv_nv61_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::NV12 => {
|
FrameFormat::NV12 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv_nv12_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(yuv_nv12_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(yuv_nv12_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(yuv_nv12_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(yuv_nv12_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(yuv_nv12_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(yuv_nv12_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(yuv_nv12_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::NV21 => {
|
FrameFormat::NV21 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv_nv21_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(yuv_nv21_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(yuv_nv21_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(yuv_nv21_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(yuv_nv21_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(yuv_nv21_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(yuv_nv21_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(yuv_nv21_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,12 +220,12 @@ impl Decoder for YUVDecoder {
|
|||||||
let a = convert_bi_planar_image_to_u16(image);
|
let a = convert_bi_planar_image_to_u16(image);
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(p010_to_rgb(&a, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgb8 => Some(p010_to_rgb(&a, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgba8 => Some(p010_to_rgba(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Rgba8 => Some(p010_to_rgba(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgr8 => Some(p010_to_bgr(&a, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgr8 => Some(p010_to_bgr(&a, buffer, stride_3px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Bgra8 => Some(p010_to_bgra(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
PixelDestination::Bgra8 => Some(p010_to_bgra(&a, buffer, stride_4px, self.config.range, self.config.matrix, self.config.mode)),
|
||||||
PixelDestination::Rgb16 => Some(p010_to_rgb10(&a, cast_slice_mut(buffer), stride_3px_2w, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb16 => Some(p010_to_rgb10(&a, cast_slice_mut(buffer), stride_3px_2w, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba16 => Some(p010_to_rgba10(&a, cast_slice_mut(buffer), stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba16 => Some(p010_to_rgba10(&a, cast_slice_mut(buffer), stride_4px, self.config.range, self.config.matrix)),
|
||||||
// _ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrameFormat::P012 => {
|
FrameFormat::P012 => {
|
||||||
@@ -240,32 +236,32 @@ impl Decoder for YUVDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if FrameFormat::YCBCR_SEMI.contains(&yuv_format) {
|
if FrameFormat::YCBCR_SEMI.contains(&format) {
|
||||||
return Err(NokhwaError::NotImplementedError("etto blehhh!".to_string()))
|
return Err(NokhwaError::NotImplementedError("etto blehhh!".to_string()))
|
||||||
}
|
}
|
||||||
// shouldnt happen
|
// shouldnt happen
|
||||||
return Err(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))
|
return Err(NokhwaError::DecoderUnsupportedFrameFormat(format))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stride::Planar(y_stride, u_stride, v_stride, line_ratio) => {
|
Stride::Planar(y_stride, u_stride, v_stride, line_ratio) => {
|
||||||
let image = prepare_to_planar_image(&to_decode, self.config.resolution, byte_width, y_stride, u_stride, v_stride, line_ratio);
|
let image = prepare_to_planar_image(&to_decode, self.config.resolution, byte_width, y_stride, u_stride, v_stride, line_ratio);
|
||||||
match yuv_format {
|
match format {
|
||||||
FrameFormat::Yuv_4_2_0 => {
|
FrameFormat::Yuv_4_2_0 => {
|
||||||
match destination_format {
|
match destination_format {
|
||||||
PixelDestination::Rgb8 => Some(yuv420_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgb8 => Some(yuv420_to_rgb(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Rgba8 => Some(yuv420_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Rgba8 => Some(yuv420_to_rgba(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgr8 => Some(yuv420_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgr8 => Some(yuv420_to_bgr(&image, buffer, stride_3px, self.config.range, self.config.matrix)),
|
||||||
PixelDestination::Bgra8 => Some(yuv420_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
PixelDestination::Bgra8 => Some(yuv420_to_bgra(&image, buffer, stride_4px, self.config.range, self.config.matrix)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if FrameFormat::YCBCR_PLANAR.contains(&yuv_format) {
|
if FrameFormat::YCBCR_PLANAR.contains(&format) {
|
||||||
return Err(NokhwaError::NotImplementedError("etto blehhh!".to_string()))
|
return Err(NokhwaError::NotImplementedError("etto blehhh!".to_string()))
|
||||||
}
|
}
|
||||||
// shouldnt happen
|
// shouldnt happen
|
||||||
return Err(NokhwaError::DecoderUnsupportedFrameFormat(yuv_format))
|
return Err(NokhwaError::DecoderUnsupportedFrameFormat(format))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,50 +270,10 @@ impl Decoder for YUVDecoder {
|
|||||||
Some(Ok(_)) => Ok(()),
|
Some(Ok(_)) => Ok(()),
|
||||||
Some(Err(why)) => Err(NokhwaError::Decoder(why.to_string())),
|
Some(Err(why)) => Err(NokhwaError::Decoder(why.to_string())),
|
||||||
None => Err(NokhwaError::DecoderUnsupportedFrameFormat(
|
None => Err(NokhwaError::DecoderUnsupportedFrameFormat(
|
||||||
yuv_format,
|
format,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<P: Pixel>(
|
|
||||||
&mut self,
|
|
||||||
to_decode: FrameBuffer<'_>,
|
|
||||||
) -> Result<DecodedImage<P, Self::OutputMeta>, NokhwaError>
|
|
||||||
where
|
|
||||||
<P as Pixel>::Subpixel: NonFloatScalarWidth,
|
|
||||||
{
|
|
||||||
let min_size_alloc = self.output_decoder_min_size_pixel::<P>(self.config.resolution);
|
|
||||||
let mut out_buffer: Vec<P::Subpixel> = vec![P::Subpixel::DEFAULT_MIN_VALUE; min_size_alloc];
|
|
||||||
self.decode_to_pixel_buffer::<P>(to_decode, &mut out_buffer)?;
|
|
||||||
Ok(DecodedImage::new(
|
|
||||||
ImageBuffer::from_vec(
|
|
||||||
self.config.resolution.width(),
|
|
||||||
self.config.resolution.height(),
|
|
||||||
out_buffer,
|
|
||||||
)
|
|
||||||
.ok_or(NokhwaError::Decoder(
|
|
||||||
"failed to convert into an image buffer".to_string(),
|
|
||||||
))?,
|
|
||||||
(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output_decoder_min_size(
|
|
||||||
&self,
|
|
||||||
resolution: Resolution,
|
|
||||||
destination_format: PixelDestination,
|
|
||||||
) -> Result<usize, NokhwaError> {
|
|
||||||
let px_size = match destination_format {
|
|
||||||
PixelDestination::Rgb8 | PixelDestination::Bgr8 => 3,
|
|
||||||
PixelDestination::Rgba8 | PixelDestination::Bgra8 => 4,
|
|
||||||
PixelDestination::Rgb16 => 3 * 2,
|
|
||||||
PixelDestination::Rgba16 => 4 * 2,
|
|
||||||
_ => return Err(NokhwaError::DecoderUnsupportedDestinationPixelFormat(destination_format))
|
|
||||||
};
|
|
||||||
let reso = resolution.width() * resolution.height();
|
|
||||||
Ok((reso as usize) * (px_size as usize))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@@ -331,6 +287,12 @@ pub struct YUVConfig {
|
|||||||
pub custom_frame_format_map: Option<HashMap<CustomFrameFormat, FrameFormat>>,
|
pub custom_frame_format_map: Option<HashMap<CustomFrameFormat, FrameFormat>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConfigHasResolution for YUVConfig {
|
||||||
|
fn resolution(&self) -> Resolution {
|
||||||
|
self.resolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<CameraFormat> for YUVConfig {
|
impl TryFrom<CameraFormat> for YUVConfig {
|
||||||
type Error = NokhwaError;
|
type Error = NokhwaError;
|
||||||
|
|
||||||
@@ -420,7 +382,6 @@ fn planar_stride(format: FrameFormat) -> Option<(u32, u32, u32, u32)> {
|
|||||||
fn prepare_to_packed_image<'a>(
|
fn prepare_to_packed_image<'a>(
|
||||||
frame_buffer: &'a FrameBuffer<'a>,
|
frame_buffer: &'a FrameBuffer<'a>,
|
||||||
resolution: Resolution,
|
resolution: Resolution,
|
||||||
byte_width: u32,
|
|
||||||
yuy_stride: u32,
|
yuy_stride: u32,
|
||||||
) -> YuvPackedImage<'a, u8> {
|
) -> YuvPackedImage<'a, u8> {
|
||||||
YuvPackedImage {
|
YuvPackedImage {
|
||||||
|
|||||||
@@ -44,45 +44,39 @@ impl<I, const MULTIPLIER: usize> Iterator for DuplicateConst<I, MULTIPLIER> wher
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.state {
|
match self.state {
|
||||||
DuplicateConstState::Started => {
|
DuplicateConstState::Started => {
|
||||||
match self.iter.next() {
|
if let Some(i) = self.iter.next() {
|
||||||
Some(i) => {
|
if MULTIPLIER <= 1 {
|
||||||
if MULTIPLIER <= 1 {
|
self.state = DuplicateConstState::EmitReal;
|
||||||
self.state = DuplicateConstState::EmitReal;
|
} else {
|
||||||
} else {
|
self.state = DuplicateConstState::EmitDupe;
|
||||||
self.state = DuplicateConstState::EmitDupe;
|
|
||||||
}
|
|
||||||
self.last_iter_item = Some(i.clone());
|
|
||||||
Some(i)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.state = DuplicateConstState::Finished;
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
self.last_iter_item = Some(i.clone());
|
||||||
|
Some(i)
|
||||||
|
} else {
|
||||||
|
self.state = DuplicateConstState::Finished;
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DuplicateConstState::EmitDupe => {
|
DuplicateConstState::EmitDupe => {
|
||||||
self.running_count = self.running_count.saturating_sub(1);
|
self.running_count = self.running_count.saturating_sub(1);
|
||||||
if self.running_count <= 0 {
|
if self.running_count == 0 {
|
||||||
self.state = DuplicateConstState::EmitReal;
|
self.state = DuplicateConstState::EmitReal;
|
||||||
}
|
}
|
||||||
self.last_iter_item.clone()
|
self.last_iter_item.clone()
|
||||||
}
|
}
|
||||||
DuplicateConstState::EmitReal => {
|
DuplicateConstState::EmitReal => {
|
||||||
match self.iter.next() {
|
if let Some(i) = self.iter.next() {
|
||||||
Some(i) => {
|
self.last_iter_item = Some(i.clone());
|
||||||
self.last_iter_item = Some(i.clone());
|
self.running_count = MULTIPLIER.saturating_sub(1);
|
||||||
self.running_count = MULTIPLIER.saturating_sub(1);
|
if MULTIPLIER <= 1 {
|
||||||
if MULTIPLIER <= 1 {
|
self.state = DuplicateConstState::EmitReal;
|
||||||
self.state = DuplicateConstState::EmitReal;
|
} else {
|
||||||
} else {
|
self.state = DuplicateConstState::EmitDupe;
|
||||||
self.state = DuplicateConstState::EmitDupe;
|
|
||||||
}
|
|
||||||
Some(i)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.state = DuplicateConstState::Finished;
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
Some(i)
|
||||||
|
} else {
|
||||||
|
self.state = DuplicateConstState::Finished;
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DuplicateConstState::Finished => {
|
DuplicateConstState::Finished => {
|
||||||
|
|||||||
@@ -58,23 +58,20 @@ impl<I, const PER: usize> Iterator for Interweave<I, PER> where I: Iterator, <I
|
|||||||
}
|
}
|
||||||
InterweaveState::EmitReal => {
|
InterweaveState::EmitReal => {
|
||||||
self.count = self.count.saturating_sub(1);
|
self.count = self.count.saturating_sub(1);
|
||||||
match self.iter.next() {
|
if let Some(i) = self.iter.next() {
|
||||||
Some(i) => {
|
if self.count == 0 {
|
||||||
if self.count <= 0 {
|
self.state = InterweaveState::EmitFake;
|
||||||
self.state = InterweaveState::EmitFake;
|
} else {
|
||||||
} else {
|
self.state = InterweaveState::EmitReal;
|
||||||
self.state = InterweaveState::EmitReal;
|
|
||||||
}
|
|
||||||
self.prev_state = InterweaveState::EmitReal;
|
|
||||||
Some(i)
|
|
||||||
}
|
}
|
||||||
None => {
|
self.prev_state = InterweaveState::EmitReal;
|
||||||
self.state = InterweaveState::Finished;
|
Some(i)
|
||||||
if self.emit_last && self.prev_state != InterweaveState::EmitFake {
|
} else {
|
||||||
Some(self.element.clone())
|
self.state = InterweaveState::Finished;
|
||||||
} else {
|
if self.emit_last && self.prev_state != InterweaveState::EmitFake {
|
||||||
None
|
Some(self.element.clone())
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +88,7 @@ impl<I, const PER: usize> Iterator for Interweave<I, PER> where I: Iterator, <I
|
|||||||
return (lower * 2, upper.map(|u| u * 2))
|
return (lower * 2, upper.map(|u| u * 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
let last = if self.emit_last { 1 } else { 0 };
|
let last = usize::from(self.emit_last);
|
||||||
let new_lower = lower + (lower / PER) + last;
|
let new_lower = lower + (lower / PER) + last;
|
||||||
let new_upper = upper.map(|u| { u + (u / PER) + last });
|
let new_upper = upper.map(|u| { u + (u / PER) + last });
|
||||||
(new_lower, new_upper)
|
(new_lower, new_upper)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
#[warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
|
|
||||||
pub mod interweave;
|
pub mod interweave;
|
||||||
pub mod duplicate;
|
pub mod duplicate;
|
||||||
|
|||||||
Reference in New Issue
Block a user