Skip to content

Commit f148c4b

Browse files
authored
Merge pull request #11 from awxkee/dev
Added Agx tone mapper, some improvements
2 parents a90fa31 + 0074c1d commit f148c4b

File tree

10 files changed

+332
-172
lines changed

10 files changed

+332
-172
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ workspace = { members = ["app"] }
22

33
[package]
44
name = "gainforge"
5-
version = "0.3.2"
5+
version = "0.3.4"
66
edition = "2021"
77
description = "HDR tonemapping library"
88
readme = "README.md"
@@ -17,10 +17,10 @@ exclude = ["*.jpg", "assets/*", "*.png", "assets/bench.jpg", "assets/bench.png",
1717
rust-version = "1.82.0"
1818

1919
[dependencies]
20-
moxcms = "0.6"
20+
moxcms = "^0.6.4"
2121
num-traits = "0.2"
2222
quick-xml = { version = "0.37", features = ["serde", "serde-types", "serialize"], optional = true }
23-
serde = { version = "1", features = ["derive"], optional = true }
23+
serde = { version = "^1.0.219", features = ["derive"], optional = true }
2424

2525
[features]
2626
default = []

app/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ edition = "2021"
66
[dependencies]
77
image = { version = "0.25.5", features = ["avif-native"] }
88
gainforge = { path = "../", features = ["uhdr"] }
9-
turbojpeg = "1.2.2"
109
num-traits = "0.2.19"
11-
moxcms = "0.6"
10+
moxcms = "^0.6.4"
1211
zune-jpeg = { git = "https://github.com/etemesi254/zune-image" }
13-
pic-scale = "0.5.3"
12+
pic-scale = "^0.6.4"

app/src/main.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ mod mlaf;
3030
mod parse;
3131

3232
use gainforge::{
33-
create_tone_mapper_rgb, create_tone_mapper_rgb16, BufferStore, CommonToneMapperParameters,
34-
FilmicSplineParameters, GainHdrMetadata, GainImage, GainImageMut, GamutClipping, IsoGainMap,
35-
JzazbzToneMapperParameters, MappingColorSpace, MpfInfo, RgbToneMapperParameters,
36-
ToneMappingMethod, TransferFunction, UhdrDirectoryContainer,
33+
create_tone_mapper_rgb, create_tone_mapper_rgb16, AgxCustomLook, AgxLook, BufferStore,
34+
CommonToneMapperParameters, FilmicSplineParameters, GainHdrMetadata, GainImage, GainImageMut,
35+
GamutClipping, IsoGainMap, JzazbzToneMapperParameters, MappingColorSpace, MpfInfo,
36+
RgbToneMapperParameters, ToneMappingMethod, TransferFunction, UhdrDirectoryContainer,
3737
};
38-
use moxcms::ColorProfile;
38+
use moxcms::{ColorProfile, Rgb};
3939
use std::fs::File;
4040
use std::io::{BufReader, Cursor, Read, Seek, SeekFrom};
4141
use std::time::Instant;
@@ -164,7 +164,7 @@ fn extract_images(file_path: &str) -> GainMapAssociationGroup {
164164
}
165165

166166
fn main() {
167-
let img = image::ImageReader::open("./assets/hdr.avif")
167+
let img = image::ImageReader::open("./assets/03.jpg")
168168
.unwrap()
169169
.decode()
170170
.unwrap();
@@ -180,19 +180,27 @@ fn main() {
180180
// black_point_target: 0.01f32,
181181
// ..Default::default()
182182
// }),
183-
// ToneMappingMethod::Reinhard,
184-
ToneMappingMethod::Rec2408(GainHdrMetadata::new(2000f32, 203.)),
185-
// ToneMappingMethod::Filmic,
186-
MappingColorSpace::Rgb(RgbToneMapperParameters {
187-
exposure: 1.0f32,
188-
gamut_clipping: GamutClipping::Clip,
189-
}),
190-
// MappingColorSpace::YRgb(CommonToneMapperParameters { exposure: 1f32, gamut_clipping: GamutClipping::Clip }),
191-
// MappingColorSpace::Jzazbz(JzazbzToneMapperParameters {
192-
// content_brightness: 2000f32,
183+
// ToneMappingMethod::Agx(AgxLook::Custom( AgxCustomLook {
184+
// slope: Rgb::new(1.0, 1.0, 1.0),
185+
// power: Rgb::new(1.1, 1.1, 1.1),
186+
// saturation: Rgb::new(1.4, 1.4, 1.4),
187+
// offset: Rgb::default(),
188+
// })),
189+
// ToneMappingMethod::Rec2408(GainHdrMetadata::new(2000f32, 203.)),
190+
ToneMappingMethod::Filmic,
191+
// MappingColorSpace::Rgb(RgbToneMapperParameters {
192+
// gamut_clipping: GamutClipping::NoClip,
193+
// exposure: 1f32,
194+
// }),
195+
// MappingColorSpace::YRgb(CommonToneMapperParameters {
193196
// exposure: 1f32,
194-
// gamut_clipping: GamutClipping::Clip,
197+
// gamut_clipping: GamutClipping::NoClip,
195198
// }),
199+
MappingColorSpace::Jzazbz(JzazbzToneMapperParameters {
200+
content_brightness: 2000.,
201+
exposure: 1f32,
202+
gamut_clipping: GamutClipping::NoClip,
203+
}),
196204
)
197205
.unwrap();
198206
let dims = rgb.dimensions();
@@ -239,7 +247,7 @@ fn main() {
239247
// let compressed = dst.iter().map(|&x| (x >> 8) as u8).collect::<Vec<_>>();
240248

241249
image::save_buffer(
242-
"clamp_rgb.jpg",
250+
"clamp_agx_t.jpg",
243251
&dst,
244252
img.width(),
245253
img.height(),

src/apply_gain_map.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@
2727
* // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828
*/
2929
use crate::iso_gain_map::{GainLUT, GainMap};
30-
use crate::mappers::Rgb;
3130
use crate::mlaf::mlaf;
3231
use crate::{ForgeError, GainImage, GainImageMut};
33-
use moxcms::{ColorProfile, GammaLutInterpolate, Matrix3f, PointeeSizeExpressible};
32+
use moxcms::{ColorProfile, GammaLutInterpolate, Matrix3f, PointeeSizeExpressible, Rgb};
3433
use num_traits::AsPrimitive;
3534
use std::fmt::{Debug, Display};
3635

src/err.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ impl Display for ForgeError {
7474
ForgeError::InvalidRenderingIntent => f.write_str("Invalid rendering intent"),
7575
ForgeError::DivisionByZero => f.write_str("Division by zero"),
7676
ForgeError::UnsupportedColorPrimaries(value) => {
77-
f.write_fmt(format_args!("Unsupported color primaries, {}", value))
77+
f.write_fmt(format_args!("Unsupported color primaries, {value}"))
7878
}
79-
ForgeError::UnsupportedTrc(value) => write!(f, "Unsupported TRC {}", value),
79+
ForgeError::UnsupportedTrc(value) => write!(f, "Unsupported TRC {value}"),
8080
ForgeError::InvalidGainMapConfiguration => {
8181
f.write_str("Invalid Gain map configuration")
8282
}

src/gamma.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,12 @@ pub(crate) fn bt1361_to_linear(gamma: f32) -> f32 {
135135
#[inline(always)]
136136
/// Pure gamma transfer function for gamma 2.2
137137
pub(crate) fn pure_gamma_function(x: f32, gamma: f32) -> f32 {
138-
if x <= 0f32 {
139-
0f32
140-
} else if x >= 1f32 {
141-
return 1f32;
138+
if x <= 0. {
139+
0.
140+
} else if x >= 1. {
141+
1.
142142
} else {
143-
return x.powf(gamma);
143+
x.powf(gamma)
144144
}
145145
}
146146

src/iso_gain_map.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
* // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2727
* // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828
*/
29-
use crate::mappers::Rgb;
3029
use crate::mlaf::mlaf;
30+
use moxcms::{f_exp2, f_exp2f, f_log2f, f_powf, Rgb};
3131
use quick_xml::Reader;
3232

3333
#[repr(C)]
@@ -709,8 +709,7 @@ impl IsoGainMap {
709709
return Err(UhdrErrorInfo {
710710
error_code: UhdrErrorCode::UnsupportedFeature,
711711
detail: Some(format!(
712-
"Unexpected minimum version {}, expected 0",
713-
min_version
712+
"Unexpected minimum version {min_version}, expected 0",
714713
)),
715714
});
716715
}
@@ -729,8 +728,7 @@ impl IsoGainMap {
729728
return Err(UhdrErrorInfo {
730729
error_code: UhdrErrorCode::UnsupportedFeature,
731730
detail: Some(format!(
732-
"Unexpected channel count {}, expected 1 or 3",
733-
channel_count
731+
"Unexpected channel count {channel_count}, expected 1 or 3",
734732
)),
735733
});
736734
}
@@ -849,9 +847,9 @@ impl IsoGainMap {
849847
let mut to = GainMap::default();
850848
for i in 0..3 {
851849
to.max_content_boost[i] =
852-
(self.gain_map_max_n[i] as f64 / self.gain_map_max_d[i] as f64).exp2() as f32;
850+
f_exp2(self.gain_map_max_n[i] as f64 / self.gain_map_max_d[i] as f64) as f32;
853851
to.min_content_boost[i] =
854-
(self.gain_map_min_n[i] as f64 / self.gain_map_min_d[i] as f64).exp2() as f32;
852+
f_exp2(self.gain_map_min_n[i] as f64 / self.gain_map_min_d[i] as f64) as f32;
855853

856854
to.gamma[i] =
857855
(self.gain_map_gamma_n[i] as f64 / self.gain_map_gamma_d[i] as f64) as f32;
@@ -861,11 +859,11 @@ impl IsoGainMap {
861859
to.offset_hdr[i] =
862860
(self.alternate_offset_n[i] as f64 / self.alternate_offset_d[i] as f64) as f32;
863861
}
864-
to.hdr_capacity_max = (self.alternate_hdr_headroom_n as f64
865-
/ self.alternate_hdr_headroom_d as f64)
866-
.exp2() as f32;
862+
to.hdr_capacity_max =
863+
f_exp2(self.alternate_hdr_headroom_n as f64 / self.alternate_hdr_headroom_d as f64)
864+
as f32;
867865
to.hdr_capacity_min =
868-
(self.base_hdr_headroom_n as f64 / self.base_hdr_headroom_d as f64).exp2() as f32;
866+
f_exp2(self.base_hdr_headroom_n as f64 / self.base_hdr_headroom_d as f64) as f32;
869867
to.use_base_cg = self.use_base_color_space;
870868
to
871869
}
@@ -885,7 +883,7 @@ pub struct GainMap {
885883

886884
impl GainMap {
887885
#[allow(dead_code)]
888-
pub(crate) fn all_channels_are_identical(&self) -> bool {
886+
pub(crate) fn are_all_channels_identical(&self) -> bool {
889887
self.max_content_boost[0] == self.max_content_boost[1]
890888
&& self.max_content_boost[0] == self.max_content_boost[2]
891889
&& self.min_content_boost[0] == self.min_content_boost[1]
@@ -910,18 +908,18 @@ pub struct GainLUT<const N: usize> {
910908
impl<const N: usize> GainLUT<N> {
911909
fn gen_table(idx: usize, metadata: GainMap, gainmap_weight: f32) -> Box<[f32; N]> {
912910
let mut set = Box::new([0f32; N]);
913-
let min_cb = metadata.min_content_boost[idx].log2();
914-
let max_cb = metadata.max_content_boost[idx].log2();
911+
let min_cb = f_log2f(metadata.min_content_boost[idx]);
912+
let max_cb = f_log2f(metadata.max_content_boost[idx]);
915913
for (i, gain_value) in set.iter_mut().enumerate() {
916914
let value = i as f32 / (N - 1) as f32;
917915
let log_boost = min_cb * (1.0f32 - value) + max_cb * value;
918-
*gain_value = (log_boost * gainmap_weight).exp2();
916+
*gain_value = f_exp2f(log_boost * gainmap_weight);
919917
}
920918
set
921919
}
922920

923921
pub fn new(metadata: GainMap, gainmap_weight: f32) -> Self {
924-
assert!(N >= 255, "Received N");
922+
assert!(N > 255, "Received N {N} but it should be > 255");
925923
let mut gamma_inv = [0f32; 3];
926924
gamma_inv[0] = (1f64 / metadata.gamma[0] as f64) as f32;
927925
gamma_inv[1] = (1f64 / metadata.gamma[1] as f64) as f32;
@@ -941,7 +939,7 @@ impl<const N: usize> GainLUT<N> {
941939
let gamma_inv = self.gamma_inv[CN];
942940
let mut gain = gain;
943941
if gamma_inv != 1.0f32 {
944-
gain = gain.powf(gamma_inv);
942+
gain = f_powf(gain, gamma_inv);
945943
}
946944
let idx = (mlaf(0.5f32, gain, (N - 1) as f32) as i32)
947945
.min(0)
@@ -971,7 +969,7 @@ impl<const N: usize> GainLUT<N> {
971969
}
972970

973971
#[inline]
974-
pub fn apply_gain(&self, color: Rgb, gain: Rgb) -> Rgb {
972+
pub fn apply_gain(&self, color: Rgb<f32>, gain: Rgb<f32>) -> Rgb<f32> {
975973
let gain_factor_r = self.get_gain_r_factor(gain.r);
976974
let gain_factor_g = self.get_gain_g_factor(gain.g);
977975
let gain_factor_b = self.get_gain_b_factor(gain.b);
@@ -993,7 +991,7 @@ impl<const N: usize> GainLUT<N> {
993991
/// Computes gain map weight for given display boost
994992
pub fn make_gainmap_weight(gain_map: GainMap, display_boost: f32) -> f32 {
995993
let input_boost = display_boost.max(1f32);
996-
let gainmap_weight = (input_boost.log2() - gain_map.hdr_capacity_min.log2())
997-
/ (gain_map.hdr_capacity_max.log2() - gain_map.hdr_capacity_min.log2());
994+
let gainmap_weight = (f_log2f(input_boost) - f_log2f(gain_map.hdr_capacity_min))
995+
/ (f_log2f(gain_map.hdr_capacity_max) - f_log2f(gain_map.hdr_capacity_min));
998996
gainmap_weight.max(0.0f32).min(1.0f32)
999997
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ pub use iso_gain_map::{
255255
MpfNumberOfImages, MpfTag, UhdrDirectory, UhdrDirectoryContainer, UhdrDirectoryRdf,
256256
UhdrDirectorySeq, UhdrItem, UhdrItemContainerLi, UhdrItemResource,
257257
};
258-
pub use mappers::ToneMappingMethod;
258+
pub use mappers::{AgxCustomLook, AgxLook, ToneMappingMethod};
259259
use num_traits::Num;
260260
pub use spline::FilmicSplineParameters;
261261
pub use tonemapper::{

0 commit comments

Comments
 (0)