Maraiah/src/durandal/image.rs

208 lines
3.3 KiB
Rust

//! Image and color representations.
use crate::durandal::traits::*;
use std::io;
/// Creates a RGB8 color from a R5G5B5 format color.
pub fn r5g5b5_to_rgb8(rgb: u16) -> Color8
{
let r = rgb >> 10 & 0x1f;
let g = rgb >> 5 & 0x1f;
let b = rgb & 0x1f;
Color8::new((r << 3 | r >> 2) as u8,
(g << 3 | g >> 2) as u8,
(b << 3 | b >> 2) as u8)
}
/// Creates a RGB16 color from a R5G5B5 format color.
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 << 3 | r >> 2, g << 11, b << 11)
}
/// Creates a RGB16 color from a RGB8 format color.
pub fn rgb8_to_rgb16(r: u8, g: u8, b: u8) -> Color16
{
Color16::new(r as (u16) << 8, g as (u16) << 8, b as (u16) << 8)
}
/// Writes a PPM file from an image.
pub fn write_ppm<T>(out: &mut impl io::Write, im: &T) -> io::Result<()>
where T: Image
{
write!(out, "P3\n{} {}\n{}\n", im.w(), im.h(), T::Output::MAX)?;
for y in 0..im.h() {
for x in 0..im.w() {
let cr = im.cr_at(x, y);
write!(out, "{} {} {} ", cr.r(), cr.g(), cr.b())?;
}
}
Ok(())
}
pub trait Image
{
type Output: Color;
fn w(&self) -> usize;
fn h(&self) -> usize;
fn cr_at(&self, x: usize, y: usize) -> &Self::Output;
}
pub trait Color
{
type Output: PrimInt;
const MAX: usize;
fn r(&self) -> Self::Output;
fn g(&self) -> Self::Output;
fn b(&self) -> Self::Output;
}
impl Image16
{
/// Creates a new Image16.
pub fn new(w: usize, h: usize) -> Image16
{
Image16{w, h, cr: Vec::with_capacity(w * h)}
}
}
impl Image for Image16
{
type Output = Color16;
fn w(&self) -> usize
{
self.w
}
fn h(&self) -> usize
{
self.h
}
fn cr_at(&self, x: usize, y: usize) -> &Color16
{
&self.cr[x + y * self.w]
}
}
impl Image8
{
/// Creates a new Image8.
pub fn new(w: usize, h: usize) -> Image8
{
Image8{w, h, cr: Vec::with_capacity(w * h)}
}
}
impl Image for Image8
{
type Output = Color8;
fn w(&self) -> usize
{
self.w
}
fn h(&self) -> usize
{
self.h
}
fn cr_at(&self, x: usize, y: usize) -> &Color8
{
&self.cr[x + y * self.w]
}
}
impl Color16
{
pub const fn new(r: u16, g: u16, b: u16) -> Color16
{
Color16(r, g, b)
}
}
impl Color for Color16
{
type Output = u16;
const MAX: usize = u16::max_value() as usize;
fn r(&self) -> u16
{
self.0
}
fn g(&self) -> u16
{
self.1
}
fn b(&self) -> u16
{
self.2
}
}
impl Color8
{
pub const fn new(r: u8, g: u8, b: u8) -> Color8
{
Color8(r, g, b)
}
}
impl Color for Color8
{
type Output = u8;
const MAX: usize = u8::max_value() as usize;
fn r(&self) -> u8
{
self.0
}
fn g(&self) -> u8
{
self.1
}
fn b(&self) -> u8
{
self.2
}
}
/// A RGB16 color.
#[derive(Clone, Debug, PartialEq)]
pub struct Color16(u16, u16, u16);
/// A RGB8 color.
#[derive(Clone, Debug, PartialEq)]
pub struct Color8(u8, u8, u8);
/// RGB16 image.
pub struct Image16
{
w: usize,
h: usize,
pub cr: Vec<Color16>,
}
/// RGB16 image.
pub struct Image8
{
w: usize,
h: usize,
pub cr: Vec<Color8>,
}
// EOF