261 lines
5.6 KiB
Rust
261 lines
5.6 KiB
Rust
|
//! Image and color representations.
|
||
|
|
||
|
pub mod pict;
|
||
|
pub mod ppm;
|
||
|
pub mod tga;
|
||
|
|
||
|
/// Creates a RGB8 color from a R5G5B5 format color.
|
||
|
///
|
||
|
/// # Examples
|
||
|
///
|
||
|
/// ```
|
||
|
/// use maraiah::image::{r5g5b5_to_rgb8, Color8};
|
||
|
///
|
||
|
/// assert_eq!(r5g5b5_to_rgb8(0x2345), Color8::new(64, 208, 40));
|
||
|
/// ```
|
||
|
pub fn r5g5b5_to_rgb8(rgb: u16) -> Color8
|
||
|
{
|
||
|
let r = (rgb >> 10) as u8 & 0x1f;
|
||
|
let g = (rgb >> 5) as u8 & 0x1f;
|
||
|
let b = rgb as u8 & 0x1f;
|
||
|
Color8::new(r << 3, g << 3, b << 3)
|
||
|
}
|
||
|
|
||
|
/// Creates a RGB16 color from a R5G5B5 format color.
|
||
|
///
|
||
|
/// # Examples
|
||
|
///
|
||
|
/// ```
|
||
|
/// use maraiah::image::{r5g5b5_to_rgb16, Color16};
|
||
|
///
|
||
|
/// assert_eq!(r5g5b5_to_rgb16(0x2345),
|
||
|
/// Color16::new(0x4000, 0xD000, 0x2800));
|
||
|
/// ```
|
||
|
pub fn r5g5b5_to_rgb16(rgb: u16) -> Color16
|
||
|
{
|
||
|
let r = rgb >> 10 & 0x1f;
|
||
|
let g = rgb >> 5 & 0x1f;
|
||
|
let b = rgb & 0x1f;
|
||
|
Color16::new(r << 11, g << 11, b << 11)
|
||
|
}
|
||
|
|
||
|
/// Creates a RGB16 color from a RGB8 format color.
|
||
|
///
|
||
|
/// # Examples
|
||
|
///
|
||
|
/// ```
|
||
|
/// use maraiah::image;
|
||
|
///
|
||
|
/// let inpl = image::r5g5b5_to_rgb8(0x2345);
|
||
|
/// let inph = image::r5g5b5_to_rgb16(0x2345);
|
||
|
///
|
||
|
/// assert_eq!(inph, image::rgb8_to_rgb16(inpl));
|
||
|
/// ```
|
||
|
pub fn rgb8_to_rgb16(cr: Color8) -> Color16
|
||
|
{
|
||
|
Color16::new(cr.r(), cr.g(), cr.b())
|
||
|
}
|
||
|
|
||
|
/// A generic color matrix image.
|
||
|
pub trait Image
|
||
|
{
|
||
|
/// The type of color this image uses for each pixel.
|
||
|
type Output: Color;
|
||
|
|
||
|
/// Returns the width of the image.
|
||
|
fn w(&self) -> usize;
|
||
|
|
||
|
/// Returns the height of the image.
|
||
|
fn h(&self) -> usize;
|
||
|
|
||
|
/// Returns the color of the pixel at column `x` at row `y`.
|
||
|
///
|
||
|
/// # Panics
|
||
|
///
|
||
|
/// Panics if `x` is greater than the width of the image or `y` is greater
|
||
|
/// than the height of the image.
|
||
|
fn index(&self, x: usize, y: usize) -> &Self::Output;
|
||
|
|
||
|
/// The same as `index`, but will not panic if out of bounds.
|
||
|
fn get(&self, x: usize, y: usize) -> Option<&Self::Output>
|
||
|
{
|
||
|
if x < self.w() && y < self.h() {
|
||
|
Some(self.index(x, y))
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// A generic color matrix image, which may be mutated.
|
||
|
pub trait ImageMut: Image
|
||
|
{
|
||
|
/// Returns the color of the pixel at column `x` at row `y`.
|
||
|
///
|
||
|
/// # Panics
|
||
|
///
|
||
|
/// Panics if `x` is greater than the width of the image or `y` is greater
|
||
|
/// than the height of the image.
|
||
|
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output;
|
||
|
|
||
|
/// The same as `index_mut`, but will not panic if out of bounds.
|
||
|
fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut Self::Output>
|
||
|
{
|
||
|
if x < self.w() && y < self.h() {
|
||
|
Some(self.index_mut(x, y))
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Any color which may be represented as RGBA16.
|
||
|
pub trait Color: Sized + Copy + Clone + Eq + PartialEq
|
||
|
{
|
||
|
/// Returns the red component.
|
||
|
fn r(&self) -> u16;
|
||
|
|
||
|
/// Returns the green component.
|
||
|
fn g(&self) -> u16;
|
||
|
|
||
|
/// Returns the blue component.
|
||
|
fn b(&self) -> u16;
|
||
|
|
||
|
/// Returns the alpha component.
|
||
|
fn a(&self) -> u16;
|
||
|
}
|
||
|
|
||
|
impl Image16
|
||
|
{
|
||
|
/// Creates a new Image16 with no canvas.
|
||
|
pub fn new(w: usize, h: usize) -> Self
|
||
|
{
|
||
|
Self{w, h, cr: Vec::with_capacity(w * h)}
|
||
|
}
|
||
|
|
||
|
/// Creates a new Image16 with an empty canvas.
|
||
|
pub fn new_empty(w: usize, h: usize) -> Self
|
||
|
{
|
||
|
Self{w, h, cr: vec![Color16::new(0, 0, 0); w * h]}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Image for Image16
|
||
|
{
|
||
|
type Output = Color16;
|
||
|
|
||
|
fn w(&self) -> usize {self.w}
|
||
|
fn h(&self) -> usize {self.h}
|
||
|
|
||
|
fn index(&self, x: usize, y: usize) -> &Self::Output
|
||
|
{
|
||
|
&self.cr[x + y * self.w]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ImageMut for Image16
|
||
|
{
|
||
|
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
|
||
|
{
|
||
|
&mut self.cr[x + y * self.w]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Image8
|
||
|
{
|
||
|
/// Creates a new Image8 with no canvas.
|
||
|
pub fn new(w: usize, h: usize) -> Self
|
||
|
{
|
||
|
Self{w, h, cr: Vec::with_capacity(w * h)}
|
||
|
}
|
||
|
|
||
|
/// Creates a new Image8 with an empty canvas.
|
||
|
pub fn new_empty(w: usize, h: usize) -> Self
|
||
|
{
|
||
|
Self{w, h, cr: vec![Color8::new(0, 0, 0); w * h]}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Image for Image8
|
||
|
{
|
||
|
type Output = Color8;
|
||
|
|
||
|
fn w(&self) -> usize {self.w}
|
||
|
fn h(&self) -> usize {self.h}
|
||
|
|
||
|
fn index(&self, x: usize, y: usize) -> &Self::Output
|
||
|
{
|
||
|
&self.cr[x + y * self.w]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl ImageMut for Image8
|
||
|
{
|
||
|
fn index_mut(&mut self, x: usize, y: usize) -> &mut Self::Output
|
||
|
{
|
||
|
&mut self.cr[x + y * self.w]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Color16
|
||
|
{
|
||
|
pub const fn new(r: u16, g: u16, b: u16) -> Self {Self(r, g, b)}
|
||
|
}
|
||
|
|
||
|
impl Color for Color16
|
||
|
{
|
||
|
fn r(&self) -> u16 {self.0}
|
||
|
fn g(&self) -> u16 {self.1}
|
||
|
fn b(&self) -> u16 {self.2}
|
||
|
fn a(&self) -> u16 {u16::max_value()}
|
||
|
}
|
||
|
|
||
|
impl Color8
|
||
|
{
|
||
|
pub const fn new(r: u8, g: u8, b: u8) -> Self {Self(r, g, b)}
|
||
|
}
|
||
|
|
||
|
impl Color for Color8
|
||
|
{
|
||
|
fn r(&self) -> u16 {u16::from(self.0) << 8}
|
||
|
fn g(&self) -> u16 {u16::from(self.1) << 8}
|
||
|
fn b(&self) -> u16 {u16::from(self.2) << 8}
|
||
|
fn a(&self) -> u16 {u16::max_value()}
|
||
|
}
|
||
|
|
||
|
/// An RGB16 color.
|
||
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||
|
pub struct Color16(u16, u16, u16);
|
||
|
|
||
|
/// An RGB8 color.
|
||
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||
|
pub struct Color8(u8, u8, u8);
|
||
|
|
||
|
/// An RGB16 image.
|
||
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||
|
#[derive(Debug, Eq, PartialEq)]
|
||
|
pub struct Image16
|
||
|
{
|
||
|
w: usize,
|
||
|
h: usize,
|
||
|
|
||
|
/// The raw color data for this image.
|
||
|
pub cr: Vec<Color16>,
|
||
|
}
|
||
|
|
||
|
/// An RGB8 image.
|
||
|
#[cfg_attr(feature = "serde_obj", derive(serde::Serialize))]
|
||
|
#[derive(Debug, Eq, PartialEq)]
|
||
|
pub struct Image8
|
||
|
{
|
||
|
w: usize,
|
||
|
h: usize,
|
||
|
|
||
|
/// The raw color data for this image.
|
||
|
pub cr: Vec<Color8>,
|
||
|
}
|
||
|
|
||
|
// EOF
|