pub mod ase;
pub mod gif;
pub mod heic;
pub mod svg;
use fir;
use image;
use std::{mem, num::NonZeroU32};
pub struct TransRgb {}
pub struct TransRgba {}
#[derive(Debug, Clone, Copy)]
pub struct Size<T> {
pub width: T,
pub height: T,
}
#[derive(Debug, Clone, Copy)]
pub struct MetaSize<T> {
pub screen: Size<T>,
pub window: Size<T>,
pub image: Size<T>,
pub fix: Size<T>,
}
pub trait TMetaSize {
type T;
fn new(sw: Self::T, sh: Self::T, ww: Self::T, wh: Self::T, iw: Self::T, ih: Self::T) -> Self;
fn resize(&mut self);
}
impl<T> Size<T> {
pub fn new(width: T, height: T) -> Self {
Size { width, height }
}
pub fn len(&self) -> usize
where
T: TryInto<usize> + Copy,
T::Error: std::fmt::Debug,
{
self.width.try_into().unwrap() * self.height.try_into().unwrap()
}
}
impl TransRgba {
#[inline(always)]
pub fn rgba_as_argb_u32(r: &u8, g: &u8, b: &u8, a: &u8) -> u32 {
u32::from_be_bytes([*a, *r, *g, *b])
}
#[inline(always)]
pub fn rgba_as_u32(r: &u8, g: &u8, b: &u8, a: &u8) -> u32 {
u32::from_be_bytes([*r, *g, *b, *a])
}
#[inline(always)]
pub fn rgba_from_u32(rgba: &u32) -> [u8; 4] {
rgba.to_be().to_ne_bytes()
}
}
impl TransRgb {
#[inline(always)]
pub fn rgb_to_u32(rgb: &[u8; 3]) -> u32 {
let r = (rgb[0] as u32) << 16;
let g = (rgb[1] as u32) << 8;
let b = rgb[2] as u32;
r + g + b
}
#[inline(always)]
pub fn rgb_from_u32(rgb: u32) -> [u8; 3] {
let r = (rgb >> 16) & 0x0ff;
let g = (rgb >> 8) & 0x0ff;
let b = rgb & 0x0ff;
[r as u8, g as u8, b as u8]
}
#[inline(always)]
pub fn rgb_to_gray(rgb: &[u8; 3]) -> u8 {
let r = rgb[0] as u32;
let g = rgb[1] as u32;
let b = rgb[2] as u32;
((r * 38 + g * 75 + b * 15) >> 7) as u8
}
#[inline(always)]
pub fn u32_to_gray(rgb: u32) -> u8 {
let rgb = Self::rgb_from_u32(rgb);
Self::rgb_to_gray(&rgb)
}
}
impl TMetaSize for MetaSize<u32> {
type T = u32;
fn new(sw: Self::T, sh: Self::T, ww: Self::T, wh: Self::T, iw: Self::T, ih: Self::T) -> Self {
MetaSize {
screen: Size::<u32>::new(sw, sh),
window: Size::<u32>::new(ww, wh),
image: Size::<u32>::new(iw, ih),
fix: Size::<u32>::new(0, 0),
}
}
fn resize(&mut self) {
let q = self.image.width as f32 / self.image.height as f32;
let w = self.window.width as f32;
let h = w / q;
self.fix.width = (w as Self::T / 2) * 2;
self.fix.height = (h as Self::T / 2) * 2;
}
}
pub fn resize_rgba8(
bytes: &mut Vec<u8>,
from: &Size<u32>,
to: &Size<u32>,
filter: &fir::FilterType,
) -> anyhow::Result<()> {
let mut src_image = fir::Image::from_vec_u8(
NonZeroU32::new(from.width).unwrap(),
NonZeroU32::new(from.height).unwrap(),
bytes.clone(),
fir::PixelType::U8x4,
)?;
let dst_width = NonZeroU32::new(to.width).unwrap();
let dst_height = NonZeroU32::new(to.height).unwrap();
let mut dst_image = fir::Image::new(dst_width, dst_height, src_image.pixel_type());
let mut dst_view = dst_image.view_mut();
let mut resizer = fir::Resizer::new(fir::ResizeAlg::Convolution(*filter));
unsafe {
#[cfg(feature = "sse4_1")]
{
resizer.set_cpu_extensions(fir::CpuExtensions::Sse4_1);
}
#[cfg(feature = "avx2")]
{
resizer.set_cpu_extensions(fir::CpuExtensions::Avx2);
}
}
resizer.resize(&src_image.view(), &mut dst_view)?;
let alpha_mul_div = fir::MulDiv::default();
alpha_mul_div.multiply_alpha_inplace(&mut src_image.view_mut())?;
alpha_mul_div.divide_alpha_inplace(&mut dst_view)?;
*bytes = mem::take(&mut dst_image.buffer().to_owned());
Ok(())
}
pub fn center_img<T: Copy>(bg: &mut Vec<T>, fg: &[T], bgw: usize, fgw: usize, h: usize) {
let x_offset = ((bgw - fgw) / 2);
for y in 0..h {
let fp = fgw * y;
let bp = bgw * y + x_offset;
for x in 0..fgw {
bg[bp + x] = fg[fp + x];
}
}
}
pub fn argb_u32(buffer: &mut Vec<u32>, bytes: &[u8]) {
*buffer = vec![0; bytes.len() / 4];
for (idx, f) in (0..bytes.len()).step_by(4).enumerate() {
buffer[idx] =
TransRgba::rgba_as_argb_u32(&bytes[f], &bytes[f + 1], &bytes[f + 2], &bytes[f + 3]);
}
}
pub fn rgba_u32(buffer: &mut Vec<u32>, bytes: &[u8]) {
*buffer = vec![0; bytes.len() / 4];
for (idx, f) in (0..bytes.len()).step_by(4).enumerate() {
buffer[idx] =
TransRgba::rgba_as_u32(&bytes[f], &bytes[f + 1], &bytes[f + 2], &bytes[f + 3]);
}
}
pub fn yuv420_u32() {}
mod test {
pub use crate::img::*;
#[test]
fn _rgba_as_argb_u32() {}
#[test]
fn _rgba_as_u32() {
assert_eq!(16909060, TransRgba::rgba_as_u32(&1, &2, &3, &4));
}
#[test]
fn _rgba_from_u32() {
assert_eq!([1_u8, 2, 3, 4], TransRgba::rgba_from_u32(&16909060));
}
}