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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::opbasics::*;
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct OpGoFloat {
pub crop_top: usize,
pub crop_right: usize,
pub crop_bottom: usize,
pub crop_left: usize,
pub is_cfa: bool,
pub blacklevels: [f32;4],
pub whitelevels: [f32;4],
}
fn from_int4(arr: [u16;4]) -> [f32;4] {
[arr[0] as f32, arr[1] as f32, arr[2] as f32, arr[3] as f32]
}
impl OpGoFloat {
pub fn new(img: &RawImage) -> OpGoFloat {
OpGoFloat{
crop_top: img.crops[0],
crop_right: img.crops[1],
crop_bottom: img.crops[2],
crop_left: img.crops[3],
is_cfa: img.cfa.is_valid(),
blacklevels: from_int4(img.blacklevels),
whitelevels: from_int4(img.whitelevels),
}
}
}
impl<'a> ImageOp<'a> for OpGoFloat {
fn name(&self) -> &str {"gofloat"}
fn run(&self, pipeline: &PipelineGlobals, _buf: Arc<OpBuffer>) -> Arc<OpBuffer> {
let img = &pipeline.image;
let mins = self.blacklevels;
let ranges = self.whitelevels.iter().enumerate().map(|(i, &x)| {
x - mins[i]
}).collect::<Vec<f32>>();
let x = cmp::min(self.crop_left, img.width-10);
let y = cmp::min(self.crop_top, img.height-10);
let width = img.width - cmp::min(self.crop_left + self.crop_right, img.width-10);
let height = img.height - cmp::min(self.crop_top + self.crop_bottom, img.height-10);
Arc::new(match img.data {
RawImageData::Integer(ref data) => {
if img.cpp == 1 && !self.is_cfa {
let mut out = OpBuffer::new(width, height, 4, true);
out.mutate_lines(&(|line: &mut [f32], row| {
for (o, i) in line.chunks_exact_mut(4).zip(data[img.width*(row+y)+x..].chunks_exact(1)) {
let val = ((i[0] as f32 - mins[0]) / ranges[0]).min(1.0);
o[0] = val;
o[1] = val;
o[2] = val;
o[3] = 0.0;
}
}));
out
} else if img.cpp == 3 {
let mut out = OpBuffer::new(width, height, 4, false);
out.mutate_lines(&(|line: &mut [f32], row| {
for (o, i) in line.chunks_exact_mut(4).zip(data[(img.width*(row+y)+x)*3..].chunks_exact(3)) {
o[0] = ((i[0] as f32 - mins[0]) / ranges[0]).min(1.0);
o[1] = ((i[1] as f32 - mins[0]) / ranges[0]).min(1.0);
o[2] = ((i[2] as f32 - mins[0]) / ranges[0]).min(1.0);
o[3] = 0.0;
}
}));
out
} else {
let mut out = OpBuffer::new(width, height, img.cpp, false);
out.mutate_lines(&(|line: &mut [f32], row| {
for (o, i) in line.chunks_exact_mut(1).zip(data[img.width*(row+y)+x..].chunks_exact(1)) {
o[0] = ((i[0] as f32 - mins[0]) / ranges[0]).min(1.0);
}
}));
out
}
},
RawImageData::Float(ref data) => {
if img.cpp == 1 && !self.is_cfa {
let mut out = OpBuffer::new(width, height, 4, true);
out.mutate_lines(&(|line: &mut [f32], row| {
for (o, i) in line.chunks_exact_mut(4).zip(data[img.width*(row+y)+x..].chunks_exact(1)) {
let val = ((i[0] as f32 - mins[0]) / ranges[0]).min(1.0);
o[0] = val;
o[1] = val;
o[2] = val;
o[3] = 0.0;
}
}));
out
} else if img.cpp == 3 {
let mut out = OpBuffer::new(width, height, 4, false);
out.mutate_lines(&(|line: &mut [f32], row| {
for (o, i) in line.chunks_exact_mut(4).zip(data[(img.width*(row+y)+x)*3..].chunks_exact(3)) {
o[0] = ((i[0] as f32 - mins[0]) / ranges[0]).min(1.0);
o[1] = ((i[1] as f32 - mins[0]) / ranges[0]).min(1.0);
o[2] = ((i[2] as f32 - mins[0]) / ranges[0]).min(1.0);
o[3] = 0.0;
}
}));
out
} else {
let mut out = OpBuffer::new(width, height, img.cpp, false);
out.mutate_lines(&(|line: &mut [f32], row| {
for (o, i) in line.chunks_exact_mut(1).zip(data[img.width*(row+y)+x..].chunks_exact(1)) {
o[0] = ((i[0] as f32 - mins[0]) / ranges[0]).min(1.0);
}
}));
out
}
},
})
}
}