Skip to content

Commit

Permalink
Image to LAB/XYZ improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
awxkee committed Jun 2, 2024
1 parent bbffb6f commit 0b50118
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 31 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.2.6"
version = "0.2.7"
edition = "2021"
description = "Hig performance utilities for color format handling and conversion."
readme = "README.md"
Expand Down
19 changes: 12 additions & 7 deletions src/concat_alpha.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
use crate::x86_64_simd_support::{avx2_deinterleave_rgb_ps, avx2_interleave_rgba_ps};
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
use crate::x86_64_simd_support::{sse_deinterleave_rgb_ps, sse_interleave_ps_rgba};
#[cfg(all(
any(target_arch = "aarch64", target_arch = "arm"),
Expand All @@ -11,8 +13,6 @@ use std::arch::x86::*;
use std::arch::x86_64::*;
#[allow(unused_imports)]
use std::slice;
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
use crate::x86_64_simd_support::{avx2_deinterleave_rgb_ps, avx2_interleave_rgba_ps};

/// Adds alpha plane into an existing RGB/XYZ/LAB or other 3 plane image. Image will become RGBA, XYZa, LABa etc.
pub fn append_alpha(
Expand Down Expand Up @@ -69,7 +69,8 @@ pub fn append_alpha(

let xyza_chan_ptr = dst_ptr.add(cx * 4usize);

let (xyza0, xyza1, xyza2, xyza3) = avx2_interleave_rgba_ps(x_p, y_p, z_p, a_pixel);
let (xyza0, xyza1, xyza2, xyza3) =
avx2_interleave_rgba_ps(x_p, y_p, z_p, a_pixel);
_mm256_store_ps(xyza_chan_ptr, xyza0);
_mm256_store_ps(xyza_chan_ptr.add(8), xyza1);
_mm256_store_ps(xyza_chan_ptr.add(16), xyza2);
Expand Down Expand Up @@ -113,10 +114,14 @@ pub fn append_alpha(
}

for x in cx..width as usize {
dst_slice[x * 4] = src_slice[x * 3];
dst_slice[x * 4 + 1] = src_slice[x * 3 + 1];
dst_slice[x * 4 + 2] = src_slice[x * 3 + 2];
dst_slice[x * 4 + 3] = a_slice[x];
unsafe {
let px = x * 4;
let s_x = x * 3;
*dst_slice.get_unchecked_mut(px) = *src_slice.get_unchecked(s_x);
*dst_slice.get_unchecked_mut(px + 1) = *src_slice.get_unchecked(s_x + 1);
*dst_slice.get_unchecked_mut(px + 2) = *src_slice.get_unchecked(s_x + 2);
*dst_slice.get_unchecked_mut(px + 3) = *a_slice.get_unchecked(x);
}
}

dst_offset += dst_stride as usize;
Expand Down
30 changes: 21 additions & 9 deletions src/image_to_linear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use crate::image::ImageConfiguration;
target_feature = "neon"
))]
use crate::neon_to_linear::neon_channels_to_linear;
use crate::Rgb;
#[cfg(target_arch = "x86_64")]
use crate::sse_to_linear::sse_channels_to_linear;
use crate::Rgb;

#[inline(always)]
fn channels_to_linear<const CHANNELS_CONFIGURATION: u8, const USE_ALPHA: bool>(
Expand Down Expand Up @@ -85,21 +85,33 @@ fn channels_to_linear<const CHANNELS_CONFIGURATION: u8, const USE_ALPHA: bool>(

for x in cx..width as usize {
let px = x * channels;
let r = src_slice[px + image_configuration.get_r_channel_offset()];
let g = src_slice[px + image_configuration.get_g_channel_offset()];
let b = src_slice[px + image_configuration.get_b_channel_offset()];
let r = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_r_channel_offset())
};
let g = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_g_channel_offset())
};
let b = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_b_channel_offset())
};

let rgb = Rgb::<u8>::new(r, g, b);
let rgb_f32 = rgb.to_rgb_f32();

dst_slice[px] = transfer(rgb_f32.r);
dst_slice[px + 1] = transfer(rgb_f32.g);
dst_slice[px + 2] = transfer(rgb_f32.b);
unsafe {
*dst_slice.get_unchecked_mut(px) = transfer(rgb_f32.r);
*dst_slice.get_unchecked_mut(px + 1) = transfer(rgb_f32.g);
*dst_slice.get_unchecked_mut(px + 2) = transfer(rgb_f32.b);
}

if USE_ALPHA && image_configuration.has_alpha() {
let a = src_slice[px + image_configuration.get_a_channel_offset()];
let a = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_a_channel_offset())
};
let a_lin = a as f32 * (1f32 / 255f32);
dst_slice[px + 3] = a_lin;
unsafe {
*dst_slice.get_unchecked_mut(px + 3) = a_lin;
}
}
}

Expand Down
30 changes: 21 additions & 9 deletions src/linear_to_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use crate::image::ImageConfiguration;
target_feature = "neon"
))]
use crate::neon_linear_to_image::neon_linear_to_gamma;
use crate::Rgb;
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
use crate::sse_linear_to_image::sse_linear_to_gamma;
use crate::Rgb;

#[inline(always)]
fn linear_to_gamma_channels<const CHANNELS_CONFIGURATION: u8, const USE_ALPHA: bool>(
Expand Down Expand Up @@ -85,20 +85,32 @@ fn linear_to_gamma_channels<const CHANNELS_CONFIGURATION: u8, const USE_ALPHA: b

for x in cx..width as usize {
let px = x * channels;
let r = src_slice[px + image_configuration.get_r_channel_offset()];
let g = src_slice[px + image_configuration.get_g_channel_offset()];
let b = src_slice[px + image_configuration.get_b_channel_offset()];
let r = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_r_channel_offset())
};
let g = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_g_channel_offset())
};
let b = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_b_channel_offset())
};

let rgb = Rgb::<f32>::new(r, g, b);

dst_slice[px] = (transfer(rgb.r) * 255f32) as u8;
dst_slice[px + 1] = (transfer(rgb.g) * 255f32) as u8;
dst_slice[px + 2] = (transfer(rgb.b) * 255f32) as u8;
unsafe {
*dst_slice.get_unchecked_mut(px) = (transfer(rgb.r) * 255f32) as u8;
*dst_slice.get_unchecked_mut(px + 1) = (transfer(rgb.g) * 255f32) as u8;
*dst_slice.get_unchecked_mut(px + 2) = (transfer(rgb.b) * 255f32) as u8;
}

if USE_ALPHA && image_configuration.has_alpha() {
let a = src_slice[px + image_configuration.get_a_channel_offset()];
let a = unsafe {
*src_slice.get_unchecked(px + image_configuration.get_a_channel_offset())
};
let a_lin = (a * 255f32) as u8;
dst_slice[px + 3] = a_lin;
unsafe {
*dst_slice.get_unchecked_mut(px + 3) = a_lin;
}
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/rgb_expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,14 @@ pub fn rgb_to_rgba(
}

for x in cx..width as usize {
dst[dst_offset + x * 4] = src[src_offset + x * 3];
dst[dst_offset + x * 4 + 1] = src[src_offset + x * 3 + 1];
dst[dst_offset + x * 4 + 2] = src[src_offset + x * 3 + 2];
dst[dst_offset + x * 4 + 3] = default_alpha;
let px = dst_offset + x * 4;
let s_x = src_offset + x * 3;
unsafe {
*dst.get_unchecked_mut(px) = *src.get_unchecked(s_x);
*dst.get_unchecked_mut(px + 1) = *src.get_unchecked(s_x + 1);
*dst.get_unchecked_mut(px + 2) = *src.get_unchecked(s_x + 2);
*dst.get_unchecked_mut(px + 3) = default_alpha;
}
}

dst_offset += dst_stride as usize;
Expand Down

0 comments on commit 0b50118

Please sign in to comment.