#![warn(missing_docs)]
#![allow(clippy::too_many_arguments)]
mod sys;
mod compare;
mod convert;
mod planar;
mod rotate;
mod scale;
pub use compare::*;
pub use convert::*;
pub use planar::*;
pub use rotate::*;
pub use scale::*;
pub const BUILD_REPOSITORY: &str = sys::BUILD_METADATA_REPOSITORY;
pub const BUILD_VERSION: &str = sys::BUILD_METADATA_VERSION;
#[derive(Debug)]
pub struct Error {
code: i32,
function: &'static str,
reason: Option<&'static str>,
}
impl Error {
fn new(code: i32, function: &'static str, reason: Option<&'static str>) -> Self {
Self {
code,
function,
reason,
}
}
fn with_reason(code: i32, function: &'static str, reason: &'static str) -> Self {
Self::new(code, function, Some(reason))
}
fn check(code: i32, function: &'static str) -> Result<(), Self> {
if code == 0 {
Ok(())
} else {
Err(Self::new(code, function, None))
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(reason) = self.reason {
write!(
f,
"{}() failed: code={}, reason={reason}",
self.function, self.code
)
} else {
write!(f, "{}() failed: code={}", self.function, self.code)
}
}
}
impl std::error::Error for Error {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FilterMode {
None,
Linear,
Bilinear,
Box,
}
impl FilterMode {
fn to_sys(self) -> sys::FilterMode {
match self {
FilterMode::None => sys::FilterMode_kFilterNone,
FilterMode::Linear => sys::FilterMode_kFilterLinear,
FilterMode::Bilinear => sys::FilterMode_kFilterBilinear,
FilterMode::Box => sys::FilterMode_kFilterBox,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RotationMode {
None,
Rotate90,
Rotate180,
Rotate270,
}
impl RotationMode {
fn to_sys(self) -> sys::RotationMode {
match self {
RotationMode::None => sys::RotationMode_kRotate0,
RotationMode::Rotate90 => sys::RotationMode_kRotate90,
RotationMode::Rotate180 => sys::RotationMode_kRotate180,
RotationMode::Rotate270 => sys::RotationMode_kRotate270,
}
}
pub(crate) fn output_size(self, src: ImageSize) -> ImageSize {
match self {
RotationMode::None | RotationMode::Rotate180 => src,
RotationMode::Rotate90 | RotationMode::Rotate270 => {
ImageSize::new(src.height, src.width)
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct ImageSize {
pub width: usize,
pub height: usize,
}
impl ImageSize {
pub const fn new(width: usize, height: usize) -> Self {
Self { width, height }
}
}
use std::ffi::c_int;
fn require_c_int(value: usize, function: &'static str, reason: &'static str) -> Result<(), Error> {
if c_int::try_from(value).is_err() {
return Err(Error::with_reason(-1, function, reason));
}
Ok(())
}
fn checked_buf_size(
stride: usize,
height: usize,
function: &'static str,
reason: &'static str,
) -> Result<usize, Error> {
stride
.checked_mul(height)
.ok_or_else(|| Error::with_reason(-1, function, reason))
}
fn validate_yuv_src_inner(
y: &[u8],
y_stride: usize,
u: &[u8],
u_stride: usize,
v: &[u8],
v_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(u_stride, function, "U stride exceeds c_int range")?;
require_c_int(v_stride, function, "V stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let uv_width = size.width.div_ceil(uv_width_divisor);
if u_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"U stride smaller than chroma width",
));
}
if v_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"V stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"source Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let u_size = checked_buf_size(u_stride, uv_height, function, "U buffer size overflow")?;
if u.len() < u_size {
return Err(Error::with_reason(
-1,
function,
"source U buffer too small",
));
}
let v_size = checked_buf_size(v_stride, uv_height, function, "V buffer size overflow")?;
if v.len() < v_size {
return Err(Error::with_reason(
-1,
function,
"source V buffer too small",
));
}
Ok(())
}
fn validate_yuv_dst_inner(
y: &[u8],
y_stride: usize,
u: &[u8],
u_stride: usize,
v: &[u8],
v_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(u_stride, function, "U stride exceeds c_int range")?;
require_c_int(v_stride, function, "V stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let uv_width = size.width.div_ceil(uv_width_divisor);
if u_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"U stride smaller than chroma width",
));
}
if v_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"V stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"destination Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let u_size = checked_buf_size(u_stride, uv_height, function, "U buffer size overflow")?;
if u.len() < u_size {
return Err(Error::with_reason(
-1,
function,
"destination U buffer too small",
));
}
let v_size = checked_buf_size(v_stride, uv_height, function, "V buffer size overflow")?;
if v.len() < v_size {
return Err(Error::with_reason(
-1,
function,
"destination V buffer too small",
));
}
Ok(())
}
fn validate_nv_src_inner(
y: &[u8],
y_stride: usize,
uv: &[u8],
uv_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(uv_stride, function, "UV stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let min_uv_stride = size
.width
.div_ceil(uv_width_divisor)
.checked_mul(2)
.ok_or_else(|| Error::with_reason(-1, function, "UV minimum stride overflow"))?;
if uv_stride < min_uv_stride {
return Err(Error::with_reason(
-1,
function,
"UV stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"source Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let uv_size = checked_buf_size(uv_stride, uv_height, function, "UV buffer size overflow")?;
if uv.len() < uv_size {
return Err(Error::with_reason(
-1,
function,
"source UV buffer too small",
));
}
Ok(())
}
fn validate_nv_dst_inner(
y: &[u8],
y_stride: usize,
uv: &[u8],
uv_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(uv_stride, function, "UV stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let min_uv_stride = size
.width
.div_ceil(uv_width_divisor)
.checked_mul(2)
.ok_or_else(|| Error::with_reason(-1, function, "UV minimum stride overflow"))?;
if uv_stride < min_uv_stride {
return Err(Error::with_reason(
-1,
function,
"UV stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"destination Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let uv_size = checked_buf_size(uv_stride, uv_height, function, "UV buffer size overflow")?;
if uv.len() < uv_size {
return Err(Error::with_reason(
-1,
function,
"destination UV buffer too small",
));
}
Ok(())
}
fn validate_yuv16_src_inner(
y: &[u16],
y_stride: usize,
u: &[u16],
u_stride: usize,
v: &[u16],
v_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(u_stride, function, "U stride exceeds c_int range")?;
require_c_int(v_stride, function, "V stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let uv_width = size.width.div_ceil(uv_width_divisor);
if u_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"U stride smaller than chroma width",
));
}
if v_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"V stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"source Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let u_size = checked_buf_size(u_stride, uv_height, function, "U buffer size overflow")?;
if u.len() < u_size {
return Err(Error::with_reason(
-1,
function,
"source U buffer too small",
));
}
let v_size = checked_buf_size(v_stride, uv_height, function, "V buffer size overflow")?;
if v.len() < v_size {
return Err(Error::with_reason(
-1,
function,
"source V buffer too small",
));
}
Ok(())
}
fn validate_yuv16_dst_inner(
y: &[u16],
y_stride: usize,
u: &[u16],
u_stride: usize,
v: &[u16],
v_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(u_stride, function, "U stride exceeds c_int range")?;
require_c_int(v_stride, function, "V stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let uv_width = size.width.div_ceil(uv_width_divisor);
if u_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"U stride smaller than chroma width",
));
}
if v_stride < uv_width {
return Err(Error::with_reason(
-1,
function,
"V stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"destination Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let u_size = checked_buf_size(u_stride, uv_height, function, "U buffer size overflow")?;
if u.len() < u_size {
return Err(Error::with_reason(
-1,
function,
"destination U buffer too small",
));
}
let v_size = checked_buf_size(v_stride, uv_height, function, "V buffer size overflow")?;
if v.len() < v_size {
return Err(Error::with_reason(
-1,
function,
"destination V buffer too small",
));
}
Ok(())
}
fn validate_nv16_src_inner(
y: &[u16],
y_stride: usize,
uv: &[u16],
uv_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(uv_stride, function, "UV stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let min_uv_stride = size
.width
.div_ceil(uv_width_divisor)
.checked_mul(2)
.ok_or_else(|| Error::with_reason(-1, function, "UV minimum stride overflow"))?;
if uv_stride < min_uv_stride {
return Err(Error::with_reason(
-1,
function,
"UV stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"source Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let uv_size = checked_buf_size(uv_stride, uv_height, function, "UV buffer size overflow")?;
if uv.len() < uv_size {
return Err(Error::with_reason(
-1,
function,
"source UV buffer too small",
));
}
Ok(())
}
fn validate_nv16_dst_inner(
y: &[u16],
y_stride: usize,
uv: &[u16],
uv_stride: usize,
size: ImageSize,
uv_height_divisor: usize,
uv_width_divisor: usize,
function: &'static str,
) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(y_stride, function, "Y stride exceeds c_int range")?;
require_c_int(uv_stride, function, "UV stride exceeds c_int range")?;
if y_stride < size.width {
return Err(Error::with_reason(
-1,
function,
"Y stride smaller than width",
));
}
let min_uv_stride = size
.width
.div_ceil(uv_width_divisor)
.checked_mul(2)
.ok_or_else(|| Error::with_reason(-1, function, "UV minimum stride overflow"))?;
if uv_stride < min_uv_stride {
return Err(Error::with_reason(
-1,
function,
"UV stride smaller than chroma width",
));
}
let y_size = checked_buf_size(y_stride, size.height, function, "Y buffer size overflow")?;
if y.len() < y_size {
return Err(Error::with_reason(
-1,
function,
"destination Y buffer too small",
));
}
let uv_height = size.height.div_ceil(uv_height_divisor);
let uv_size = checked_buf_size(uv_stride, uv_height, function, "UV buffer size overflow")?;
if uv.len() < uv_size {
return Err(Error::with_reason(
-1,
function,
"destination UV buffer too small",
));
}
Ok(())
}
macro_rules! define_yuv_image {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident, $uv_height_div:expr, $uv_width_div:expr) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub y: &'a [u8],
pub y_stride: usize,
pub u: &'a [u8],
pub u_stride: usize,
pub v: &'a [u8],
pub v_stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_yuv_src_inner(
self.y, self.y_stride,
self.u, self.u_stride,
self.v, self.v_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub y: &'a mut [u8],
pub y_stride: usize,
pub u: &'a mut [u8],
pub u_stride: usize,
pub v: &'a mut [u8],
pub v_stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
y: self.y,
y_stride: self.y_stride,
u: self.u,
u_stride: self.u_stride,
v: self.v,
v_stride: self.v_stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_yuv_dst_inner(
self.y, self.y_stride,
self.u, self.u_stride,
self.v, self.v_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
};
}
macro_rules! define_y_image {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub y: &'a [u8],
pub y_stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(self.y_stride, function, "Y stride exceeds c_int range")?;
if self.y_stride < size.width {
return Err(Error::with_reason(-1, function, "Y stride smaller than width"));
}
let buf_size = checked_buf_size(self.y_stride, size.height, function, "buffer size overflow")?;
if self.y.len() < buf_size {
return Err(Error::with_reason(-1, function, "source Y buffer too small"));
}
Ok(())
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub y: &'a mut [u8],
pub y_stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
y: self.y,
y_stride: self.y_stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(self.y_stride, function, "Y stride exceeds c_int range")?;
if self.y_stride < size.width {
return Err(Error::with_reason(-1, function, "Y stride smaller than width"));
}
let buf_size = checked_buf_size(self.y_stride, size.height, function, "buffer size overflow")?;
if self.y.len() < buf_size {
return Err(Error::with_reason(-1, function, "destination Y buffer too small"));
}
Ok(())
}
}
};
}
macro_rules! define_nv_image {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident, $uv_height_div:expr, $uv_width_div:expr) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub y: &'a [u8],
pub y_stride: usize,
pub uv: &'a [u8],
pub uv_stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_nv_src_inner(
self.y, self.y_stride,
self.uv, self.uv_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub y: &'a mut [u8],
pub y_stride: usize,
pub uv: &'a mut [u8],
pub uv_stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
y: self.y,
y_stride: self.y_stride,
uv: self.uv,
uv_stride: self.uv_stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_nv_dst_inner(
self.y, self.y_stride,
self.uv, self.uv_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
};
}
macro_rules! define_packed_image {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident, $bpp:expr) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub data: &'a [u8],
pub stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(self.stride, function, "stride exceeds c_int range")?;
let min_stride = size.width.checked_mul($bpp)
.ok_or_else(|| Error::with_reason(-1, function, "minimum stride overflow"))?;
if self.stride < min_stride {
return Err(Error::with_reason(-1, function, "stride smaller than width * bpp"));
}
let buf_size = checked_buf_size(self.stride, size.height, function, "buffer size overflow")?;
if self.data.len() < buf_size {
return Err(Error::with_reason(-1, function, "source buffer too small"));
}
Ok(())
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub data: &'a mut [u8],
pub stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
data: self.data,
stride: self.stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(self.stride, function, "stride exceeds c_int range")?;
let min_stride = size.width.checked_mul($bpp)
.ok_or_else(|| Error::with_reason(-1, function, "minimum stride overflow"))?;
if self.stride < min_stride {
return Err(Error::with_reason(-1, function, "stride smaller than width * bpp"));
}
let buf_size = checked_buf_size(self.stride, size.height, function, "buffer size overflow")?;
if self.data.len() < buf_size {
return Err(Error::with_reason(-1, function, "destination buffer too small"));
}
Ok(())
}
}
};
}
macro_rules! define_yuv_image16 {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident, $uv_height_div:expr, $uv_width_div:expr) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub y: &'a [u16],
pub y_stride: usize,
pub u: &'a [u16],
pub u_stride: usize,
pub v: &'a [u16],
pub v_stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_yuv16_src_inner(
self.y, self.y_stride,
self.u, self.u_stride,
self.v, self.v_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub y: &'a mut [u16],
pub y_stride: usize,
pub u: &'a mut [u16],
pub u_stride: usize,
pub v: &'a mut [u16],
pub v_stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
y: self.y,
y_stride: self.y_stride,
u: self.u,
u_stride: self.u_stride,
v: self.v,
v_stride: self.v_stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_yuv16_dst_inner(
self.y, self.y_stride,
self.u, self.u_stride,
self.v, self.v_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
};
}
macro_rules! define_nv_image16 {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident, $uv_height_div:expr, $uv_width_div:expr) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub y: &'a [u16],
pub y_stride: usize,
pub uv: &'a [u16],
pub uv_stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_nv16_src_inner(
self.y, self.y_stride,
self.uv, self.uv_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub y: &'a mut [u16],
pub y_stride: usize,
pub uv: &'a mut [u16],
pub uv_stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
y: self.y,
y_stride: self.y_stride,
uv: self.uv,
uv_stride: self.uv_stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
validate_nv16_dst_inner(
self.y, self.y_stride,
self.uv, self.uv_stride,
size, $uv_height_div, $uv_width_div, function,
)
}
}
};
}
macro_rules! define_packed_image16 {
($(#[doc = $doc:expr])* $name:ident, $(#[doc = $doc_mut:expr])* $name_mut:ident, $epp:expr) => {
$(#[doc = $doc])*
#[derive(Debug)]
pub struct $name<'a> {
pub data: &'a [u16],
pub stride: usize,
}
impl $name<'_> {
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(self.stride, function, "stride exceeds c_int range")?;
let min_stride = size.width.checked_mul($epp)
.ok_or_else(|| Error::with_reason(-1, function, "minimum stride overflow"))?;
if self.stride < min_stride {
return Err(Error::with_reason(-1, function, "stride smaller than width * epp"));
}
let buf_size = checked_buf_size(self.stride, size.height, function, "buffer size overflow")?;
if self.data.len() < buf_size {
return Err(Error::with_reason(-1, function, "source buffer too small"));
}
Ok(())
}
}
$(#[doc = $doc_mut])*
#[derive(Debug)]
pub struct $name_mut<'a> {
pub data: &'a mut [u16],
pub stride: usize,
}
impl $name_mut<'_> {
pub fn as_ref(&self) -> $name<'_> {
$name {
data: self.data,
stride: self.stride,
}
}
#[allow(dead_code)]
pub(crate) fn validate(&self, size: ImageSize, function: &'static str) -> Result<(), Error> {
require_c_int(size.width, function, "width exceeds c_int range")?;
require_c_int(size.height, function, "height exceeds c_int range")?;
require_c_int(self.stride, function, "stride exceeds c_int range")?;
let min_stride = size.width.checked_mul($epp)
.ok_or_else(|| Error::with_reason(-1, function, "minimum stride overflow"))?;
if self.stride < min_stride {
return Err(Error::with_reason(-1, function, "stride smaller than width * epp"));
}
let buf_size = checked_buf_size(self.stride, size.height, function, "buffer size overflow")?;
if self.data.len() < buf_size {
return Err(Error::with_reason(-1, function, "destination buffer too small"));
}
Ok(())
}
}
};
}
define_yuv_image!( I420Image, I420ImageMut, 2, 2);
define_yuv_image!( J420Image, J420ImageMut, 2, 2);
define_yuv_image!( H420Image, H420ImageMut, 2, 2);
define_yuv_image!( U420Image, U420ImageMut, 2, 2);
define_yuv_image!( Android420Image, Android420ImageMut, 2, 2);
define_yuv_image!( I422Image, I422ImageMut, 1, 2);
define_yuv_image!( J422Image, J422ImageMut, 1, 2);
define_yuv_image!( H422Image, H422ImageMut, 1, 2);
define_yuv_image!( U422Image, U422ImageMut, 1, 2);
define_yuv_image!( I444Image, I444ImageMut, 1, 1);
define_yuv_image!( J444Image, J444ImageMut, 1, 1);
define_yuv_image!( H444Image, H444ImageMut, 1, 1);
define_yuv_image!( U444Image, U444ImageMut, 1, 1);
define_y_image!( I400Image, I400ImageMut);
define_y_image!( J400Image, J400ImageMut);
define_nv_image!( Nv12Image, Nv12ImageMut, 2, 2);
define_nv_image!( Nv21Image, Nv21ImageMut, 2, 2);
define_nv_image!( Mm21Image, Mm21ImageMut, 2, 2);
define_nv_image!( Mt2tImage, Mt2tImageMut, 2, 2);
define_nv_image!( Nv16Image, Nv16ImageMut, 1, 2);
define_nv_image!( Nv24Image, Nv24ImageMut, 1, 1);
define_packed_image!( ArgbImage, ArgbImageMut, 4);
define_packed_image!( AbgrImage, AbgrImageMut, 4);
define_packed_image!( RgbaImage, RgbaImageMut, 4);
define_packed_image!( BgraImage, BgraImageMut, 4);
define_packed_image!( Ar30Image, Ar30ImageMut, 4);
define_packed_image!( Ab30Image, Ab30ImageMut, 4);
define_packed_image!( AyuvImage, AyuvImageMut, 4);
define_packed_image!( Rgb24Image, Rgb24ImageMut, 3);
define_packed_image!( RawImage, RawImageMut, 3);
define_packed_image!( Yuv24Image, Yuv24ImageMut, 3);
define_packed_image!( Rgb565Image, Rgb565ImageMut, 2);
define_packed_image!( Argb1555Image, Argb1555ImageMut, 2);
define_packed_image!( Argb4444Image, Argb4444ImageMut, 2);
define_packed_image!( Yuy2Image, Yuy2ImageMut, 2);
define_packed_image!( UyvyImage, UyvyImageMut, 2);
define_yuv_image16!( I010Image, I010ImageMut, 2, 2);
define_yuv_image16!( I012Image, I012ImageMut, 2, 2);
define_yuv_image16!( H010Image, H010ImageMut, 2, 2);
define_yuv_image16!( U010Image, U010ImageMut, 2, 2);
define_yuv_image16!( I210Image, I210ImageMut, 1, 2);
define_yuv_image16!( I212Image, I212ImageMut, 1, 2);
define_yuv_image16!( H210Image, H210ImageMut, 1, 2);
define_yuv_image16!( U210Image, U210ImageMut, 1, 2);
define_yuv_image16!( I410Image, I410ImageMut, 1, 1);
define_yuv_image16!( I412Image, I412ImageMut, 1, 1);
define_nv_image16!( P010Image, P010ImageMut, 2, 2);
define_nv_image16!( P012Image, P012ImageMut, 2, 2);
define_nv_image16!( P210Image, P210ImageMut, 1, 2);
define_nv_image16!( P212Image, P212ImageMut, 1, 2);
define_nv_image16!( P410Image, P410ImageMut, 1, 1);
define_packed_image16!( Ar64Image, Ar64ImageMut, 4);
define_packed_image16!( Ab64Image, Ab64ImageMut, 4);