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

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

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

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

@ -84,10 +84,10 @@ pub struct qcms_profile {
pub redColorant: XYZNumber, pub redColorant: XYZNumber,
pub blueColorant: XYZNumber, pub blueColorant: XYZNumber,
pub greenColorant: XYZNumber, pub greenColorant: XYZNumber,
pub redTRC: *mut curveType, pub redTRC: Option<Box<curveType>>,
pub blueTRC: *mut curveType, pub blueTRC: Option<Box<curveType>>,
pub greenTRC: *mut curveType, pub greenTRC: Option<Box<curveType>>,
pub grayTRC: *mut curveType, pub grayTRC: Option<Box<curveType>>,
pub A2B0: *mut lutType, pub A2B0: *mut lutType,
pub B2A0: *mut lutType, pub B2A0: *mut lutType,
pub mAB: *mut lutmABType, pub mAB: *mut lutmABType,
@ -122,16 +122,12 @@ impl Drop for qcms_profile {
if !self.mBA.is_null() { if !self.mBA.is_null() {
mAB_release(self.mBA); 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)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Clone)]
pub struct lutmABType { pub struct lutmABType {
pub num_in_channels: u8, pub num_in_channels: u8,
pub num_out_channels: u8, pub num_out_channels: u8,
@ -150,19 +146,17 @@ pub struct lutmABType {
pub e23: s15Fixed16Number, pub e23: s15Fixed16Number,
pub reversed: bool, pub reversed: bool,
pub clut_table: *mut f32, pub clut_table: *mut f32,
pub a_curves: [*mut curveType; 10], pub a_curves: [Option<Box<curveType>>; 10],
pub b_curves: [*mut curveType; 10], pub b_curves: [Option<Box<curveType>>; 10],
pub m_curves: [*mut curveType; 10], pub m_curves: [Option<Box<curveType>>; 10],
pub clut_table_data: [f32; 0], pub clut_table_data: [f32; 0],
} }
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Clone)]
pub struct curveType { pub enum curveType {
pub type_0: u32, Curve(Vec<uInt16Number>),
pub count: u32, Parametric(Vec<f32>),
pub parameter: [f32; 7],
pub data: [uInt16Number; 0],
} }
pub type uInt16Number = u16; 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. // Read the tag at a given offset rather then the tag_index.
// This method is used when reading mAB tags where nested curveType are // This method is used when reading mAB tags where nested curveType are
// present that are not part of the tag_index. // present that are not part of the tag_index.
unsafe extern "C" fn read_curveType( fn read_curveType(
mut src: &mut mem_source, mut src: &mut mem_source,
mut offset: u32, mut offset: u32,
mut len: *mut u32, mut len: &mut u32,
) -> *mut curveType { ) -> Option<Box<curveType>> {
static mut COUNT_TO_LENGTH: [u32; 5] = [1, 3, 4, 5, 7]; //PARAMETRIC_CURVE_TYPE const COUNT_TO_LENGTH: [u32; 5] = [1, 3, 4, 5, 7]; //PARAMETRIC_CURVE_TYPE
let mut curve: *mut curveType; let mut curve: *mut curveType;
let mut type_0: u32 = read_u32(src, offset as usize); let mut type_0: u32 = read_u32(src, offset as usize);
let mut count: u32; let mut count: u32;
let mut i: u32; let mut i: u32;
if type_0 != CURVE_TYPE && type_0 != PARAMETRIC_CURVE_TYPE { if type_0 != CURVE_TYPE && type_0 != PARAMETRIC_CURVE_TYPE {
invalid_source(src, "unexpected type, expected CURV or PARA"); invalid_source(src, "unexpected type, expected CURV or PARA");
return 0 as *mut curveType; return None;
} }
if type_0 == CURVE_TYPE { if type_0 == CURVE_TYPE {
count = read_u32(src, (offset + 8) as usize); count = read_u32(src, (offset + 8) as usize);
//arbitrary //arbitrary
if count > 40000 { if count > 40000 {
invalid_source(src, "curve size too large"); invalid_source(src, "curve size too large");
return 0 as *mut curveType; return None;
} }
curve = malloc( let mut table = Vec::with_capacity(count as usize);
::std::mem::size_of::<curveType>() for i in 0..count {
+ ::std::mem::size_of::<uInt16Number>() * count as usize, table.push(read_u16(src, (offset + 12 + i * 2) as usize));
) as *mut curveType;
if curve.is_null() {
return 0 as *mut curveType;
} }
(*curve).count = count; *len = 12 + count * 2;
(*curve).type_0 = CURVE_TYPE; return Some(Box::new(curveType::Curve(table)));
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
} else { } else {
count = read_u16(src, (offset + 8) as usize) as u32; count = read_u16(src, (offset + 8) as usize) as u32;
if count > 4 { if count > 4 {
invalid_source(src, "parametric function type not supported."); 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; let mut params = Vec::with_capacity(count as usize);
if curve.is_null() { for i in 0..COUNT_TO_LENGTH[count as usize] {
return 0 as *mut curveType; params.push(s15Fixed16Number_to_float(read_s15Fixed16Number(
}
(*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(
src, src,
(offset + 12 + i * 4) as usize, (offset + 12 + i * 4) as usize,
)); )));
i = i + 1
} }
*len = 12 + COUNT_TO_LENGTH[count as usize] * 4; *len = 12 + COUNT_TO_LENGTH[count as usize] * 4;
if count == 1 || count == 2 { if count == 1 || count == 2 {
/* we have a type 1 or type 2 function that has a division by 'a' */ /* 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 { if a == 0.0 {
invalid_source(src, "parametricCurve definition causes division by zero"); 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 src: &mut mem_source,
mut index: &tag_index, mut index: &tag_index,
mut tag_id: u32, mut tag_id: u32,
) -> *mut curveType { ) -> Option<Box<curveType>> {
let mut tag = find_tag(index, tag_id); let mut tag = find_tag(index, tag_id);
let mut curve: *mut curveType = 0 as *mut curveType;
if let Some(tag) = tag { if let Some(tag) = tag {
let mut len: u32 = 0; let mut len: u32 = 0;
return read_curveType(src, (*tag).offset, &mut len); return read_curveType(src, (*tag).offset, &mut len);
} else { } else {
invalid_source(src, "missing curvetag"); invalid_source(src, "missing curvetag");
} }
return curve; return None;
} }
// arbitrary // arbitrary
unsafe extern "C" fn read_nested_curveType( unsafe extern "C" fn read_nested_curveType(
mut src: &mut mem_source, mut src: &mut mem_source,
mut curveArray: *mut [*mut curveType; 10], mut curveArray: *mut [Option<Box<curveType>>; 10],
mut num_channels: u8, mut num_channels: u8,
mut curve_offset: u32, mut curve_offset: u32,
) { ) {
@ -744,7 +720,7 @@ unsafe extern "C" fn read_nested_curveType(
let mut tag_len: u32 = 0; let mut tag_len: u32 = 0;
(*curveArray)[i as usize] = (*curveArray)[i as usize] =
read_curveType(src, curve_offset + channel_offset, &mut tag_len); 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"); invalid_source(src, "invalid nested curveType curve");
break; break;
} else { } else {
@ -761,13 +737,13 @@ unsafe extern "C" fn mAB_release(mut lut: *mut lutmABType) {
let mut i: u8; let mut i: u8;
i = 0u8; i = 0u8;
while (i as i32) < (*lut).num_in_channels as i32 { 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 = i + 1
} }
i = 0u8; i = 0u8;
while (i as i32) < (*lut).num_out_channels as i32 { while (i as i32) < (*lut).num_out_channels as i32 {
free((*lut).b_curves[i as usize] as *mut libc::c_void); (*lut).b_curves[i as usize] = None;
free((*lut).m_curves[i as usize] as *mut libc::c_void); (*lut).m_curves[i as usize] = None;
i = i + 1 i = i + 1
} }
free(lut as *mut libc::c_void); 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; 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 curve: *mut curveType;
let mut i: i32; let mut data = Vec::with_capacity(num_entries as usize);
curve = malloc( for i in 0..num_entries {
::std::mem::size_of::<curveType>() data.push(*table.offset(i as isize));
+ ::std::mem::size_of::<uInt16Number>() * num_entries as usize,
) as *mut curveType;
if curve.is_null() {
return 0 as *mut curveType;
} }
(*curve).type_0 = CURVE_TYPE; return Box::new(curveType::Curve(data));
(*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;
} }
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 { if a > 255.0 + 255.0 / 256f32 {
return 0xffffu16; return 0xffffu16;
} else if a < 0.0 { } 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; 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; fn curve_from_gamma(mut gamma: f32) -> Box<curveType> {
let mut num_entries: i32 = 1; Box::new(curveType::Curve(vec![float_to_u8Fixed8Number(gamma)]))
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;
} }
//XXX: it would be nice if we had a way of ensuring //XXX: it would be nice if we had a way of ensuring
// everything in a profile was initialized regardless of how it was created // 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) { if !set_rgb_colorants(&mut profile, white_point, primaries) {
return 0 as *mut qcms_profile; return 0 as *mut qcms_profile;
} }
(*profile).redTRC = curve_from_gamma(redGamma); (*profile).redTRC = Some(curve_from_gamma(redGamma));
(*profile).blueTRC = curve_from_gamma(blueGamma); (*profile).blueTRC = Some(curve_from_gamma(blueGamma));
(*profile).greenTRC = curve_from_gamma(greenGamma); (*profile).greenTRC = Some(curve_from_gamma(greenGamma));
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 0 as *mut qcms_profile; 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 { pub unsafe extern "C" fn qcms_profile_create_gray_with_gamma(mut gamma: f32) -> *mut qcms_profile {
let mut profile = qcms_profile_create(); let mut profile = qcms_profile_create();
(*profile).grayTRC = curve_from_gamma(gamma); (*profile).grayTRC = Some(curve_from_gamma(gamma));
if (*profile).grayTRC.is_null() { if (*profile).grayTRC.is_none() {
return 0 as *mut qcms_profile; return 0 as *mut qcms_profile;
} }
(*profile).class_type = DISPLAY_DEVICE_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) { if !set_rgb_colorants(&mut profile, white_point, primaries) {
return 0 as *mut qcms_profile; return 0 as *mut qcms_profile;
} }
(*profile).redTRC = curve_from_table(table, num_entries); (*profile).redTRC = Some(curve_from_table(table, num_entries));
(*profile).blueTRC = curve_from_table(table, num_entries); (*profile).blueTRC = Some(curve_from_table(table, num_entries));
(*profile).greenTRC = curve_from_table(table, num_entries); (*profile).greenTRC = Some(curve_from_table(table, num_entries));
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 0 as *mut qcms_profile; 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).redTRC = read_tag_curveType(src, &index, TAG_rTRC);
(*profile).greenTRC = read_tag_curveType(src, &index, TAG_gTRC); (*profile).greenTRC = read_tag_curveType(src, &index, TAG_gTRC);
(*profile).blueTRC = read_tag_curveType(src, &index, TAG_bTRC); (*profile).blueTRC = read_tag_curveType(src, &index, TAG_bTRC);
if (*profile).redTRC.is_null() if (*profile).redTRC.is_none()
|| (*profile).blueTRC.is_null() || (*profile).blueTRC.is_none()
|| (*profile).greenTRC.is_null() || (*profile).greenTRC.is_none()
{ {
return null_mut(); return null_mut();
} }
} }
} else if (*profile).color_space == GRAY_SIGNATURE { } else if (*profile).color_space == GRAY_SIGNATURE {
(*profile).grayTRC = read_tag_curveType(src, &index, TAG_kTRC); (*profile).grayTRC = read_tag_curveType(src, &index, TAG_kTRC);
if (*profile).grayTRC.is_null() { if (*profile).grayTRC.is_none() {
return null_mut(); return null_mut();
} }
} else { } 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 */ /* 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; return;
} }
@ -1194,7 +1194,7 @@ pub unsafe extern "C" fn qcms_profile_precache_output_transform(mut profile: *mu
(*profile).output_table_r = precache_create(); (*profile).output_table_r = precache_create();
if !(*profile).output_table_r.is_null() if !(*profile).output_table_r.is_null()
&& !compute_precache( && !compute_precache(
(*profile).redTRC, (*profile).redTRC.as_deref().unwrap(),
(*(*profile).output_table_r).data.as_mut_ptr(), (*(*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(); (*profile).output_table_g = precache_create();
if !(*profile).output_table_g.is_null() if !(*profile).output_table_g.is_null()
&& !compute_precache( && !compute_precache(
(*profile).greenTRC, (*profile).greenTRC.as_deref().unwrap(),
(*(*profile).output_table_g).data.as_mut_ptr(), (*(*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(); (*profile).output_table_b = precache_create();
if !(*profile).output_table_b.is_null() if !(*profile).output_table_b.is_null()
&& !compute_precache( && !compute_precache(
(*profile).blueTRC, (*profile).blueTRC.as_deref().unwrap(),
(*(*profile).output_table_b).data.as_mut_ptr(), (*(*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_g = precache_reference((*out).output_table_g);
(*transform).output_table_b = precache_reference((*out).output_table_b) (*transform).output_table_b = precache_reference((*out).output_table_b)
} else { } 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); qcms_transform_release(transform);
return 0 as *mut qcms_transform; return 0 as *mut qcms_transform;
} }
build_output_lut( build_output_lut(
(*out).redTRC, (*out).redTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_r, &mut (*transform).output_gamma_lut_r,
&mut (*transform).output_gamma_lut_r_length, &mut (*transform).output_gamma_lut_r_length,
); );
build_output_lut( build_output_lut(
(*out).greenTRC, (*out).greenTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_g, &mut (*transform).output_gamma_lut_g,
&mut (*transform).output_gamma_lut_g_length, &mut (*transform).output_gamma_lut_g_length,
); );
build_output_lut( build_output_lut(
(*out).blueTRC, (*out).blueTRC.as_deref().unwrap(),
&mut (*transform).output_gamma_lut_b, &mut (*transform).output_gamma_lut_b,
&mut (*transform).output_gamma_lut_b_length, &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) (*transform).transform_fn = Some(qcms_transform_data_bgra_out_lut)
} }
//XXX: avoid duplicating tables if we can //XXX: avoid duplicating tables if we can
(*transform).input_gamma_table_r = build_input_gamma_table((*in_0).redTRC); (*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); (*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); (*transform).input_gamma_table_b = build_input_gamma_table((*in_0).blueTRC.as_deref());
if (*transform).input_gamma_table_r.is_null() if (*transform).input_gamma_table_r.is_null()
|| (*transform).input_gamma_table_g.is_null() || (*transform).input_gamma_table_g.is_null()
|| (*transform).input_gamma_table_b.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[1][2] = result_0.m[2][1];
(*transform).matrix[2][2] = result_0.m[2][2] (*transform).matrix[2][2] = result_0.m[2][2]
} else if (*in_0).color_space == 0x47524159 { } 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() { if (*transform).input_gamma_table_gray.is_null() {
qcms_transform_release(transform); qcms_transform_release(transform);
return 0 as *mut qcms_transform; return 0 as *mut qcms_transform;

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

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