Bug 1667374 - Make curveType more Rust like. r=aosmond

Turns curveType into a enum. The change is mostly mechanical fixing of
the the code to the new structure except that for Parametrics curves
we now store the result of COUNT_TO_LENGTH as the len.
This mostly affects compute_curve_gamma_table_type_parametric where we
use the post COUNT_TO_LENGTH instead of the pre COUNT_TO_LENGTH.

Differential Revision: https://phabricator.services.mozilla.com/D91421
This commit is contained in:
Jeff Muizelaar 2020-09-27 18:57:50 +00:00
Родитель 5440a231d9
Коммит b5a1244a00
5 изменённых файлов: 242 добавлений и 292 удалений

Просмотреть файл

@ -819,7 +819,7 @@ unsafe extern "C" fn qcms_modular_transform_create_mAB(
let mut first_transform: *mut qcms_modular_transform = 0 as *mut qcms_modular_transform;
let mut next_transform: *mut *mut qcms_modular_transform = &mut first_transform;
let mut transform: *mut qcms_modular_transform;
if !(*lut).a_curves[0].is_null() {
if !(*lut).a_curves[0].is_none() {
let mut clut_length: usize;
let mut clut: *mut f32;
// If the A curve is present this also implies the
@ -833,9 +833,12 @@ unsafe extern "C" fn qcms_modular_transform_create_mAB(
current_block = 7590209878260659629;
} else {
append_transform(transform, &mut next_transform);
(*transform).input_clut_table_r = build_input_gamma_table((*lut).a_curves[0]);
(*transform).input_clut_table_g = build_input_gamma_table((*lut).a_curves[1]);
(*transform).input_clut_table_b = build_input_gamma_table((*lut).a_curves[2]);
(*transform).input_clut_table_r =
build_input_gamma_table((*lut).a_curves[0].as_deref());
(*transform).input_clut_table_g =
build_input_gamma_table((*lut).a_curves[1].as_deref());
(*transform).input_clut_table_b =
build_input_gamma_table((*lut).a_curves[2].as_deref());
(*transform).transform_module_fn = Some(
qcms_transform_module_gamma_table
as unsafe extern "C" fn(
@ -894,7 +897,7 @@ unsafe extern "C" fn qcms_modular_transform_create_mAB(
}
match current_block {
10652014663920648156 => {
if !(*lut).m_curves[0].is_null() {
if !(*lut).m_curves[0].is_none() {
// M curve imples the presence of a Matrix
// Prepare M curve
transform = qcms_modular_transform_alloc();
@ -902,9 +905,12 @@ unsafe extern "C" fn qcms_modular_transform_create_mAB(
current_block = 7590209878260659629;
} else {
append_transform(transform, &mut next_transform);
(*transform).input_clut_table_r = build_input_gamma_table((*lut).m_curves[0]);
(*transform).input_clut_table_g = build_input_gamma_table((*lut).m_curves[1]);
(*transform).input_clut_table_b = build_input_gamma_table((*lut).m_curves[2]);
(*transform).input_clut_table_r =
build_input_gamma_table((*lut).m_curves[0].as_deref());
(*transform).input_clut_table_g =
build_input_gamma_table((*lut).m_curves[1].as_deref());
(*transform).input_clut_table_b =
build_input_gamma_table((*lut).m_curves[2].as_deref());
(*transform).transform_module_fn = Some(
qcms_transform_module_gamma_table
as unsafe extern "C" fn(
@ -947,17 +953,17 @@ unsafe extern "C" fn qcms_modular_transform_create_mAB(
match current_block {
7590209878260659629 => {}
_ => {
if !(*lut).b_curves[0].is_null() {
if !(*lut).b_curves[0].is_none() {
// Prepare B curve
transform = qcms_modular_transform_alloc();
if !transform.is_null() {
append_transform(transform, &mut next_transform);
(*transform).input_clut_table_r =
build_input_gamma_table((*lut).b_curves[0]);
build_input_gamma_table((*lut).b_curves[0].as_deref());
(*transform).input_clut_table_g =
build_input_gamma_table((*lut).b_curves[1]);
build_input_gamma_table((*lut).b_curves[1].as_deref());
(*transform).input_clut_table_b =
build_input_gamma_table((*lut).b_curves[2]);
build_input_gamma_table((*lut).b_curves[2].as_deref());
(*transform).transform_module_fn = Some(
qcms_transform_module_gamma_table
as unsafe extern "C" fn(
@ -1118,9 +1124,9 @@ pub unsafe extern "C" fn qcms_modular_transform_create_input(
current_block = 8903102000210989603;
} else {
append_transform(transform, &mut next_transform);
(*transform).input_clut_table_r = build_input_gamma_table((*in_0).redTRC);
(*transform).input_clut_table_g = build_input_gamma_table((*in_0).greenTRC);
(*transform).input_clut_table_b = build_input_gamma_table((*in_0).blueTRC);
(*transform).input_clut_table_r = build_input_gamma_table((*in_0).redTRC.as_deref());
(*transform).input_clut_table_g = build_input_gamma_table((*in_0).greenTRC.as_deref());
(*transform).input_clut_table_b = build_input_gamma_table((*in_0).blueTRC.as_deref());
(*transform).transform_module_fn = Some(
qcms_transform_module_gamma_table
as unsafe extern "C" fn(
@ -1216,7 +1222,7 @@ unsafe extern "C" fn qcms_modular_transform_create_output(
append_transform(lut_transform_0, &mut next_transform);
current_block = 13131896068329595644;
}
} else if !(*out).redTRC.is_null() && !(*out).greenTRC.is_null() && !(*out).blueTRC.is_null() {
} else if !(*out).redTRC.is_none() && !(*out).greenTRC.is_none() && !(*out).blueTRC.is_none() {
let mut transform: *mut qcms_modular_transform = qcms_modular_transform_alloc();
if transform.is_null() {
current_block = 15713701561912628542;
@ -1262,17 +1268,17 @@ unsafe extern "C" fn qcms_modular_transform_create_output(
} else {
append_transform(transform, &mut next_transform);
build_output_lut(
(*out).redTRC,
(*out).redTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_r,
&mut (*transform).output_gamma_lut_r_length,
);
build_output_lut(
(*out).greenTRC,
(*out).greenTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_g,
&mut (*transform).output_gamma_lut_g_length,
);
build_output_lut(
(*out).blueTRC,
(*out).blueTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_b,
&mut (*transform).output_gamma_lut_b_length,
);

Просмотреть файл

@ -2,9 +2,7 @@
mod test {
use crate::{
iccread::*,
transform::*,
transform_util::lut_inverse_interp16, QCMS_INTENT_PERCEPTUAL,
iccread::*, transform::*, transform_util::lut_inverse_interp16, QCMS_INTENT_PERCEPTUAL,
};
#[test]

Просмотреть файл

@ -84,10 +84,10 @@ pub struct qcms_profile {
pub redColorant: XYZNumber,
pub blueColorant: XYZNumber,
pub greenColorant: XYZNumber,
pub redTRC: *mut curveType,
pub blueTRC: *mut curveType,
pub greenTRC: *mut curveType,
pub grayTRC: *mut curveType,
pub redTRC: Option<Box<curveType>>,
pub blueTRC: Option<Box<curveType>>,
pub greenTRC: Option<Box<curveType>>,
pub grayTRC: Option<Box<curveType>>,
pub A2B0: *mut lutType,
pub B2A0: *mut lutType,
pub mAB: *mut lutmABType,
@ -122,16 +122,12 @@ impl Drop for qcms_profile {
if !self.mBA.is_null() {
mAB_release(self.mBA);
}
free(self.redTRC as *mut libc::c_void);
free(self.blueTRC as *mut libc::c_void);
free(self.greenTRC as *mut libc::c_void);
free(self.grayTRC as *mut libc::c_void);
}
}
}
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Clone)]
pub struct lutmABType {
pub num_in_channels: u8,
pub num_out_channels: u8,
@ -150,19 +146,17 @@ pub struct lutmABType {
pub e23: s15Fixed16Number,
pub reversed: bool,
pub clut_table: *mut f32,
pub a_curves: [*mut curveType; 10],
pub b_curves: [*mut curveType; 10],
pub m_curves: [*mut curveType; 10],
pub a_curves: [Option<Box<curveType>>; 10],
pub b_curves: [Option<Box<curveType>>; 10],
pub m_curves: [Option<Box<curveType>>; 10],
pub clut_table_data: [f32; 0],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct curveType {
pub type_0: u32,
pub count: u32,
pub parameter: [f32; 7],
pub data: [uInt16Number; 0],
#[derive(Clone)]
pub enum curveType {
Curve(Vec<uInt16Number>),
Parametric(Vec<f32>),
}
pub type uInt16Number = u16;
@ -647,93 +641,75 @@ fn read_tag_XYZType(mut src: &mut mem_source, mut index: &tag_index, mut tag_id:
// Read the tag at a given offset rather then the tag_index.
// This method is used when reading mAB tags where nested curveType are
// present that are not part of the tag_index.
unsafe extern "C" fn read_curveType(
fn read_curveType(
mut src: &mut mem_source,
mut offset: u32,
mut len: *mut u32,
) -> *mut curveType {
static mut COUNT_TO_LENGTH: [u32; 5] = [1, 3, 4, 5, 7]; //PARAMETRIC_CURVE_TYPE
mut len: &mut u32,
) -> Option<Box<curveType>> {
const COUNT_TO_LENGTH: [u32; 5] = [1, 3, 4, 5, 7]; //PARAMETRIC_CURVE_TYPE
let mut curve: *mut curveType;
let mut type_0: u32 = read_u32(src, offset as usize);
let mut count: u32;
let mut i: u32;
if type_0 != CURVE_TYPE && type_0 != PARAMETRIC_CURVE_TYPE {
invalid_source(src, "unexpected type, expected CURV or PARA");
return 0 as *mut curveType;
return None;
}
if type_0 == CURVE_TYPE {
count = read_u32(src, (offset + 8) as usize);
//arbitrary
if count > 40000 {
invalid_source(src, "curve size too large");
return 0 as *mut curveType;
return None;
}
curve = malloc(
::std::mem::size_of::<curveType>()
+ ::std::mem::size_of::<uInt16Number>() * count as usize,
) as *mut curveType;
if curve.is_null() {
return 0 as *mut curveType;
let mut table = Vec::with_capacity(count as usize);
for i in 0..count {
table.push(read_u16(src, (offset + 12 + i * 2) as usize));
}
(*curve).count = count;
(*curve).type_0 = CURVE_TYPE;
i = 0;
while i < count {
*(*curve).data.as_mut_ptr().offset(i as isize) =
read_u16(src, (offset + 12 + i * 2) as usize);
i = i + 1
}
*len = 12 + count * 2
*len = 12 + count * 2;
return Some(Box::new(curveType::Curve(table)));
} else {
count = read_u16(src, (offset + 8) as usize) as u32;
if count > 4 {
invalid_source(src, "parametric function type not supported.");
return 0 as *mut curveType;
return None;
}
curve = malloc(::std::mem::size_of::<curveType>()) as *mut curveType;
if curve.is_null() {
return 0 as *mut curveType;
}
(*curve).count = count;
(*curve).type_0 = PARAMETRIC_CURVE_TYPE;
i = 0;
while i < COUNT_TO_LENGTH[count as usize] {
(*curve).parameter[i as usize] = s15Fixed16Number_to_float(read_s15Fixed16Number(
let mut params = Vec::with_capacity(count as usize);
for i in 0..COUNT_TO_LENGTH[count as usize] {
params.push(s15Fixed16Number_to_float(read_s15Fixed16Number(
src,
(offset + 12 + i * 4) as usize,
));
i = i + 1
)));
}
*len = 12 + COUNT_TO_LENGTH[count as usize] * 4;
if count == 1 || count == 2 {
/* we have a type 1 or type 2 function that has a division by 'a' */
let mut a: f32 = (*curve).parameter[1];
let mut a: f32 = params[1];
if a == 0.0 {
invalid_source(src, "parametricCurve definition causes division by zero");
}
}
return Some(Box::new(curveType::Parametric(params)));
}
return curve;
}
unsafe fn read_tag_curveType(
fn read_tag_curveType(
mut src: &mut mem_source,
mut index: &tag_index,
mut tag_id: u32,
) -> *mut curveType {
) -> Option<Box<curveType>> {
let mut tag = find_tag(index, tag_id);
let mut curve: *mut curveType = 0 as *mut curveType;
if let Some(tag) = tag {
let mut len: u32 = 0;
return read_curveType(src, (*tag).offset, &mut len);
} else {
invalid_source(src, "missing curvetag");
}
return curve;
return None;
}
// arbitrary
unsafe extern "C" fn read_nested_curveType(
mut src: &mut mem_source,
mut curveArray: *mut [*mut curveType; 10],
mut curveArray: *mut [Option<Box<curveType>>; 10],
mut num_channels: u8,
mut curve_offset: u32,
) {
@ -744,7 +720,7 @@ unsafe extern "C" fn read_nested_curveType(
let mut tag_len: u32 = 0;
(*curveArray)[i as usize] =
read_curveType(src, curve_offset + channel_offset, &mut tag_len);
if (*curveArray)[i as usize].is_null() {
if (*curveArray)[i as usize].is_none() {
invalid_source(src, "invalid nested curveType curve");
break;
} else {
@ -761,13 +737,13 @@ unsafe extern "C" fn mAB_release(mut lut: *mut lutmABType) {
let mut i: u8;
i = 0u8;
while (i as i32) < (*lut).num_in_channels as i32 {
free((*lut).a_curves[i as usize] as *mut libc::c_void);
(*lut).a_curves[i as usize] = None;
i = i + 1
}
i = 0u8;
while (i as i32) < (*lut).num_out_channels as i32 {
free((*lut).b_curves[i as usize] as *mut libc::c_void);
free((*lut).m_curves[i as usize] as *mut libc::c_void);
(*lut).b_curves[i as usize] = None;
(*lut).m_curves[i as usize] = None;
i = i + 1
}
free(lut as *mut libc::c_void);
@ -1139,26 +1115,15 @@ unsafe extern "C" fn build_sRGB_gamma_table(mut num_entries: i32) -> *mut u16 {
}
return table;
}
unsafe extern "C" fn curve_from_table(mut table: *mut u16, mut num_entries: i32) -> *mut curveType {
unsafe extern "C" fn curve_from_table(mut table: *mut u16, mut num_entries: i32) -> Box<curveType> {
let mut curve: *mut curveType;
let mut i: i32;
curve = malloc(
::std::mem::size_of::<curveType>()
+ ::std::mem::size_of::<uInt16Number>() * num_entries as usize,
) as *mut curveType;
if curve.is_null() {
return 0 as *mut curveType;
let mut data = Vec::with_capacity(num_entries as usize);
for i in 0..num_entries {
data.push(*table.offset(i as isize));
}
(*curve).type_0 = CURVE_TYPE;
(*curve).count = num_entries as u32;
i = 0;
while i < num_entries {
*(*curve).data.as_mut_ptr().offset(i as isize) = *table.offset(i as isize);
i += 1
}
return curve;
return Box::new(curveType::Curve(data));
}
unsafe extern "C" fn float_to_u8Fixed8Number(mut a: f32) -> u16 {
fn float_to_u8Fixed8Number(mut a: f32) -> u16 {
if a > 255.0 + 255.0 / 256f32 {
return 0xffffu16;
} else if a < 0.0 {
@ -1167,20 +1132,9 @@ unsafe extern "C" fn float_to_u8Fixed8Number(mut a: f32) -> u16 {
return (a * 256.0 + 0.5).floor() as u16;
};
}
unsafe extern "C" fn curve_from_gamma(mut gamma: f32) -> *mut curveType {
let mut curve: *mut curveType;
let mut num_entries: i32 = 1;
curve = malloc(
::std::mem::size_of::<curveType>()
+ ::std::mem::size_of::<uInt16Number>() * num_entries as usize,
) as *mut curveType;
if curve.is_null() {
return 0 as *mut curveType;
}
(*curve).count = num_entries as u32;
*(*curve).data.as_mut_ptr().offset(0isize) = float_to_u8Fixed8Number(gamma);
(*curve).type_0 = CURVE_TYPE;
return curve;
fn curve_from_gamma(mut gamma: f32) -> Box<curveType> {
Box::new(curveType::Curve(vec![float_to_u8Fixed8Number(gamma)]))
}
//XXX: it would be nice if we had a way of ensuring
// everything in a profile was initialized regardless of how it was created
@ -1200,10 +1154,10 @@ pub unsafe extern "C" fn qcms_profile_create_rgb_with_gamma_set(
if !set_rgb_colorants(&mut profile, white_point, primaries) {
return 0 as *mut qcms_profile;
}
(*profile).redTRC = curve_from_gamma(redGamma);
(*profile).blueTRC = curve_from_gamma(blueGamma);
(*profile).greenTRC = curve_from_gamma(greenGamma);
if (*profile).redTRC.is_null() || (*profile).blueTRC.is_null() || (*profile).greenTRC.is_null()
(*profile).redTRC = Some(curve_from_gamma(redGamma));
(*profile).blueTRC = Some(curve_from_gamma(blueGamma));
(*profile).greenTRC = Some(curve_from_gamma(greenGamma));
if (*profile).redTRC.is_none() || (*profile).blueTRC.is_none() || (*profile).greenTRC.is_none()
{
return 0 as *mut qcms_profile;
}
@ -1218,8 +1172,8 @@ pub unsafe extern "C" fn qcms_profile_create_rgb_with_gamma_set(
pub unsafe extern "C" fn qcms_profile_create_gray_with_gamma(mut gamma: f32) -> *mut qcms_profile {
let mut profile = qcms_profile_create();
(*profile).grayTRC = curve_from_gamma(gamma);
if (*profile).grayTRC.is_null() {
(*profile).grayTRC = Some(curve_from_gamma(gamma));
if (*profile).grayTRC.is_none() {
return 0 as *mut qcms_profile;
}
(*profile).class_type = DISPLAY_DEVICE_PROFILE;
@ -1249,10 +1203,10 @@ pub unsafe extern "C" fn qcms_profile_create_rgb_with_table(
if !set_rgb_colorants(&mut profile, white_point, primaries) {
return 0 as *mut qcms_profile;
}
(*profile).redTRC = curve_from_table(table, num_entries);
(*profile).blueTRC = curve_from_table(table, num_entries);
(*profile).greenTRC = curve_from_table(table, num_entries);
if (*profile).redTRC.is_null() || (*profile).blueTRC.is_null() || (*profile).greenTRC.is_null()
(*profile).redTRC = Some(curve_from_table(table, num_entries));
(*profile).blueTRC = Some(curve_from_table(table, num_entries));
(*profile).greenTRC = Some(curve_from_table(table, num_entries));
if (*profile).redTRC.is_none() || (*profile).blueTRC.is_none() || (*profile).greenTRC.is_none()
{
return 0 as *mut qcms_profile;
}
@ -1451,16 +1405,16 @@ pub unsafe extern "C" fn qcms_profile_from_memory(
(*profile).redTRC = read_tag_curveType(src, &index, TAG_rTRC);
(*profile).greenTRC = read_tag_curveType(src, &index, TAG_gTRC);
(*profile).blueTRC = read_tag_curveType(src, &index, TAG_bTRC);
if (*profile).redTRC.is_null()
|| (*profile).blueTRC.is_null()
|| (*profile).greenTRC.is_null()
if (*profile).redTRC.is_none()
|| (*profile).blueTRC.is_none()
|| (*profile).greenTRC.is_none()
{
return null_mut();
}
}
} else if (*profile).color_space == GRAY_SIGNATURE {
(*profile).grayTRC = read_tag_curveType(src, &index, TAG_kTRC);
if (*profile).grayTRC.is_null() {
if (*profile).grayTRC.is_none() {
return null_mut();
}
} else {

Просмотреть файл

@ -1186,7 +1186,7 @@ pub unsafe extern "C" fn qcms_profile_precache_output_transform(mut profile: *mu
}
}
/* don't precache if we do not have the TRC curves */
if (*profile).redTRC.is_null() || (*profile).greenTRC.is_null() || (*profile).blueTRC.is_null()
if (*profile).redTRC.is_none() || (*profile).greenTRC.is_none() || (*profile).blueTRC.is_none()
{
return;
}
@ -1194,7 +1194,7 @@ pub unsafe extern "C" fn qcms_profile_precache_output_transform(mut profile: *mu
(*profile).output_table_r = precache_create();
if !(*profile).output_table_r.is_null()
&& !compute_precache(
(*profile).redTRC,
(*profile).redTRC.as_deref().unwrap(),
(*(*profile).output_table_r).data.as_mut_ptr(),
)
{
@ -1206,7 +1206,7 @@ pub unsafe extern "C" fn qcms_profile_precache_output_transform(mut profile: *mu
(*profile).output_table_g = precache_create();
if !(*profile).output_table_g.is_null()
&& !compute_precache(
(*profile).greenTRC,
(*profile).greenTRC.as_deref().unwrap(),
(*(*profile).output_table_g).data.as_mut_ptr(),
)
{
@ -1218,7 +1218,7 @@ pub unsafe extern "C" fn qcms_profile_precache_output_transform(mut profile: *mu
(*profile).output_table_b = precache_create();
if !(*profile).output_table_b.is_null()
&& !compute_precache(
(*profile).blueTRC,
(*profile).blueTRC.as_deref().unwrap(),
(*(*profile).output_table_b).data.as_mut_ptr(),
)
{
@ -1367,22 +1367,22 @@ pub unsafe extern "C" fn qcms_transform_create(
(*transform).output_table_g = precache_reference((*out).output_table_g);
(*transform).output_table_b = precache_reference((*out).output_table_b)
} else {
if (*out).redTRC.is_null() || (*out).greenTRC.is_null() || (*out).blueTRC.is_null() {
if (*out).redTRC.is_none() || (*out).greenTRC.is_none() || (*out).blueTRC.is_none() {
qcms_transform_release(transform);
return 0 as *mut qcms_transform;
}
build_output_lut(
(*out).redTRC,
(*out).redTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_r,
&mut (*transform).output_gamma_lut_r_length,
);
build_output_lut(
(*out).greenTRC,
(*out).greenTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_g,
&mut (*transform).output_gamma_lut_g_length,
);
build_output_lut(
(*out).blueTRC,
(*out).blueTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_b,
&mut (*transform).output_gamma_lut_b_length,
);
@ -1449,9 +1449,9 @@ pub unsafe extern "C" fn qcms_transform_create(
(*transform).transform_fn = Some(qcms_transform_data_bgra_out_lut)
}
//XXX: avoid duplicating tables if we can
(*transform).input_gamma_table_r = build_input_gamma_table((*in_0).redTRC);
(*transform).input_gamma_table_g = build_input_gamma_table((*in_0).greenTRC);
(*transform).input_gamma_table_b = build_input_gamma_table((*in_0).blueTRC);
(*transform).input_gamma_table_r = build_input_gamma_table((*in_0).redTRC.as_deref());
(*transform).input_gamma_table_g = build_input_gamma_table((*in_0).greenTRC.as_deref());
(*transform).input_gamma_table_b = build_input_gamma_table((*in_0).blueTRC.as_deref());
if (*transform).input_gamma_table_r.is_null()
|| (*transform).input_gamma_table_g.is_null()
|| (*transform).input_gamma_table_b.is_null()
@ -1494,7 +1494,7 @@ pub unsafe extern "C" fn qcms_transform_create(
(*transform).matrix[1][2] = result_0.m[2][1];
(*transform).matrix[2][2] = result_0.m[2][2]
} else if (*in_0).color_space == 0x47524159 {
(*transform).input_gamma_table_gray = build_input_gamma_table((*in_0).grayTRC);
(*transform).input_gamma_table_gray = build_input_gamma_table((*in_0).grayTRC.as_deref());
if (*transform).input_gamma_table_gray.is_null() {
qcms_transform_release(transform);
return 0 as *mut qcms_transform;

Просмотреть файл

@ -24,7 +24,7 @@
use ::libc;
use libc::{free, malloc};
use crate::{iccread::PARAMETRIC_CURVE_TYPE, matrix::matrix};
use crate::matrix::matrix;
use crate::{
iccread::{curveType, qcms_profile},
s15Fixed16Number_to_float,
@ -73,7 +73,7 @@ pub fn clamp_float(mut a: f32) -> f32 {
#[no_mangle]
pub unsafe extern "C" fn lut_interp_linear(
mut input_value: f64,
mut table: *mut u16,
mut table: *const u16,
mut length: i32,
) -> f32 {
input_value = input_value * (length - 1) as f64;
@ -91,7 +91,7 @@ pub unsafe extern "C" fn lut_interp_linear(
#[no_mangle]
pub unsafe extern "C" fn lut_interp_linear16(
mut input_value: u16,
mut table: *mut u16,
mut table: *const u16,
mut length: i32,
) -> u16 {
/* Start scaling input_value to the length of the array: 65535*(length-1).
@ -162,22 +162,18 @@ pub unsafe extern "C" fn compute_curve_gamma_table_type1(
}
}
#[no_mangle]
pub unsafe extern "C" fn compute_curve_gamma_table_type2(
mut gamma_table: *mut f32,
mut table: *mut u16,
mut length: i32,
) {
pub unsafe fn compute_curve_gamma_table_type2(mut gamma_table: *mut f32, mut table: &[u16]) {
let mut i: libc::c_uint = 0;
while i < 256 {
*gamma_table.offset(i as isize) = lut_interp_linear(i as f64 / 255.0f64, table, length);
*gamma_table.offset(i as isize) =
lut_interp_linear(i as f64 / 255.0f64, table.as_ptr(), table.len() as i32);
i = i + 1
}
}
#[no_mangle]
pub unsafe extern "C" fn compute_curve_gamma_table_type_parametric(
pub unsafe fn compute_curve_gamma_table_type_parametric(
mut gamma_table: *mut f32,
mut parameter: *mut f32,
mut count: i32,
mut params: &[f32],
) {
let mut interval: f32;
let mut a: f32;
@ -185,42 +181,43 @@ pub unsafe extern "C" fn compute_curve_gamma_table_type_parametric(
let mut c: f32;
let mut e: f32;
let mut f: f32;
let mut y: f32 = *parameter.offset(0isize);
if count == 0 {
let mut y: f32 = params[0];
// XXX: this could probably be cleaner with slice patterns
if params.len() == 1 {
a = 1.;
b = 0.;
c = 0.;
e = 0.;
f = 0.;
interval = -1.
} else if count == 1 {
a = *parameter.offset(1isize);
b = *parameter.offset(2isize);
} else if params.len() == 3 {
a = params[1];
b = params[2];
c = 0.;
e = 0.;
f = 0.;
interval = -1. * *parameter.offset(2isize) / *parameter.offset(1isize)
} else if count == 2 {
a = *parameter.offset(1isize);
b = *parameter.offset(2isize);
interval = -1. * params[2] / params[1]
} else if params.len() == 4 {
a = params[1];
b = params[2];
c = 0.;
e = *parameter.offset(3isize);
f = *parameter.offset(3isize);
interval = -1. * *parameter.offset(2isize) / *parameter.offset(1isize)
} else if count == 3 {
a = *parameter.offset(1isize);
b = *parameter.offset(2isize);
c = *parameter.offset(3isize);
e = params[3];
f = params[3];
interval = -1. * params[2] / params[1]
} else if params.len() == 5 {
a = params[1];
b = params[2];
c = params[3];
e = -c;
f = 0.;
interval = *parameter.offset(4isize)
} else if count == 4 {
a = *parameter.offset(1isize);
b = *parameter.offset(2isize);
c = *parameter.offset(3isize);
e = *parameter.offset(5isize) - c;
f = *parameter.offset(6isize);
interval = *parameter.offset(4isize)
interval = params[4]
} else if params.len() == 7 {
a = params[1];
b = params[2];
c = params[3];
e = params[5] - c;
f = params[6];
interval = params[4]
} else {
debug_assert!(false, "invalid parametric function type.");
a = 1.;
@ -256,28 +253,26 @@ pub unsafe extern "C" fn compute_curve_gamma_table_type0(mut gamma_table: *mut f
}
}
#[no_mangle]
pub unsafe extern "C" fn build_input_gamma_table(mut TRC: *mut curveType) -> *mut f32 {
if TRC.is_null() {
return 0 as *mut f32;
}
pub unsafe extern "C" fn build_input_gamma_table(mut TRC: Option<&curveType>) -> *mut f32 {
let TRC = match TRC {
Some(TRC) => TRC,
None => return 0 as *mut f32,
};
let mut gamma_table: *mut f32 = malloc(::std::mem::size_of::<f32>() * 256) as *mut f32;
if !gamma_table.is_null() {
if (*TRC).type_0 == PARAMETRIC_CURVE_TYPE {
compute_curve_gamma_table_type_parametric(
gamma_table,
(*TRC).parameter.as_mut_ptr(),
(*TRC).count as i32,
);
} else if (*TRC).count == 0 {
compute_curve_gamma_table_type0(gamma_table);
} else if (*TRC).count == 1 {
compute_curve_gamma_table_type1(gamma_table, *(*TRC).data.as_mut_ptr().offset(0isize));
} else {
compute_curve_gamma_table_type2(
gamma_table,
(*TRC).data.as_mut_ptr(),
(*TRC).count as i32,
);
match TRC {
curveType::Parametric(params) => {
compute_curve_gamma_table_type_parametric(gamma_table, params)
}
curveType::Curve(data) => {
if data.len() == 0 {
compute_curve_gamma_table_type0(gamma_table);
} else if data.len() == 1 {
compute_curve_gamma_table_type1(gamma_table, data[0]);
} else {
compute_curve_gamma_table_type2(gamma_table, data);
}
}
}
}
return gamma_table;
@ -307,7 +302,7 @@ pub unsafe extern "C" fn build_colorant_matrix(mut p: *mut qcms_profile) -> matr
#[no_mangle]
pub unsafe extern "C" fn lut_inverse_interp16(
mut Value: u16,
mut LutTable: *mut u16,
mut LutTable: *const u16,
mut length: i32,
) -> uint16_fract_t {
let mut l: i32 = 1; // 'int' Give spacing for negative values
@ -413,7 +408,7 @@ which has an maximum error of about 9855 (pixel difference of ~38.346)
For now, we punt the decision of output size to the caller. */
unsafe extern "C" fn invert_lut(
mut table: *mut u16,
mut table: *const u16,
mut length: i32,
mut out_length: i32,
) -> *mut u16 {
@ -464,62 +459,60 @@ pub unsafe extern "C" fn compute_precache_linear(mut output: *mut u8) {
}
}
#[no_mangle]
pub unsafe extern "C" fn compute_precache(mut trc: *mut curveType, mut output: *mut u8) -> bool {
if (*trc).type_0 == PARAMETRIC_CURVE_TYPE {
let mut gamma_table: [f32; 256] = [0.; 256];
let mut gamma_table_uint: [u16; 256] = [0; 256];
pub unsafe extern "C" fn compute_precache(mut trc: &curveType, mut output: *mut u8) -> bool {
match trc {
curveType::Parametric(params) => {
let mut gamma_table: [f32; 256] = [0.; 256];
let mut gamma_table_uint: [u16; 256] = [0; 256];
let mut inverted_size: i32 = 256;
compute_curve_gamma_table_type_parametric(
gamma_table.as_mut_ptr(),
(*trc).parameter.as_mut_ptr(),
(*trc).count as i32,
);
let mut i: u16 = 0u16;
while (i as i32) < 256 {
gamma_table_uint[i as usize] = (gamma_table[i as usize] * 65535f32) as u16;
i = i + 1
let mut inverted_size: i32 = 256;
compute_curve_gamma_table_type_parametric(gamma_table.as_mut_ptr(), params);
let mut i: u16 = 0u16;
while (i as i32) < 256 {
gamma_table_uint[i as usize] = (gamma_table[i as usize] * 65535f32) as u16;
i = i + 1
}
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, howeve r it is what lcms uses.
// the maximum number we would need is 65535 because that's the
// accuracy used for computing the pre cache table
if inverted_size < 256 {
inverted_size = 256
}
let mut inverted: *mut u16 =
invert_lut(gamma_table_uint.as_mut_ptr(), 256, inverted_size);
if inverted.is_null() {
return false;
}
compute_precache_lut(output, inverted, inverted_size);
free(inverted as *mut libc::c_void);
}
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, howeve r it is what lcms uses.
// the maximum number we would need is 65535 because that's the
// accuracy used for computing the pre cache table
if inverted_size < 256 {
inverted_size = 256
curveType::Curve(data) => {
if data.len() == 0 {
compute_precache_linear(output);
} else if data.len() == 1 {
compute_precache_pow(
output,
(1.0f64 / u8Fixed8Number_to_float(data[0]) as f64) as f32,
);
} else {
let mut inverted_size_0: i32 = data.len() as i32;
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, howeve r it is what lcms uses.
// the maximum number we would need is 65535 because that's the
// accuracy used for computing the pre cache table
if inverted_size_0 < 256 {
inverted_size_0 = 256
} //XXX turn this conversion into a function
let mut inverted_0: *mut u16 =
invert_lut(data.as_ptr(), data.len() as i32, inverted_size_0);
if inverted_0.is_null() {
return false;
}
compute_precache_lut(output, inverted_0, inverted_size_0);
free(inverted_0 as *mut libc::c_void);
}
}
let mut inverted: *mut u16 = invert_lut(gamma_table_uint.as_mut_ptr(), 256, inverted_size);
if inverted.is_null() {
return false;
}
compute_precache_lut(output, inverted, inverted_size);
free(inverted as *mut libc::c_void);
} else if (*trc).count == 0 {
compute_precache_linear(output);
} else if (*trc).count == 1 {
compute_precache_pow(
output,
(1.0f64 / u8Fixed8Number_to_float(*(*trc).data.as_mut_ptr().offset(0isize)) as f64)
as f32,
);
} else {
let mut inverted_size_0: i32 = (*trc).count as i32;
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, howeve r it is what lcms uses.
// the maximum number we would need is 65535 because that's the
// accuracy used for computing the pre cache table
if inverted_size_0 < 256 {
inverted_size_0 = 256
} //XXX turn this conversion into a function
let mut inverted_0: *mut u16 = invert_lut(
(*trc).data.as_mut_ptr(),
(*trc).count as i32,
inverted_size_0,
);
if inverted_0.is_null() {
return false;
}
compute_precache_lut(output, inverted_0, inverted_size_0);
free(inverted_0 as *mut libc::c_void);
}
return true;
}
@ -555,50 +548,49 @@ unsafe extern "C" fn build_pow_table(mut gamma: f32, mut length: i32) -> *mut u1
#[no_mangle]
pub unsafe extern "C" fn build_output_lut(
mut trc: *mut curveType,
mut trc: &curveType,
mut output_gamma_lut: *mut *mut u16,
mut output_gamma_lut_length: *mut usize,
) {
if (*trc).type_0 == PARAMETRIC_CURVE_TYPE {
let mut gamma_table: [f32; 256] = [0.; 256];
match trc {
curveType::Parametric(params) => {
let mut gamma_table: [f32; 256] = [0.; 256];
let mut output: *mut u16 = malloc(::std::mem::size_of::<u16>() * 256) as *mut u16;
if output.is_null() {
*output_gamma_lut = 0 as *mut u16;
return;
let mut output: *mut u16 = malloc(::std::mem::size_of::<u16>() * 256) as *mut u16;
if output.is_null() {
*output_gamma_lut = 0 as *mut u16;
return;
}
compute_curve_gamma_table_type_parametric(gamma_table.as_mut_ptr(), params);
*output_gamma_lut_length = 256;
let mut i: u16 = 0u16;
while (i as i32) < 256 {
*output.offset(i as isize) = (gamma_table[i as usize] * 65535f32) as u16;
i = i + 1
}
*output_gamma_lut = output
}
compute_curve_gamma_table_type_parametric(
gamma_table.as_mut_ptr(),
(*trc).parameter.as_mut_ptr(),
(*trc).count as i32,
);
*output_gamma_lut_length = 256;
let mut i: u16 = 0u16;
while (i as i32) < 256 {
*output.offset(i as isize) = (gamma_table[i as usize] * 65535f32) as u16;
i = i + 1
curveType::Curve(data) => {
if data.len() == 0 {
*output_gamma_lut = build_linear_table(4096);
*output_gamma_lut_length = 4096
} else if data.len() == 1 {
let mut gamma: f32 = (1.0f64 / u8Fixed8Number_to_float(data[0]) as f64) as f32;
*output_gamma_lut = build_pow_table(gamma, 4096);
*output_gamma_lut_length = 4096
} else {
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, however it is what lcms uses.
*output_gamma_lut_length = data.len();
if *output_gamma_lut_length < 256 {
*output_gamma_lut_length = 256
}
*output_gamma_lut = invert_lut(
data.as_ptr(),
data.len() as i32,
*output_gamma_lut_length as i32,
)
}
}
*output_gamma_lut = output
} else if (*trc).count == 0 {
*output_gamma_lut = build_linear_table(4096);
*output_gamma_lut_length = 4096
} else if (*trc).count == 1 {
let mut gamma: f32 = (1.0f64
/ u8Fixed8Number_to_float(*(*trc).data.as_mut_ptr().offset(0isize)) as f64)
as f32;
*output_gamma_lut = build_pow_table(gamma, 4096);
*output_gamma_lut_length = 4096
} else {
//XXX: the choice of a minimum of 256 here is not backed by any theory,
// measurement or data, however it is what lcms uses.
*output_gamma_lut_length = (*trc).count as usize;
if *output_gamma_lut_length < 256 {
*output_gamma_lut_length = 256
}
*output_gamma_lut = invert_lut(
(*trc).data.as_mut_ptr(),
(*trc).count as i32,
*output_gamma_lut_length as i32,
)
};
}
}