//XXX: it would be nice if we had a way of ensuring // everything in a profile was initialized regardless of how it was created //XXX: should this also be taking a black_point? /* similar to CGColorSpaceCreateCalibratedRGB */ #[no_mangle] pubunsafeextern"C"fn qcms_profile_create_rgb_with_gamma_set(
white_point: qcms_CIE_xyY,
primaries: qcms_CIE_xyYTRIPLE,
redGamma: f32,
greenGamma: f32,
blueGamma: f32,
) -> *mut Profile { let profile =
Profile::new_rgb_with_gamma_set(white_point, primaries, redGamma, greenGamma, blueGamma);
profile.map_or_else(null_mut, Box::into_raw)
}
/* qcms_profile_from_memory does not hold a reference to the memory passed in */ #[no_mangle] pubunsafeextern"C"fn qcms_profile_from_memory(
mem: *const libc::c_void,
size: usize,
) -> *mut Profile { let mem = slice::from_raw_parts(mem as *const libc::c_uchar, size); let profile = Profile::new_from_slice(mem, false);
profile.map_or_else(null_mut, Box::into_raw)
}
#[no_mangle] pubunsafeextern"C"fn qcms_profile_from_memory_curves_only(
mem: *const libc::c_void,
size: usize,
) -> *mut Profile { let mem = slice::from_raw_parts(mem as *const libc::c_uchar, size); let profile = Profile::new_from_slice(mem, true);
profile.map_or_else(null_mut, Box::into_raw)
}
#[no_mangle] pubunsafeextern"C"fn qcms_profile_release(profile: *mut Profile) {
drop(Box::from_raw(profile));
} unsafeextern"C"fn qcms_data_from_file(
file: *mut FILE,
mem: *mut *mut libc::c_void,
size: *mut usize,
) { let length: u32; let remaining_length: u32; let read_length: usize; letmut length_be: u32 = 0; let data: *mut libc::c_void;
*mem = std::ptr::null_mut::<libc::c_void>();
*size = 0; if fread(
&mut length_be as *mut u32 as *mut libc::c_void, 1,
::std::mem::size_of::<u32>(),
file,
) != ::std::mem::size_of::<u32>()
{ return;
}
length = u32::from_be(length_be); if length > MAX_PROFILE_SIZE as libc::c_uint
|| (length as libc::c_ulong) < ::std::mem::size_of::<u32>() as libc::c_ulong
{ return;
} /* allocate room for the entire profile */
data = malloc(length as usize); if data.is_null() { return;
} /* copy in length to the front so that the buffer will contain the entire profile */
*(data as *mut u32) = length_be;
remaining_length =
(length as libc::c_ulong - ::std::mem::size_of::<u32>() as libc::c_ulong) as u32; /* read the rest profile */
read_length = fread(
(data as *mut libc::c_uchar).add(::std::mem::size_of::<u32>()) as *mut libc::c_void, 1,
remaining_length as usize,
file,
) as usize; if read_length != remaining_length as usize {
free(data); return;
} /* successfully get the profile.*/
*mem = data;
*size = length as usize;
}
#[no_mangle] pubunsafeextern"C"fn qcms_data_create_rgb_with_gamma(
white_point: qcms_CIE_xyY,
primaries: qcms_CIE_xyYTRIPLE,
gamma: f32,
mem: *mut *mut libc::c_void,
size: *mut usize,
) { let length: u32; letmut index: u32; let xyz_count: u32; let trc_count: u32; letmut tag_table_offset: usize; letmut tag_data_offset: usize; let data: *mut libc::c_void;
let TAG_XYZ: [u32; 3] = [TAG_rXYZ, TAG_gXYZ, TAG_bXYZ]; let TAG_TRC: [u32; 3] = [TAG_rTRC, TAG_gTRC, TAG_bTRC]; if mem.is_null() || size.is_null() { return;
}
*mem = std::ptr::null_mut::<libc::c_void>();
*size = 0; /* *totallength=iccprofileheader(128)+tagcount(4)+ *(tagtableitem(12)*totaltag(6=3rTRC+3rXYZ))+rTRCelementsdata(3*20) *+rXYZelementsdata(3*16),andalltagdataelementsmuststartatthe4-byteboundary.
*/
xyz_count = 3; // rXYZ, gXYZ, bXYZ
trc_count = 3; // rTRC, gTRC, bTRC
length =
(128 + 4) as libc::c_uint + 12 * (xyz_count + trc_count) + xyz_count * 20 + trc_count * 16; // reserve the total memory.
data = malloc(length as usize); if data.is_null() { return;
}
memset(data, 0, length as usize); // Part1 : write rXYZ, gXYZ and bXYZ let colorants = match get_rgb_colorants(white_point, primaries) {
Some(colorants) => colorants,
None => {
free(data); return;
}
};
let data = std::slice::from_raw_parts_mut(data as *mut u8, length as usize); // the position of first tag's signature in tag table
tag_table_offset = (128 + 4) as usize; // the start of tag data elements.
tag_data_offset = ((128 + 4) as libc::c_uint + 12 * (xyz_count + trc_count)) as usize;
index = 0; while index < xyz_count { // tag table
write_u32(data, tag_table_offset, TAG_XYZ[index as usize]); // 20 bytes per TAG_(r/g/b)XYZ tag element
write_u32(data, tag_table_offset + 4, tag_data_offset as u32);
write_u32(data, tag_table_offset + 8, 20); // tag data element
write_u32(data, tag_data_offset, XYZ_TYPE); // reserved 4 bytes.
write_u32(
data,
tag_data_offset + 8,
double_to_s15Fixed16Number(colorants.m[0][index as usize] as f64) as u32,
);
write_u32(
data,
tag_data_offset + 12,
double_to_s15Fixed16Number(colorants.m[1][index as usize] as f64) as u32,
);
write_u32(
data,
tag_data_offset + 16,
double_to_s15Fixed16Number(colorants.m[2][index as usize] as f64) as u32,
);
tag_table_offset += 12;
tag_data_offset += 20;
index += 1
} // Part2 : write rTRC, gTRC and bTRC
index = 0; while index < trc_count { // tag table
write_u32(data, tag_table_offset, TAG_TRC[index as usize]); // 14 bytes per TAG_(r/g/b)TRC element
write_u32(data, tag_table_offset + 4, tag_data_offset as u32);
write_u32(data, tag_table_offset + 8, 14); // tag data element
write_u32(data, tag_data_offset, CURVE_TYPE); // reserved 4 bytes.
write_u32(data, tag_data_offset + 8, 1); // count
write_u16(data, tag_data_offset + 12, float_to_u8Fixed8Number(gamma));
tag_table_offset += 12;
tag_data_offset += 16;
index += 1
} /* Part3 : write profile header * *Importantheaderfieldsareleftempty.Thisgeneratesaprofileforinternaluseonly. *Weshouldbegenerating:Profileversion(04300000h),Profilesignature(acsp), *PCSillumiantfield.Likewisemandatoryprofiletagsareomitted.
*/
write_u32(data, 0, length); // the total length of this memory
write_u32(data, 12, DISPLAY_DEVICE_PROFILE); // profile->class_type
write_u32(data, 16, RGB_SIGNATURE); // profile->color_space
write_u32(data, 20, XYZ_TYPE); // profile->pcs
write_u32(data, 64, Intent::Perceptual as u32); // profile->rendering_intent
write_u32(data, 128, 6); // total tag count // prepare the result
*mem = data.as_mut_ptr() as *mut libc::c_void;
*size = length as usize;
}
#[no_mangle] pubextern"C"fn qcms_profile_get_lut(
profile: &qcms_profile,
channel: qcms_color_channel, // FYI: UB if you give Rust something out of range!
out_begin: *mut f32,
out_end: *mut f32,
) { let out_slice = unsafe {
std::slice::from_raw_parts_mut(out_begin, out_end.offset_from(out_begin) as usize)
};
let trc = match channel {
qcms_color_channel::Red => &profile.redTRC,
qcms_color_channel::Green => &profile.greenTRC,
qcms_color_channel::Blue => &profile.blueTRC,
};
let samples_u16 = iflet Some(trc) = trc { let trc = &*trc; // Yes, sub-optimal, but easier to implement, and these aren't big or hot: // 1. Ask for a new vec<u16> lut based on the trc. // * (eat the extra alloc) // 2. Convert the u16s back out to f32s in our slice. // * (eat the copy and quantization error from f32->u16->f32 roundtrip)
transform_util::build_lut_for_linear_from_tf(trc, Some(out_slice.len()))
} else {
Vec::new()
};
assert_eq!(samples_u16.len(), out_slice.len()); for (d, s) in out_slice.iter_mut().zip(samples_u16.into_iter()) {
*d = (s as f32) / (u16::MAX as f32);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.