#![doc(
html_logo_url = "https://raw.githubusercontent.com/AldaronLau/png_pong/master/res/icon.png",
html_favicon_url = "https://raw.githubusercontent.com/AldaronLau/png_pong/master/res/icon.png",
html_root_url = "https://docs.rs/png_pong"
)]
#![forbid(unsafe_code)]
#![warn(
anonymous_parameters,
missing_copy_implementations,
nonstandard_style,
rust_2018_idioms,
single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
unreachable_pub,
unused_extern_crates,
unused_qualifications,
variant_size_differences
)]
mod chunk;
mod consts;
mod encode;
mod encoder;
mod zlib;
#[derive(Debug, Clone, Copy)]
pub struct Rgb {
pub r: u8,
pub g: u8,
pub b: u8,
}
#[derive(Debug, Clone, Copy)]
pub struct Rgba {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl Rgba {
pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r, g, b, a }
}
pub fn blend(&self, secondary: Rgba, primary_ratio: f64) -> Rgba {
let ratio = ((primary_ratio * 1024.0) as u32).min(1024);
let inv_ratio = 1024 - ratio;
let blended = |a: u8, b: u8| {
((a as u32 * ratio + b as u32 * inv_ratio) >> 10).min(255) as u8
};
Rgba {
r: blended(self.r, secondary.r),
g: blended(self.g, secondary.g),
b: blended(self.b, secondary.b),
a: blended(self.a, secondary.a),
}
}
pub const fn from_be(rgba: u32) -> Self {
let rgba = rgba.to_be_bytes();
Self {
r: rgba[0],
g: rgba[1],
b: rgba[2],
a: rgba[3],
}
}
}
impl From<[u8; 4]> for Rgba {
fn from(rgba: [u8; 4]) -> Self {
Self {
r: rgba[0],
g: rgba[1],
b: rgba[2],
a: rgba[3],
}
}
}
impl From<u32> for Rgba {
fn from(rgba: u32) -> Self {
rgba.to_be_bytes().into()
}
}
use encode::Error;
pub use encoder::Encoder;
pub struct IndexedImage<'a> {
pub pixels: &'a [u8],
pub width: u32,
pub height: u32,
pub palette: &'a [Rgba],
}
impl IndexedImage<'_> {
#[inline(never)]
pub fn encode(&self, compression: u8) -> Result<Vec<u8>, Error> {
let mut encoder = Encoder::new()
.compression_level(compression)
.into_step_enc();
encoder.encode(self.pixels, self.width, self.height, self.palette)?;
Ok(encoder.encoder.encode.writer)
}
}