use std::marker::PhantomData;
use super::convert::ConvertFrom;
use super::{BigEndian, Color, Endianness, LittleEndian, NativeEndian, Zero};
#[cfg(feature = "col-nrgba64")]
use super::{Nrgba64Be, Nrgba64Channels};
use crate::specialized;
pub trait Gray16Channels: Sized {
fn y(self) -> u16;
fn set_y(self, r: u16) -> Self;
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub struct Gray16<E> {
y: u16,
_endianness: PhantomData<E>,
}
impl<E1: Endianness> Gray16<E1> {
pub const fn cast<E2: Endianness>(self) -> Gray16<E2> {
let Gray16 { y, .. } = self;
Gray16 {
y,
_endianness: PhantomData,
}
}
}
pub type Gray16Ne = Gray16<NativeEndian>;
pub type Gray16Be = Gray16<BigEndian>;
pub type Gray16Le = Gray16<LittleEndian>;
impl Gray16<NativeEndian> {
pub const fn ne(y: u16) -> Self {
Self {
y,
_endianness: PhantomData,
}
}
}
impl Gray16Channels for Gray16<NativeEndian> {
#[inline(always)]
fn y(self) -> u16 {
self.y
}
#[inline(always)]
fn set_y(mut self, y: u16) -> Self {
self.y = y;
self
}
}
impl Gray16<LittleEndian> {
pub const fn le(y: u16) -> Self {
Self {
y: y.to_le(),
_endianness: PhantomData,
}
}
}
impl Gray16Channels for Gray16<LittleEndian> {
#[inline(always)]
fn y(self) -> u16 {
#[cfg(target_endian = "little")]
{
self.y
}
#[cfg(target_endian = "big")]
{
self.y.swap_bytes()
}
}
#[inline(always)]
fn set_y(mut self, y: u16) -> Self {
#[cfg(target_endian = "little")]
{
self.y = y
}
#[cfg(target_endian = "big")]
{
self.y = y.swap_bytes()
}
self
}
}
impl Gray16<BigEndian> {
pub const fn be(y: u16) -> Self {
Self {
y: y.to_be(),
_endianness: PhantomData,
}
}
}
impl Gray16Channels for Gray16<BigEndian> {
#[inline(always)]
fn y(self) -> u16 {
#[cfg(target_endian = "little")]
{
self.y.swap_bytes()
}
#[cfg(target_endian = "big")]
{
self.y
}
}
#[inline(always)]
fn set_y(mut self, y: u16) -> Self {
#[cfg(target_endian = "little")]
{
self.y = y.swap_bytes()
}
#[cfg(target_endian = "big")]
{
self.y = y
}
self
}
}
impl<E> Zero for Gray16<E>
where
Gray16<E>: Color + Copy,
{
const ZERO: Self = Gray16 {
y: 0,
_endianness: PhantomData,
};
}
impl<E> Color for Gray16<E>
where
E: Endianness,
Self: Copy + Gray16Channels,
{
fn as_rgba(&self) -> (u32, u32, u32, u32) {
let y = self.y() as u32;
(y, y, y, 0xffff)
}
}
impl<E1, E2> ConvertFrom<Gray16<E1>, specialized::Aye> for Gray16<E2>
where
E1: Endianness,
E2: Endianness,
Gray16<E1>: Color,
Gray16<E2>: Color + From<u16>,
u16: From<Gray16<E1>>,
{
fn convert_from(c: Gray16<E1>) -> Gray16<E2> {
let c: u16 = c.into();
c.into()
}
}
impl<C, E> ConvertFrom<C> for Gray16<E>
where
C: Color,
E: Endianness,
Self: Zero + Gray16Channels,
{
fn convert_from(c: C) -> Self {
let (r, g, b, _) = c.as_rgba();
Self::ZERO.set_y(((19595 * r + 38470 * g + 7471 * b + 0x8000) >> 16) as u16)
}
}
#[cfg(feature = "col-nrgba64")]
impl ConvertFrom<Nrgba64Be, specialized::For<Gray16Be>> for Gray16Be {
fn convert_from(c: Nrgba64Be) -> Self {
let (r, g, b) = (c.r(), c.g(), c.b());
let y = (((19595 * r as u64 + 38470 * g as u64 + 7471 * b as u64 + 0x8000) >> 16) as u16)
.to_be();
Gray16 {
y,
_endianness: PhantomData,
}
}
}
impl<E> From<Gray16<E>> for u16
where
E: Endianness,
Gray16<E>: Gray16Channels,
{
#[inline(always)]
fn from(c: Gray16<E>) -> u16 {
c.y()
}
}
impl<E> From<u16> for Gray16<E>
where
E: Endianness,
Self: Copy + Color + Gray16Channels,
{
#[inline(always)]
fn from(y: u16) -> Self {
Self::ZERO.set_y(y)
}
}