Skip to content

Commit

Permalink
Added new gamma curves
Browse files Browse the repository at this point in the history
  • Loading branch information
awxkee committed Jun 16, 2024
1 parent 7074604 commit 1b3b686
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 62 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ workspace = { members = ["src/app"] }

[package]
name = "colorutils-rs"
version = "0.4.2"
version = "0.4.3"
edition = "2021"
description = "High performance utilities for color format handling and conversion."
readme = "README.md"
Expand Down
8 changes: 5 additions & 3 deletions src/app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,14 @@ fn main() {
lab_store.resize(width as usize * components * height as usize, 0f32);
let src_stride = width * components as u32;
let start_time = Instant::now();
rgb_to_lab(
rgb_to_linear(
src_bytes,
src_stride,
&mut lab_store,
store_stride as u32,
width,
height,
TransferFunction::Srgb,
);
let elapsed_time = start_time.elapsed();
// Print the elapsed time in milliseconds
Expand Down Expand Up @@ -92,13 +93,14 @@ fn main() {
// }

let start_time = Instant::now();
lab_to_srgb(
linear_to_rgb(
&lab_store,
store_stride as u32,
&mut dst_slice,
src_stride,
width,
height,
TransferFunction::Srgb
);

let elapsed_time = start_time.elapsed();
Expand Down Expand Up @@ -175,7 +177,7 @@ fn main() {
.unwrap();
} else {
image::save_buffer(
"converted.jpg",
"converted.png",
src_bytes.as_bytes(),
dimensions.0,
dimensions.1,
Expand Down
38 changes: 36 additions & 2 deletions src/gamma_curves.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#[inline(always)]
pub fn srgb_to_linear(gamma: f32) -> f32 {
return if gamma < 0f32 {
0f32
} else if gamma < 12.92f32 * 0.0030412825601275209f32 {
gamma / 12.92f32
gamma * (1f32 / 12.92f32)
} else if gamma < 1.0f32 {
((gamma + 0.0550107189475866f32) / 1.0550107189475866f32).powf(2.4f32)
} else {
1.0f32
};
}

#[inline(always)]
pub fn srgb_from_linear(linear: f32) -> f32 {
return if linear < 0.0f32 {
0.0f32
Expand All @@ -22,18 +24,20 @@ pub fn srgb_from_linear(linear: f32) -> f32 {
};
}

#[inline(always)]
pub fn rec709_to_linear(gamma: f32) -> f32 {
return if gamma < 0.0f32 {
0.0f32
} else if gamma < 4.5f32 * 0.018053968510807f32 {
gamma / 4.5f32
gamma * (1f32 / 4.5f32)
} else if gamma < 1.0f32 {
((gamma + 0.09929682680944f32) / 1.09929682680944f32).powf(1.0f32 / 0.45f32)
} else {
1.0f32
};
}

#[inline(always)]
pub fn rec709_from_linear(linear: f32) -> f32 {
return if linear < 0.0f32 {
0.0f32
Expand All @@ -46,10 +50,36 @@ pub fn rec709_from_linear(linear: f32) -> f32 {
};
}

#[inline(always)]
pub fn gamma2p2_from_linear(linear: f32) -> f32 {
linear.powf(1f32 / 2.2f32)
}

#[inline(always)]
pub fn gamma2p2_to_linear(gamma: f32) -> f32 {
gamma.powf(2.2f32)
}

#[inline(always)]
pub fn gamma2p8_from_linear(linear: f32) -> f32 {
linear.powf(1f32 / 2.8f32)
}

#[inline(always)]
pub fn gamma2p8_to_linear(gamma: f32) -> f32 {
gamma.powf(2.8f32)
}

#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum TransferFunction {
/// sRGB Transfer function
Srgb,
/// Rec.709 Transfer function
Rec709,
/// Pure gamma 2.2 Transfer function
Gamma2p2,
/// Pure gamma 2.8 Transfer function
Gamma2p8,
}

impl TransferFunction {
Expand All @@ -58,6 +88,8 @@ impl TransferFunction {
match self {
TransferFunction::Srgb => srgb_to_linear,
TransferFunction::Rec709 => rec709_to_linear,
TransferFunction::Gamma2p8 => gamma2p8_to_linear,
TransferFunction::Gamma2p2 => gamma2p2_to_linear,
}
}

Expand All @@ -66,6 +98,8 @@ impl TransferFunction {
match self {
TransferFunction::Srgb => srgb_from_linear,
TransferFunction::Rec709 => rec709_from_linear,
TransferFunction::Gamma2p2 => gamma2p2_from_linear,
TransferFunction::Gamma2p8 => gamma2p8_from_linear,
}
}
}
64 changes: 35 additions & 29 deletions src/neon/neon_gamma_curves.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
#[allow(unused_imports)]
use crate::gamma_curves::TransferFunction;
use crate::neon::neon_math::vpowq_n_f32;
#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
use std::arch::aarch64::*;

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn neon_srgb_from_linear(linear: float32x4_t) -> float32x4_t {
let low_cut_off = vdupq_n_f32(0.0030412825601275209f32);
Expand All @@ -28,11 +18,6 @@ pub unsafe fn neon_srgb_from_linear(linear: float32x4_t) -> float32x4_t {
return vbslq_f32(mask, high, low);
}

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn neon_srgb_to_linear(gamma: float32x4_t) -> float32x4_t {
let low_cut_off = vdupq_n_f32(12.92f32 * 0.0030412825601275209f32);
Expand All @@ -50,11 +35,6 @@ pub unsafe fn neon_srgb_to_linear(gamma: float32x4_t) -> float32x4_t {
return vbslq_f32(mask, high, low);
}

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn neon_rec709_from_linear(linear: float32x4_t) -> float32x4_t {
let low_cut_off = vdupq_n_f32(0.018053968510807f32);
Expand All @@ -71,11 +51,6 @@ pub unsafe fn neon_rec709_from_linear(linear: float32x4_t) -> float32x4_t {
return vbslq_f32(mask, high, low);
}

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
#[allow(dead_code)]
#[inline(always)]
pub unsafe fn neon_rec709_to_linear(linear: float32x4_t) -> float32x4_t {
let low_cut_off = vdupq_n_f32(4.5f32 * 0.018053968510807f32);
Expand All @@ -93,15 +68,46 @@ pub unsafe fn neon_rec709_to_linear(linear: float32x4_t) -> float32x4_t {
return vbslq_f32(mask, high, low);
}

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
#[inline(always)]
pub unsafe fn neon_gamma2p2_to_linear(gamma: float32x4_t) -> float32x4_t {
vpowq_n_f32(gamma, 2.2f32)
}

#[inline(always)]
pub unsafe fn neon_gamma2p8_to_linear(gamma: float32x4_t) -> float32x4_t {
vpowq_n_f32(gamma, 2.8f32)
}

#[inline(always)]
pub unsafe fn neon_gamma2p2_from_linear(linear: float32x4_t) -> float32x4_t {
vpowq_n_f32(linear, 1f32 / 2.2f32)
}

#[inline(always)]
pub unsafe fn neon_gamma2p8_from_linear(linear: float32x4_t) -> float32x4_t {
vpowq_n_f32(linear, 1f32 / 2.8f32)
}

#[inline(always)]
pub unsafe fn get_neon_linear_transfer(
transfer_function: TransferFunction,
) -> unsafe fn(float32x4_t) -> float32x4_t {
match transfer_function {
TransferFunction::Srgb => neon_srgb_to_linear,
TransferFunction::Rec709 => neon_rec709_to_linear,
TransferFunction::Gamma2p2 => neon_gamma2p2_to_linear,
TransferFunction::Gamma2p8 => neon_gamma2p8_to_linear,
}
}

#[inline(always)]
pub unsafe fn get_neon_gamma_transfer(
transfer_function: TransferFunction,
) -> unsafe fn(float32x4_t) -> float32x4_t {
match transfer_function {
TransferFunction::Srgb => neon_srgb_from_linear,
TransferFunction::Rec709 => neon_rec709_from_linear,
TransferFunction::Gamma2p2 => neon_gamma2p2_from_linear,
TransferFunction::Gamma2p8 => neon_gamma2p8_from_linear,
}
}
14 changes: 0 additions & 14 deletions src/neon/neon_linear_to_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ use crate::TransferFunction;
))]
use std::arch::aarch64::*;

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
))]
#[inline(always)]
pub unsafe fn get_neon_gamma_transfer(
transfer_function: TransferFunction,
) -> unsafe fn(float32x4_t) -> float32x4_t {
match transfer_function {
TransferFunction::Srgb => neon_srgb_from_linear,
TransferFunction::Rec709 => neon_rec709_from_linear,
}
}

#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
target_feature = "neon"
Expand Down
12 changes: 0 additions & 12 deletions src/sse/gamma_curves.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
#[allow(unused_imports)]
use crate::gamma_curves::TransferFunction;
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
use crate::sse::*;
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[inline(always)]
#[allow(dead_code)]
pub unsafe fn sse_srgb_from_linear(linear: __m128) -> __m128 {
let low_cut_off = _mm_set1_ps(0.0030412825601275209f32);
let mask = _mm_cmpge_ps(linear, low_cut_off);
Expand All @@ -28,9 +24,7 @@ pub unsafe fn sse_srgb_from_linear(linear: __m128) -> __m128 {
return _mm_select_ps(mask, high, low);
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[inline(always)]
#[allow(dead_code)]
pub unsafe fn sse_srgb_to_linear(gamma: __m128) -> __m128 {
let low_cut_off = _mm_set1_ps(12.92f32 * 0.0030412825601275209f32);
let mask = _mm_cmpge_ps(gamma, low_cut_off);
Expand All @@ -47,9 +41,7 @@ pub unsafe fn sse_srgb_to_linear(gamma: __m128) -> __m128 {
return _mm_select_ps(mask, high, low);
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[inline(always)]
#[allow(dead_code)]
pub unsafe fn sse_rec709_from_linear(linear: __m128) -> __m128 {
let low_cut_off = _mm_set1_ps(0.018053968510807f32);
let mask = _mm_cmpge_ps(linear, low_cut_off);
Expand All @@ -68,9 +60,7 @@ pub unsafe fn sse_rec709_from_linear(linear: __m128) -> __m128 {
return _mm_select_ps(mask, high, low);
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[inline(always)]
#[allow(dead_code)]
pub unsafe fn sse_rec709_to_linear(linear: __m128) -> __m128 {
let low_cut_off = _mm_set1_ps(4.5f32 * 0.018053968510807f32);
let mask = _mm_cmpge_ps(linear, low_cut_off);
Expand All @@ -87,7 +77,6 @@ pub unsafe fn sse_rec709_to_linear(linear: __m128) -> __m128 {
return _mm_select_ps(mask, high, low);
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
pub unsafe fn get_sse_linear_transfer(
transfer_function: TransferFunction,
) -> unsafe fn(__m128) -> __m128 {
Expand All @@ -97,7 +86,6 @@ pub unsafe fn get_sse_linear_transfer(
}
}

#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
#[inline(always)]
pub unsafe fn get_sse_gamma_transfer(
transfer_function: TransferFunction,
Expand Down

0 comments on commit 1b3b686

Please sign in to comment.