#[cfg(feature = "std")]
mod from;
use paste::paste;
macro_rules! from_pixel {
($t:ident) => {
paste! {
fn from_l8(pixel: &u8) -> Self {
pixel.[<to_ $t>]()
}
fn from_la8(pixel: &[u8; 2]) -> Self {
pixel.[<to_ $t>]()
}
fn from_l32(pixel: &f32) -> Self {
pixel.[<to_ $t>]()
}
fn from_la32(pixel: &[f32; 2]) -> Self {
pixel.[<to_ $t>]()
}
fn from_rgb8(pixel: &[u8; 3]) -> Self {
pixel.[<to_ $t>]()
}
fn from_rgba8(pixel: &[u8; 4]) -> Self {
pixel.[<to_ $t>]()
}
fn from_rgba32(pixel: &[f32; 4]) -> Self {
pixel.[<to_ $t>]()
}
#[cfg(feature = "softbuffer")]
fn from_zrgb(pixel: &crate::sb::Zrgb) -> Self {
pixel.[<to_ $t>]()
}
}
};
}
pub trait PixelConverter {
fn to_l8(&self) -> u8;
fn to_la8(&self) -> [u8; 2];
fn to_l32(&self) -> f32;
fn to_la32(&self) -> [f32; 2];
fn to_rgb8(&self) -> [u8; 3];
fn to_rgba8(&self) -> [u8; 4];
fn to_rgba32(&self) -> [f32; 4];
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb;
fn from_l8(pixel: &u8) -> Self;
fn from_la8(pixel: &[u8; 2]) -> Self;
fn from_l32(pixel: &f32) -> Self;
fn from_la32(pixel: &[f32; 2]) -> Self;
fn from_rgb8(pixel: &[u8; 3]) -> Self;
fn from_rgba8(pixel: &[u8; 4]) -> Self;
fn from_rgba32(pixel: &[f32; 4]) -> Self;
#[cfg(feature = "softbuffer")]
fn from_zrgb(pixel: &crate::sb::Zrgb) -> Self;
}
impl PixelConverter for u8 {
fn to_l8(&self) -> u8 {
*self
}
fn to_la8(&self) -> [u8; 2] {
[*self, 255]
}
fn to_l32(&self) -> f32 {
u8_to_f32(*self)
}
fn to_la32(&self) -> [f32; 2] {
[self.to_l32(), 1.]
}
fn to_rgb8(&self) -> [u8; 3] {
[*self; 3]
}
fn to_rgba8(&self) -> [u8; 4] {
[*self; 4]
}
fn to_rgba32(&self) -> [f32; 4] {
let p = self.to_l32();
[p, p, p, 1.]
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
let p = *self;
crate::sb::Zrgb::new(p, p, p)
}
from_pixel!(l8);
}
impl PixelConverter for f32 {
fn to_l8(&self) -> u8 {
f32_to_u8(*self)
}
fn to_la8(&self) -> [u8; 2] {
[self.to_l8(), 255]
}
fn to_l32(&self) -> f32 {
*self
}
fn to_la32(&self) -> [f32; 2] {
[*self, 1.]
}
fn to_rgb8(&self) -> [u8; 3] {
[self.to_l8(); 3]
}
fn to_rgba8(&self) -> [u8; 4] {
let p = self.to_l8();
[p, p, p, 255]
}
fn to_rgba32(&self) -> [f32; 4] {
let p = *self;
[p, p, p, 1.]
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
let p = f32_to_u8(*self);
crate::sb::Zrgb::new(p, p, p)
}
from_pixel!(l32);
}
impl PixelConverter for [u8; 2] {
fn to_l8(&self) -> u8 {
self[0]
}
fn to_la8(&self) -> [u8; 2] {
*self
}
fn to_l32(&self) -> f32 {
u8_to_f32(self[0])
}
fn to_la32(&self) -> [f32; 2] {
[u8_to_f32(self[0]), u8_to_f32(self[1])]
}
fn to_rgb8(&self) -> [u8; 3] {
[self[0]; 3]
}
fn to_rgba8(&self) -> [u8; 4] {
[self[0]; 4]
}
fn to_rgba32(&self) -> [f32; 4] {
let p = u8_to_f32(self[0]);
let a = u8_to_f32(self[1]);
[p, p, p, a]
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
let p = self[0];
crate::sb::Zrgb::new(p, p, p)
}
from_pixel!(la8);
}
impl PixelConverter for [f32; 2] {
fn to_l8(&self) -> u8 {
f32_to_u8(self[0])
}
fn to_la8(&self) -> [u8; 2] {
[f32_to_u8(self[0]), f32_to_u8(self[1])]
}
fn to_l32(&self) -> f32 {
self[0]
}
fn to_la32(&self) -> [f32; 2] {
*self
}
fn to_rgb8(&self) -> [u8; 3] {
[f32_to_u8(self[0]); 3]
}
fn to_rgba8(&self) -> [u8; 4] {
let p = f32_to_u8(self[0]);
[p, p, p, f32_to_u8(self[1])]
}
fn to_rgba32(&self) -> [f32; 4] {
let p = self[0];
[p, p, p, self[1]]
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
let p = f32_to_u8(self[0]);
crate::sb::Zrgb::new(p, p, p)
}
from_pixel!(la32);
}
impl PixelConverter for [u8; 3] {
fn to_l8(&self) -> u8 {
f32_to_u8(self.to_l32())
}
fn to_la8(&self) -> [u8; 2] {
[self.to_l8(), 255]
}
fn to_l32(&self) -> f32 {
grayscale(self[0], self[1], self[2])
}
fn to_la32(&self) -> [f32; 2] {
[self.to_l32(), 1.]
}
fn to_rgb8(&self) -> [u8; 3] {
*self
}
fn to_rgba8(&self) -> [u8; 4] {
[self[0], self[1], self[2], 255]
}
fn to_rgba32(&self) -> [f32; 4] {
[
u8_to_f32(self[0]),
u8_to_f32(self[1]),
u8_to_f32(self[2]),
1.,
]
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
crate::sb::Zrgb::new(self[0], self[1], self[2])
}
from_pixel!(rgb8);
}
impl PixelConverter for [u8; 4] {
fn to_l8(&self) -> u8 {
f32_to_u8(self.to_l32())
}
fn to_la8(&self) -> [u8; 2] {
[self.to_l8(), self[3]]
}
fn to_l32(&self) -> f32 {
grayscale(self[0], self[1], self[2])
}
fn to_la32(&self) -> [f32; 2] {
[self.to_l32(), u8_to_f32(self[3])]
}
fn to_rgb8(&self) -> [u8; 3] {
[self[0], self[1], self[2]]
}
fn to_rgba8(&self) -> [u8; 4] {
*self
}
fn to_rgba32(&self) -> [f32; 4] {
[
u8_to_f32(self[0]),
u8_to_f32(self[1]),
u8_to_f32(self[2]),
u8_to_f32(self[3]),
]
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
crate::sb::Zrgb::new(self[0], self[1], self[2])
}
from_pixel!(rgba8);
}
impl PixelConverter for [f32; 4] {
fn to_l8(&self) -> u8 {
self.to_l32() as u8
}
fn to_la8(&self) -> [u8; 2] {
[self.to_l32() as u8, (self[3] * 265.) as u8]
}
fn to_l32(&self) -> f32 {
const GRAYSCALE: f32 = 88.333_336;
(self[0] + self[1] + self[2]) * GRAYSCALE
}
fn to_la32(&self) -> [f32; 2] {
[(self[0] + self[1] + self[2]) / 3., self[3]]
}
fn to_rgb8(&self) -> [u8; 3] {
let r = (self[0] * 265.) as u8;
let g = (self[1] * 265.) as u8;
let b = (self[2] * 265.) as u8;
[r, g, b]
}
fn to_rgba8(&self) -> [u8; 4] {
let r = (self[0] * 265.) as u8;
let g = (self[1] * 265.) as u8;
let b = (self[2] * 265.) as u8;
let a = (self[3] * 265.) as u8;
[r, g, b, a]
}
fn to_rgba32(&self) -> [f32; 4] {
*self
}
#[cfg(feature = "softbuffer")]
fn to_zrgb(&self) -> crate::sb::Zrgb {
let r = (self[0] * 265.) as u8;
let g = (self[1] * 265.) as u8;
let b = (self[2] * 265.) as u8;
crate::sb::Zrgb::new(r, g, b)
}
from_pixel!(rgba32);
}
pub(crate) const fn f32_to_u8(pixel: f32) -> u8 {
(pixel * 256.) as u8
}
pub(crate) const fn u8_to_f32(pixel: u8) -> f32 {
const U8_TO_F32: [f32; 256] = [
0.0, 0.0039216, 0.0078431, 0.0117647, 0.0156863, 0.0196078, 0.0235294, 0.027451, 0.0313725,
0.0352941, 0.0392157, 0.0431373, 0.0470588, 0.0509804, 0.054902, 0.0588235, 0.0627451,
0.0666667, 0.0705882, 0.0745098, 0.0784314, 0.0823529, 0.0862745, 0.0901961, 0.0941176,
0.0980392, 0.1019608, 0.1058824, 0.1098039, 0.1137255, 0.1176471, 0.1215686, 0.1254902,
0.1294118, 0.1333333, 0.1372549, 0.1411765, 0.145098, 0.1490196, 0.1529412, 0.1568627,
0.1607843, 0.1647059, 0.1686275, 0.172549, 0.1764706, 0.1803922, 0.1843137, 0.1882353,
0.1921569, 0.1960784, 0.2, 0.2039216, 0.2078431, 0.2117647, 0.2156863, 0.2196078,
0.2235294, 0.227451, 0.2313725, 0.2352941, 0.2392157, 0.2431373, 0.2470588, 0.2509804,
0.254902, 0.2588235, 0.2627451, 0.2666667, 0.2705882, 0.2745098, 0.2784314, 0.2823529,
0.2862745, 0.2901961, 0.2941176, 0.2980392, 0.3019608, 0.3058824, 0.3098039, 0.3137255,
0.3176471, 0.3215686, 0.3254902, 0.3294118, 0.3333333, 0.3372549, 0.3411765, 0.345098,
0.3490196, 0.3529412, 0.3568627, 0.3607843, 0.3647059, 0.3686275, 0.372549, 0.3764706,
0.3803922, 0.3843137, 0.3882353, 0.3921569, 0.3960784, 0.4, 0.4039216, 0.4078431,
0.4117647, 0.4156863, 0.4196078, 0.4235294, 0.427451, 0.4313725, 0.4352941, 0.4392157,
0.4431373, 0.4470588, 0.4509804, 0.454902, 0.4588235, 0.4627451, 0.4666667, 0.4705882,
0.4745098, 0.4784314, 0.4823529, 0.4862745, 0.4901961, 0.4941176, 0.4980392, 0.5019608,
0.5058824, 0.5098039, 0.5137255, 0.5176471, 0.5215686, 0.5254902, 0.5294118, 0.5333333,
0.5372549, 0.5411765, 0.545098, 0.5490196, 0.5529412, 0.5568627, 0.5607843, 0.5647059,
0.5686275, 0.572549, 0.5764706, 0.5803922, 0.5843137, 0.5882353, 0.5921569, 0.5960784, 0.6,
0.6039216, 0.6078431, 0.6117647, 0.6156863, 0.6196078, 0.6235294, 0.627451, 0.6313725,
0.6352941, 0.6392157, 0.6431373, 0.6470588, 0.6509804, 0.654902, 0.6588235, 0.6627451,
0.6666667, 0.6705882, 0.6745098, 0.6784314, 0.6823529, 0.6862745, 0.6901961, 0.6941176,
0.6980392, 0.7019608, 0.7058824, 0.7098039, 0.7137255, 0.7176471, 0.7215686, 0.7254902,
0.7294118, 0.7333333, 0.7372549, 0.7411765, 0.745098, 0.7490196, 0.7529412, 0.7568627,
0.7607843, 0.7647059, 0.7686275, 0.772549, 0.7764706, 0.7803922, 0.7843137, 0.7882353,
0.7921569, 0.7960784, 0.8, 0.8039216, 0.8078431, 0.8117647, 0.8156863, 0.8196078,
0.8235294, 0.827451, 0.8313725, 0.8352941, 0.8392157, 0.8431373, 0.8470588, 0.8509804,
0.854902, 0.8588235, 0.8627451, 0.8666667, 0.8705882, 0.8745098, 0.8784314, 0.8823529,
0.8862745, 0.8901961, 0.8941176, 0.8980392, 0.9019608, 0.9058824, 0.9098039, 0.9137255,
0.9176471, 0.9215686, 0.9254902, 0.9294118, 0.9333333, 0.9372549, 0.9411765, 0.945098,
0.9490196, 0.9529412, 0.9568627, 0.9607843, 0.9647059, 0.9686275, 0.972549, 0.9764706,
0.9803922, 0.9843137, 0.9882353, 0.9921569, 0.9960784, 1.0,
];
U8_TO_F32[pixel as usize]
}
pub(crate) const fn grayscale(r: u8, g: u8, b: u8) -> f32 {
(u8_to_f32(r) + u8_to_f32(g) + u8_to_f32(b)) / 3.
}