full documentation

This commit is contained in:
bendn 2023-09-06 08:31:53 +07:00
parent e2128bb9f2
commit f8ea570db0
No known key found for this signature in database
GPG key ID: 0D9D3A2A3B2A93D6
3 changed files with 30 additions and 8 deletions

View file

@ -1,3 +1,4 @@
//! Manages the affine image transformations.
use crate::Image; use crate::Image;
impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> { impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {

View file

@ -1,3 +1,6 @@
//! # fimg
//!
//! Provides fast image operations, such as rotation, flipping, and overlaying.
#![feature( #![feature(
slice_swap_unchecked, slice_swap_unchecked,
slice_as_chunks, slice_as_chunks,
@ -7,12 +10,13 @@
test test
)] )]
#![warn( #![warn(
clippy::missing_docs_in_private_items,
clippy::multiple_unsafe_ops_per_block, clippy::multiple_unsafe_ops_per_block,
clippy::missing_const_for_fn, clippy::missing_const_for_fn,
clippy::missing_safety_doc, clippy::missing_safety_doc,
unsafe_op_in_unsafe_fn, unsafe_op_in_unsafe_fn,
clippy::dbg_macro, clippy::dbg_macro,
clippy::perf missing_docs
)] )]
#![allow(clippy::zero_prefixed_literal)] #![allow(clippy::zero_prefixed_literal)]
@ -22,6 +26,10 @@ mod affine;
mod overlay; mod overlay;
pub use overlay::{Overlay, OverlayAt}; pub use overlay::{Overlay, OverlayAt};
/// like assert!(), but causes undefined behaviour at runtime when the condition is not met.
///
/// # Safety
/// UB if condition is false.
macro_rules! assert_unchecked { macro_rules! assert_unchecked {
($cond:expr) => {{ ($cond:expr) => {{
if !$cond { if !$cond {
@ -54,6 +62,7 @@ impl Image<&[u8], 3> {
} }
} }
/// calculates a column major index, with unchecked math
#[inline] #[inline]
unsafe fn really_unsafe_index(x: u32, y: u32, w: u32) -> usize { unsafe fn really_unsafe_index(x: u32, y: u32, w: u32) -> usize {
// y * w + x // y * w + x
@ -98,7 +107,7 @@ impl<T, const CHANNELS: usize> Image<T, CHANNELS> {
#[inline] #[inline]
/// create a new image /// create a new image
pub const fn new(width: NonZeroU32, height: NonZeroU32, buffer: T) -> Self { pub const fn new(width: NonZeroU32, height: NonZeroU32, buffer: T) -> Self {
Image { Self {
buffer, buffer,
width, width,
height, height,
@ -229,13 +238,15 @@ impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
/// if width || height == 0 /// if width || height == 0
#[must_use] #[must_use]
pub fn alloc(width: u32, height: u32) -> Self { pub fn alloc(width: u32, height: u32) -> Self {
Image { Self {
width: width.try_into().unwrap(), width: width.try_into().unwrap(),
height: height.try_into().unwrap(), height: height.try_into().unwrap(),
buffer: vec![0; CHANNELS * width as usize * height as usize], buffer: vec![0; CHANNELS * width as usize * height as usize],
} }
} }
} }
/// helper macro for defining the save() method.
macro_rules! save { macro_rules! save {
($channels:literal == $clr:ident ($clrhuman:literal)) => { ($channels:literal == $clr:ident ($clrhuman:literal)) => {
impl Image<Vec<u8>, $channels> { impl Image<Vec<u8>, $channels> {

View file

@ -1,3 +1,4 @@
//! Handles image overlay
use super::{assert_unchecked, really_unsafe_index, Image}; use super::{assert_unchecked, really_unsafe_index, Image};
use std::simd::SimdInt; use std::simd::SimdInt;
use std::simd::SimdPartialOrd; use std::simd::SimdPartialOrd;
@ -22,11 +23,10 @@ pub trait Overlay<W> {
} }
#[inline] #[inline]
/// SIMD accelerated rgba => rgb overlay.
///
/// See [blit](https://en.wikipedia.org/wiki/Bit_blit)
unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) { unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
const LAST4: Simd<u8, 16> = Simd::from_array([
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
]);
let mut srci = 0; let mut srci = 0;
let mut dsti = 0; let mut dsti = 0;
while dsti + 16 <= rgb.len() { while dsti + 16 <= rgb.len() {
@ -38,7 +38,9 @@ unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
threshold, threshold,
[3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 15, 0, 0, 0, 0] [3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 15, 0, 0, 0, 0]
); );
mask &= LAST4; mask &= Simd::from_array([
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
]);
let new_rgb = simd_swizzle!(new, [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0, 0, 0, 0]); let new_rgb = simd_swizzle!(new, [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0, 0, 0, 0]);
let blended = (new_rgb & mask) | (old & !mask); let blended = (new_rgb & mask) | (old & !mask);
@ -106,8 +108,16 @@ impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> {
} }
impl OverlayAt<Image<&[u8], 3>> for Image<&mut [u8], 3> { impl OverlayAt<Image<&[u8], 3>> for Image<&mut [u8], 3> {
/// Overlay a RGB image(with) => self at coordinates x, y.
/// As this is a `RGBxRGB` operation, blending is unnecessary,
/// and this is simply a copy.
///
/// # Safety
///
/// UB if x, y is out of bounds
#[inline] #[inline]
unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self { unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self {
/// helper macro for defining rgb=>rgb overlays. allows unrolling
macro_rules! o3x3 { macro_rules! o3x3 {
($n:expr) => {{ ($n:expr) => {{
for j in 0..($n as usize) { for j in 0..($n as usize) {