Bug 1668526 - qcms: Fix v4 profiles. r=aosmond
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 01 Oct 2020 19:09:37 +0000
changeset 551170 225e361e5b8c001260196b63d6ae4f8e748121df
parent 551169 290e7f47eed96df17e9490496943d31c80aea481
child 551171 5954ef1f0b60bda0131a77ba5edf8c563d24d875
push id127712
push userjmuizelaar@mozilla.com
push dateThu, 01 Oct 2020 23:45:14 +0000
treeherderautoland@225e361e5b8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaosmond
bugs1668526
milestone83.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1668526 - qcms: Fix v4 profiles. r=aosmond Using floor() instead of ceil() was a typo that was introduced while converting from the libm functions to rust builtins. This adds a test to prevent us from breaking it in the future. Differential Revision: https://phabricator.services.mozilla.com/D92131
gfx/qcms/profiles/displaycal-lut-stripped.icc
gfx/qcms/src/chain.rs
gfx/qcms/src/gtest.rs
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..79ddef53e98a3082a0576f5023b60080a5d0ee2b
GIT binary patch
literal 17236
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
--- a/gfx/qcms/src/chain.rs
+++ b/gfx/qcms/src/chain.rs
@@ -336,18 +336,18 @@ unsafe extern "C" fn qcms_transform_modu
         let mut linear_b: f32 = lut_interp_linear_float(
             device_b,
             (*transform).input_clut_table_b,
             (*transform).input_clut_table_length as i32,
         );
         let mut x: i32 = (linear_r * ((*transform).grid_size as i32 - 1) as f32).floor() as i32;
         let mut y: i32 = (linear_g * ((*transform).grid_size as i32 - 1) as f32).floor() as i32;
         let mut z: i32 = (linear_b * ((*transform).grid_size as i32 - 1) as f32).floor() as i32;
-        let mut x_n: i32 = (linear_r * ((*transform).grid_size as i32 - 1) as f32).floor() as i32;
-        let mut y_n: i32 = (linear_g * ((*transform).grid_size as i32 - 1) as f32).floor() as i32;
+        let mut x_n: i32 = (linear_r * ((*transform).grid_size as i32 - 1) as f32).ceil() as i32;
+        let mut y_n: i32 = (linear_g * ((*transform).grid_size as i32 - 1) as f32).ceil() as i32;
         let mut z_n: i32 = (linear_b * ((*transform).grid_size as i32 - 1) as f32).ceil() as i32;
         let mut x_d: f32 = linear_r * ((*transform).grid_size as i32 - 1) as f32 - x as f32;
         let mut y_d: f32 = linear_g * ((*transform).grid_size as i32 - 1) as f32 - y as f32;
         let mut z_d: f32 = linear_b * ((*transform).grid_size as i32 - 1) as f32 - z as f32;
 
         let mut r_x1: f32 = lerp(CLU(r_table, x, y, z), CLU(r_table, x_n, y, z), x_d);
         let mut r_x2: f32 = lerp(CLU(r_table, x, y_n, z), CLU(r_table, x_n, y_n, z), x_d);
         let mut r_y1: f32 = lerp(r_x1, r_x2, y_d);
--- a/gfx/qcms/src/gtest.rs
+++ b/gfx/qcms/src/gtest.rs
@@ -1,11 +1,10 @@
 #[cfg(test)]
 mod test {
-
     use crate::{
         iccread::*, transform::*, transform_util::lut_inverse_interp16, QCMS_INTENT_PERCEPTUAL,
     };
 
     #[test]
     fn test_lut_inverse_crash() {
         let mut lutTable1: [u16; 128] = [
             0x0000, 0x0000, 0x0000, 0x8000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
@@ -255,9 +254,82 @@ mod test {
             let mut data = Vec::new();
             file.read_to_end(&mut data).unwrap();
             let profile =
                 unsafe { qcms_profile_from_memory(data.as_ptr() as *const c_void, data.len()) };
             assert_ne!(profile, std::ptr::null_mut());
             unsafe { qcms_profile_release(profile) };
         }
     }
+
+    #[test]
+    fn v4() {
+        use libc::c_void;
+        use std::io::Read;
+
+        let mut p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+        unsafe {
+            qcms_enable_iccv4();
+        }
+        p.push("profiles");
+        // this profile was made by taking the lookup table profile from
+        // http://displaycal.net/icc-color-management-test/ and removing
+        // the unneeed tables using lcms
+        p.push("displaycal-lut-stripped.icc");
+
+        let mut file = std::fs::File::open(p).unwrap();
+        let mut data = Vec::new();
+        file.read_to_end(&mut data).unwrap();
+        let profile =
+            unsafe { qcms_profile_from_memory(data.as_ptr() as *const c_void, data.len()) };
+        assert_ne!(profile, std::ptr::null_mut());
+
+        let srgb_profile = unsafe { qcms_profile_sRGB() };
+        assert_ne!(srgb_profile, std::ptr::null_mut());
+
+        unsafe { qcms_profile_precache_output_transform(srgb_profile) };
+
+        let intent = unsafe { qcms_profile_get_rendering_intent(profile) };
+        let transform = unsafe {
+            qcms_transform_create(
+                profile,
+                QCMS_DATA_RGB_8,
+                srgb_profile,
+                QCMS_DATA_RGB_8,
+                intent,
+            )
+        };
+
+        assert_ne!(transform, std::ptr::null_mut());
+
+        const SRC_SIZE: usize = 4;
+        let src: [u8; SRC_SIZE * 3] = [
+            246, 246, 246, // gray
+            255, 0, 0, // red
+            0, 255, 255, // cyan
+            255, 255, 0, // yellow
+        ];
+        let mut dst: [u8; SRC_SIZE * 3] = [0; SRC_SIZE * 3];
+
+        // the reference values here should be adjusted if the accuracy
+        // of the transformation changes
+        let mut reference = [
+            246, 246, 246, // gray
+            255, 0, 0, // red
+            248, 14, 22, // red
+            0, 0, 255, // blue
+        ];
+
+        unsafe {
+            qcms_transform_data(
+                transform,
+                src.as_ptr() as *const libc::c_void,
+                dst.as_mut_ptr() as *mut libc::c_void,
+                SRC_SIZE,
+            );
+        }
+
+        assert_eq!(reference, dst);
+        unsafe { qcms_transform_release(transform) }
+        unsafe { qcms_profile_release(profile) }
+        unsafe { qcms_profile_release(srgb_profile) }
+    }
 }