1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
pub extern crate unzip3;
use self::unzip3::Unzip3;
use image::RGBAPLU;
use image::RGBLU;
use image::ToRGB;
use imgref::*;
use rayon::prelude::*;
const D65x: f64 = 0.9505;
const D65y: f64 = 1.0;
const D65z: f64 = 1.089;
pub type GBitmap = ImgVec<f32>;
pub(crate) trait ToLAB {
fn to_lab(&self) -> (f32, f32, f32);
}
impl ToLAB for RGBLU {
fn to_lab(&self) -> (f32, f32, f32) {
let fx = ((self.r as f64 * 0.4124 + self.g as f64 * 0.3576 + self.b as f64 * 0.1805) / D65x) as f32;
let fy = ((self.r as f64 * 0.2126 + self.g as f64 * 0.7152 + self.b as f64 * 0.0722) / D65y) as f32;
let fz = ((self.r as f64 * 0.0193 + self.g as f64 * 0.1192 + self.b as f64 * 0.9505) / D65z) as f32;
let epsilon: f32 = 216. / 24389.;
let k = ((24389. / 27.) / 116.) as f32;
let X = if fx > epsilon {fx.powf(1./3.) - 16./116.} else {k * fx};
let Y = if fy > epsilon {fy.powf(1./3.) - 16./116.} else {k * fy};
let Z = if fz > epsilon {fz.powf(1./3.) - 16./116.} else {k * fz};
return (
Y * 1.16,
(86.2/ 220.0 + 500.0/ 220.0 * (X - Y)),
(107.9/ 220.0 + 200.0/ 220.0 * (Y - Z)),
);
}
}
pub trait ToLABBitmap {
fn to_lab(&self) -> Vec<GBitmap>;
}
impl ToLABBitmap for ImgVec<RGBAPLU> {
fn to_lab(&self) -> Vec<GBitmap> {
self.as_ref().to_lab()
}
}
impl ToLABBitmap for GBitmap {
fn to_lab(&self) -> Vec<GBitmap> {
vec![
self.new_buf(
self.buf.par_iter().cloned().map(|fy| {
let epsilon: f32 = 216. / 24389.;
let Y = if fy > epsilon { fy.powf(1. / 3.) - 16. / 116. } else { ((24389. / 27.) / 116.) * fy };
return Y * 1.16;
}).collect(),
)
]
}
}
impl<'a> ToLABBitmap for ImgRef<'a, RGBAPLU> {
fn to_lab(&self) -> Vec<GBitmap> {
let width = self.width();
let mut x=11;
let mut y=11;
let (l,a,b) = self.buf.iter().map(|px|{
let n = x ^ y;
if x >= width {
x=0;
y+=1;
}
x += 1;
px.to_rgb(n).to_lab()
}).unzip3();
return vec![
self.new_buf(l),
self.new_buf(a),
self.new_buf(b),
];
}
}
impl<'a> ToLABBitmap for ImgRef<'a, RGBLU> {
fn to_lab(&self) -> Vec<GBitmap> {
let (l, a, b) = self.buf.iter().map(|px| px.to_lab()).unzip3();
return vec![
self.new_buf(l),
self.new_buf(a),
self.new_buf(b),
];
}
}