pixel 0.1.3

Prototype! Pixel manipulation library (blend and convert colors)
Documentation
use std::f32::NAN;
use super::*;
use super::utils::{ pack_chanel_value, unpack_chanel_value };


/// One of commonly used pixel formats.
/// 32-bit per pixel format use 8 bit for each of red, green, blue and alpha channels.
#[derive(Clone)]
#[derive(Copy)]
#[repr(C)]
pub struct ARGB32([u8; 4]);

impl ARGB32 {
    fn get_alpha_int(&self) -> u8 { self.0[0] }
    fn get_red_int(&self) -> u8 { self.0[1] }
    fn get_green_int(&self) -> u8 { self.0[2] }
    fn get_blue_int(&self) -> u8 { self.0[3] }

    fn get_alpha_float(&self) -> f32 { unpack_chanel_value(self.get_alpha_int() as u64, 255, 1.0) }
    fn get_red_float(&self) -> f32 { unpack_chanel_value(self.get_red_int() as u64, self.get_alpha_int() as usize, 1.0) }
    fn get_green_float(&self) -> f32 { unpack_chanel_value(self.get_green_int() as u64, self.get_alpha_int() as usize, 1.0) }
    fn get_blue_float(&self) -> f32 { unpack_chanel_value(self.get_blue_int() as u64, self.get_alpha_int() as usize, 1.0) }

    fn make(rgba: RGBA) -> ARGB32 {
        let RGBA{ rgb, alpha } = rgba;
        let RGB{ red, green, blue } = rgb;
        let alpha = pack_chanel_value(alpha, 1.0, 255) as u8;
        let red = pack_chanel_value(red, 1.0, alpha as usize) as u8;
        let green = pack_chanel_value(green, 1.0, alpha as usize) as u8;
        let blue = pack_chanel_value(blue, 1.0, alpha as usize) as u8;
        return ARGB32([alpha, red, green, blue]);
    }
}

impl Color for ARGB32 {
    fn to_rgb(&self) -> RGB { RGB { red: self.get_red_float(), green: self.get_green_float(), blue: self.get_blue_float() } }

    fn get_red(&self) -> f32 { self.get_red_float() }
    fn get_green(&self) -> f32 { self.get_green_float() }
    fn get_blue(&self) -> f32 { self.get_blue_float() }
}

impl Pixel for ARGB32 {
    fn get_alpha(&self) -> f32 { self.get_alpha_float() }
}

impl FromColor for ARGB32 {
    fn from<C: Color>(color: &C) -> ARGB32 {
        ARGB32::make(RGBA{rgb: color.to_rgb(), alpha: 1.0})
    }
}

impl FromPixel for ARGB32 {
    fn loosing_alpha() -> bool { false }
    fn from<P: Pixel>(pixel: &P) -> ARGB32 {
        ARGB32::make(pixel.to_rgba())
    }
}

/// One of commonly used pixel formats.
/// 32-bit per pixel format use 8 bit for each of red, green and blue.
#[derive(Clone)]
#[derive(Copy)]
#[repr(C)]
pub struct RGB24([u8; 3]);

impl RGB24 {
    fn get_red_int(&self) -> u8 { self.0[1] }
    fn get_green_int(&self) -> u8 { self.0[2] }
    fn get_blue_int(&self) -> u8 { self.0[3] }

    fn get_red_float(&self) -> f32 { unpack_chanel_value(self.get_red_int() as u64, 255, 1.0) }
    fn get_green_float(&self) -> f32 { unpack_chanel_value(self.get_green_int() as u64, 255, 1.0) }
    fn get_blue_float(&self) -> f32 { unpack_chanel_value(self.get_blue_int() as u64, 255, 1.0) }

    fn make(rgb: RGB) -> RGB24 {
        let RGB{ red, green, blue } = rgb;
        let red = pack_chanel_value(red, 1.0, 255) as u8;
        let green = pack_chanel_value(green, 1.0, 255) as u8;
        let blue = pack_chanel_value(blue, 1.0, 255) as u8;
        return RGB24([red, green, blue]);
    }
}

impl Color for RGB24 {
    fn to_rgb(&self) -> RGB { RGB { red: self.get_red_float(), green: self.get_green_float(), blue: self.get_blue_float() } }
}

impl Pixel for RGB24 {}

impl FromColor for RGB24 {
    fn from<C: Color>(color: &C) -> RGB24 {
        RGB24::make(color.to_rgb())
    }
}

impl FromPixel for RGB24 {
    fn from<P: Pixel>(pixel: &P) -> RGB24 {
        RGB24::make(pixel.to_rgb())
    }
}


/// One of not so commonly used pixel format.
#[derive(Clone)]
#[derive(Copy)]
#[repr(C)]
pub struct RGB555(u16);

impl RGB555 {
    fn get_red_int(&self) -> u8 { ((self.0 >> 10) & 31) as u8 }     // 5 bits after first one
    fn get_green_int(&self) -> u8 { ((self.0 >> 5) & 31) as u8 }    // next 5 bits
    fn get_blue_int(&self) -> u8 { (self.0 & 31) as u8 }            // last 5 bits

    fn get_red_float(&self) -> f32 { unpack_chanel_value(self.get_red_int() as u64, 31 as usize, 1.0) }
    fn get_green_float(&self) -> f32 { unpack_chanel_value(self.get_green_int() as u64, 31 as usize, 1.0) }
    fn get_blue_float(&self) -> f32 { unpack_chanel_value(self.get_blue_int() as u64, 31, 1.0) }

    fn make(rgb: RGB) -> RGB555 {
        let RGB{ red, green, blue } = rgb;
        let red = pack_chanel_value(red, 1.0, 31) as u16;
        let green = pack_chanel_value(green, 1.0, 31) as u16;
        let blue = pack_chanel_value(blue, 1.0, 31) as u16;
        return RGB555(red << 10|green << 5|blue);
    }
}

impl Color for RGB555 {
    fn to_rgb(&self) -> RGB { RGB { red: self.get_red_float(), green: self.get_green_float(), blue: self.get_blue_float() } }
}

impl Pixel for RGB555 {}

impl FromColor for RGB555 {
    fn from<C: Color>(color: &C) -> RGB555 {
        RGB555::make(color.to_rgb())
    }
}

impl FromPixel for RGB555 {
    fn from<P: Pixel>(pixel: &P) -> RGB555 {
        RGB555::make(pixel.to_rgb())
    }
}


/// This format is similar to `RGB555` but use most significant pixel for transparrency data.
/// Use twice as less memory than `ARGB32`.
#[derive(Clone)]
#[derive(Copy)]
#[repr(C)]
pub struct ARGB1555(u16);

impl ARGB1555 {
    fn get_alpha_int(&self) -> u8 { (self.0 >> 15) as u8 }
    fn get_red_int(&self) -> u8 { ((self.0 >> 10) & 31) as u8 }     // 5 bits after first one
    fn get_green_int(&self) -> u8 { ((self.0 >> 5) & 31) as u8 }    // next 5 bits
    fn get_blue_int(&self) -> u8 { (self.0 & 31) as u8 }            // last 5 bits

    fn get_alpha_float(&self) -> f32 { if self.get_alpha_int() == 0 { 0.0 } else { 1.0 } }
    fn get_red_float(&self) -> f32 { unpack_chanel_value(self.get_red_int() as u64, 31 as usize, 1.0) }
    fn get_green_float(&self) -> f32 { unpack_chanel_value(self.get_green_int() as u64, 31 as usize, 1.0) }
    fn get_blue_float(&self) -> f32 { unpack_chanel_value(self.get_blue_int() as u64, 31, 1.0) }

    fn make(rgba: RGBA) -> ARGB1555 {
        let RGBA{ rgb, alpha } = rgba;
        let RGB{ red, green, blue } = rgb;
        let alpha = pack_chanel_value(alpha, 1.0, 1) as u16;
        let red = pack_chanel_value(red, 1.0, 31) as u16;
        let green = pack_chanel_value(green, 1.0, 31) as u16;
        let blue = pack_chanel_value(blue, 1.0, 31) as u16;
        return ARGB1555(alpha<<15|red << 10|green << 5|blue);
    }
}

impl Color for ARGB1555 {
    fn to_rgb(&self) -> RGB { RGB { red: self.get_red_float(), green: self.get_green_float(), blue: self.get_blue_float() } }
}

impl Pixel for ARGB1555 {
    fn get_alpha(&self) -> f32 { self.get_alpha_float() }
}

impl FromColor for ARGB1555 {
    fn from<C: Color>(color: &C) -> ARGB1555 {
        ARGB1555::make(RGBA{rgb: color.to_rgb(), alpha: 1.0})
    }
}

impl FromPixel for ARGB1555 {
    fn loosing_alpha() -> bool { false }
    fn from<P: Pixel>(pixel: &P) -> ARGB1555 {
        ARGB1555::make(pixel.to_rgba())
    }
}

/// This format is similar to `RGB555` but use one more for green channel.
#[derive(Clone)]
#[derive(Copy)]
#[repr(C)]
pub struct RGB565(u16);

impl RGB565 {
    fn get_red_int(&self) -> u8 { (self.0 >> 11) as u8 }            // first 5 bits
    fn get_green_int(&self) -> u8 { ((self.0 >> 5) & 63) as u8 }    // next 6 bits
    fn get_blue_int(&self) -> u8 { (self.0 & 31) as u8 }            // last 5 bits

    fn get_red_float(&self) -> f32 { unpack_chanel_value(self.get_red_int() as u64, 31 as usize, 1.0) }
    fn get_green_float(&self) -> f32 { unpack_chanel_value(self.get_green_int() as u64, 63 as usize, 1.0) }
    fn get_blue_float(&self) -> f32 { unpack_chanel_value(self.get_blue_int() as u64, 31, 1.0) }

    fn make(rgb: RGB) -> RGB565 {
        let RGB{ red, green, blue } = rgb;
        let red = pack_chanel_value(red, 1.0, 31) as u16;
        let green = pack_chanel_value(green, 1.0, 63) as u16;
        let blue = pack_chanel_value(blue, 1.0, 31) as u16;
        return RGB565(red << 11|green << 5|blue);
    }
}

impl Color for RGB565 {
    fn to_rgb(&self) -> RGB { RGB { red: self.get_red_float(), green: self.get_green_float(), blue: self.get_blue_float() } }
}

impl Pixel for RGB565 {}

impl FromColor for RGB565 {
    fn from<C: Color>(color: &C) -> RGB565 {
        RGB565::make(color.to_rgb())
    }
}

impl FromPixel for RGB565 {
    fn from<P: Pixel>(pixel: &P) -> RGB565 {
        RGB565::make(pixel.to_rgb())
    }
}


/// Black-white with transparrency.
/// 8-bit per pixel
#[derive(Clone)]
#[derive(Copy)]
#[repr(C)]
pub struct A8(u8);

impl Color for A8 {
    fn to_rgb(&self) -> RGB { RGB { red: 1.0, green: 1.0, blue: 1.0 } }
    fn to_hsv(&self) -> HSV { HSV { hue: NAN, saturation: 0.0, value: 1.0 } }
    fn to_hsl(&self) -> HSL { HSL { hue: NAN, saturation: 0.0, lightness: 1.0 } }
}

impl Pixel for A8 {
    fn get_alpha(&self) -> f32 { unpack_chanel_value(self.0 as u64, 255, 1.0) }
}

impl FromColor for A8 {
    fn loosing_color() -> bool { true }
    fn from<C: Color>(_: &C) -> A8 { A8(255) }
}

impl FromPixel for A8 {
    fn from<P: Pixel>(pixel: &P) -> A8 { A8(pack_chanel_value(pixel.get_alpha(), 1.0, 255) as u8) }
}