mod encoder;
mod prepare;
pub use encoder::ImageEncoder;
pub use prepare::{PreparedImage, VisionArtifacts};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[non_exhaustive]
pub enum VisionBudget {
Tokens70,
Tokens140,
Tokens280,
}
impl VisionBudget {
pub const ALL: [Self; 3] = [Self::Tokens70, Self::Tokens140, Self::Tokens280];
#[inline]
pub const fn as_str(&self) -> &'static str {
match self {
Self::Tokens70 => "vision_70",
Self::Tokens140 => "vision_140",
Self::Tokens280 => "vision_280",
}
}
#[inline]
pub const fn tokens(&self) -> usize {
match self {
Self::Tokens70 => 70,
Self::Tokens140 => 140,
Self::Tokens280 => 280,
}
}
#[inline]
pub const fn patches(&self) -> usize {
9 * self.tokens()
}
#[inline]
pub const fn from_tokens(tokens: usize) -> Option<Self> {
match tokens {
70 => Some(Self::Tokens70),
140 => Some(Self::Tokens140),
280 => Some(Self::Tokens280),
_ => None,
}
}
#[inline]
const fn bit(self) -> u8 {
1 << self as u8
}
}
impl core::fmt::Display for VisionBudget {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.tokens())
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for VisionBudget {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_u16(self.tokens() as u16)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for VisionBudget {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let tokens = <u64 as serde::Deserialize>::deserialize(deserializer)?;
usize::try_from(tokens)
.ok()
.and_then(Self::from_tokens)
.ok_or_else(|| {
serde::de::Error::custom(format_args!(
"unknown vision budget {tokens}: expected one of 70, 140, 280"
))
})
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct VisionBudgets(u8);
impl VisionBudgets {
#[inline]
pub const fn empty() -> Self {
Self(0)
}
#[inline]
pub const fn only(budget: VisionBudget) -> Self {
Self(budget.bit())
}
#[inline]
pub const fn all() -> Self {
Self(0b111)
}
#[must_use]
#[inline]
pub const fn with(self, budget: VisionBudget) -> Self {
Self(self.0 | budget.bit())
}
#[inline]
pub const fn contains(&self, budget: VisionBudget) -> bool {
self.0 & budget.bit() != 0
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0 == 0
}
#[inline]
pub const fn len(&self) -> usize {
self.0.count_ones() as usize
}
pub fn iter(&self) -> impl Iterator<Item = VisionBudget> + '_ {
VisionBudget::ALL
.into_iter()
.filter(move |budget| self.contains(*budget))
}
}
impl FromIterator<VisionBudget> for VisionBudgets {
fn from_iter<I: IntoIterator<Item = VisionBudget>>(iter: I) -> Self {
iter.into_iter().fold(Self::empty(), Self::with)
}
}
impl core::fmt::Debug for VisionBudgets {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
impl core::fmt::Display for VisionBudgets {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("[")?;
for (index, budget) in self.iter().enumerate() {
if index > 0 {
f.write_str(",")?;
}
write!(f, "{budget}")?;
}
f.write_str("]")
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for VisionBudgets {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for budget in self.iter() {
seq.serialize_element(&budget)?;
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for VisionBudgets {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Members;
impl<'de> serde::de::Visitor<'de> for Members {
type Value = VisionBudgets;
fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("a list of distinct vision budgets")
}
fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<Self::Value, A::Error> {
let mut set = VisionBudgets::empty();
while let Some(budget) = seq.next_element::<VisionBudget>()? {
if set.contains(budget) {
return Err(serde::de::Error::custom(format_args!(
"the vision budget {budget} is listed twice"
)));
}
set = set.with(budget);
}
Ok(set)
}
}
deserializer.deserialize_seq(Members)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, derive_more::Display)]
#[display("{}", self.as_str())]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
#[non_exhaustive]
pub enum ResizeRoad {
HfBicubic,
}
impl ResizeRoad {
#[inline]
pub const fn as_str(&self) -> &'static str {
match self {
Self::HfBicubic => "hf_bicubic",
}
}
}
#[cfg(test)]
mod tests;