Bug 1795045 - qcms: Add support for only reading the curves from profiles. r=aosmond

We use this when reading the output profiles to avoid the
performance cost of doing the color transformation using LUTs
when the output profile has them.

This will let us enable ICCv4 everywhere.

Differential Revision: https://phabricator.services.mozilla.com/D159273
This commit is contained in:
Jeff Muizelaar 2022-10-14 19:16:54 +00:00
Родитель 320e015715
Коммит 2091af5f6b
5 изменённых файлов: 37 добавлений и 23 удалений

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

@ -159,6 +159,7 @@ qcms_profile* qcms_profile_create_cicp(uint8_t colour_primaries,
uint8_t transfer_characteristics); uint8_t transfer_characteristics);
qcms_profile* qcms_profile_from_memory(const void *mem, size_t size); qcms_profile* qcms_profile_from_memory(const void *mem, size_t size);
qcms_profile* qcms_profile_from_memory_curves_only(const void *mem, size_t size);
qcms_profile* qcms_profile_from_file(FILE *file); qcms_profile* qcms_profile_from_file(FILE *file);
qcms_profile* qcms_profile_from_path(const char *path); qcms_profile* qcms_profile_from_path(const char *path);

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

@ -79,10 +79,21 @@ pub unsafe extern "C" fn qcms_profile_from_memory(
size: usize, size: usize,
) -> *mut Profile { ) -> *mut Profile {
let mem = slice::from_raw_parts(mem as *const libc::c_uchar, size); let mem = slice::from_raw_parts(mem as *const libc::c_uchar, size);
let profile = Profile::new_from_slice(mem); let profile = Profile::new_from_slice(mem, false);
profile.map_or_else(null_mut, Box::into_raw) profile.map_or_else(null_mut, Box::into_raw)
} }
#[no_mangle]
pub unsafe extern "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] #[no_mangle]
pub extern "C" fn qcms_profile_get_rendering_intent(profile: &Profile) -> Intent { pub extern "C" fn qcms_profile_get_rendering_intent(profile: &Profile) -> Intent {
profile.rendering_intent profile.rendering_intent

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

@ -917,7 +917,7 @@ mod test {
let mut file = std::fs::File::open(path).unwrap(); let mut file = std::fs::File::open(path).unwrap();
let mut data = Vec::new(); let mut data = Vec::new();
file.read_to_end(&mut data).unwrap(); file.read_to_end(&mut data).unwrap();
Profile::new_from_slice(&data).unwrap() Profile::new_from_slice(&data, false).unwrap()
} }
#[test] #[test]

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

@ -22,7 +22,7 @@
use std::{ use std::{
convert::TryInto, convert::TryInto,
sync::atomic::{AtomicBool, Ordering}, sync::atomic::AtomicBool,
sync::Arc, sync::Arc,
}; };
@ -1588,10 +1588,10 @@ impl Profile {
} }
pub fn new_from_path(file: &str) -> Option<Box<Profile>> { pub fn new_from_path(file: &str) -> Option<Box<Profile>> {
Profile::new_from_slice(&std::fs::read(file).ok()?) Profile::new_from_slice(&std::fs::read(file).ok()?, false)
} }
pub fn new_from_slice(mem: &[u8]) -> Option<Box<Profile>> { pub fn new_from_slice(mem: &[u8], curves_only: bool) -> Option<Box<Profile>> {
let length: u32; let length: u32;
let mut source: MemSource = MemSource { let mut source: MemSource = MemSource {
buf: mem, buf: mem,
@ -1645,23 +1645,25 @@ impl Profile {
|| profile.class_type == COLOR_SPACE_PROFILE || profile.class_type == COLOR_SPACE_PROFILE
{ {
if profile.color_space == RGB_SIGNATURE { if profile.color_space == RGB_SIGNATURE {
if let Some(A2B0) = find_tag(&index, TAG_A2B0) { if !curves_only {
let lut_type = read_u32(src, A2B0.offset as usize); if let Some(A2B0) = find_tag(&index, TAG_A2B0) {
if lut_type == LUT8_TYPE || lut_type == LUT16_TYPE { let lut_type = read_u32(src, A2B0.offset as usize);
profile.A2B0 = read_tag_lutType(src, A2B0) if lut_type == LUT8_TYPE || lut_type == LUT16_TYPE {
} else if lut_type == LUT_MAB_TYPE { profile.A2B0 = read_tag_lutType(src, A2B0)
profile.mAB = read_tag_lutmABType(src, A2B0) } else if lut_type == LUT_MAB_TYPE {
profile.mAB = read_tag_lutmABType(src, A2B0)
}
}
if let Some(B2A0) = find_tag(&index, TAG_B2A0) {
let lut_type = read_u32(src, B2A0.offset as usize);
if lut_type == LUT8_TYPE || lut_type == LUT16_TYPE {
profile.B2A0 = read_tag_lutType(src, B2A0)
} else if lut_type == LUT_MBA_TYPE {
profile.mBA = read_tag_lutmABType(src, B2A0)
}
} }
} }
if let Some(B2A0) = find_tag(&index, TAG_B2A0) { if find_tag(&index, TAG_rXYZ).is_some() || curves_only {
let lut_type = read_u32(src, B2A0.offset as usize);
if lut_type == LUT8_TYPE || lut_type == LUT16_TYPE {
profile.B2A0 = read_tag_lutType(src, B2A0)
} else if lut_type == LUT_MBA_TYPE {
profile.mBA = read_tag_lutmABType(src, B2A0)
}
}
if find_tag(&index, TAG_rXYZ).is_some() || !SUPPORTS_ICCV4.load(Ordering::Relaxed) {
profile.redColorant = read_tag_XYZType(src, &index, TAG_rXYZ); profile.redColorant = read_tag_XYZType(src, &index, TAG_rXYZ);
profile.greenColorant = read_tag_XYZType(src, &index, TAG_gXYZ); profile.greenColorant = read_tag_XYZType(src, &index, TAG_gXYZ);
profile.blueColorant = read_tag_XYZType(src, &index, TAG_bXYZ) profile.blueColorant = read_tag_XYZType(src, &index, TAG_bXYZ)
@ -1670,7 +1672,7 @@ impl Profile {
return None; return None;
} }
if find_tag(&index, TAG_rTRC).is_some() || !SUPPORTS_ICCV4.load(Ordering::Relaxed) { if find_tag(&index, TAG_rTRC).is_some() || curves_only {
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);

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

@ -2116,8 +2116,8 @@ void gfxPlatform::InitializeCMS() {
nsTArray<uint8_t> outputProfileData = nsTArray<uint8_t> outputProfileData =
gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData();
if (!outputProfileData.IsEmpty()) { if (!outputProfileData.IsEmpty()) {
gCMSOutputProfile = qcms_profile_from_memory(outputProfileData.Elements(), gCMSOutputProfile = qcms_profile_from_memory_curves_only(outputProfileData.Elements(),
outputProfileData.Length()); outputProfileData.Length());
} }
} }