From 7ec90142c2cf63e99fb6d9f0993ddf6a30addf12 Mon Sep 17 00:00:00 2001 From: Marti Maria Date: Tue, 20 Sep 2022 17:46:04 +0200 Subject: Added a faster 32-bit float to 32-bit float RGB to Lab conversion Another special case --- plugins/fast_float/src/fast_float_tethra.c | 21 +++- plugins/fast_float/testbed/fast_float_testbed.c | 128 ++++++++++++++++-------- 2 files changed, 107 insertions(+), 42 deletions(-) (limited to 'plugins') diff --git a/plugins/fast_float/src/fast_float_tethra.c b/plugins/fast_float/src/fast_float_tethra.c index ef4fccf..64e011a 100644 --- a/plugins/fast_float/src/fast_float_tethra.c +++ b/plugins/fast_float/src/fast_float_tethra.c @@ -254,10 +254,9 @@ cmsBool OptimizeCLUTRGBTransform(_cmsTransform2Fn* TransformFn, if (T_BYTES(*InputFormat) != sizeof(cmsFloat32Number) || T_BYTES(*OutputFormat) != sizeof(cmsFloat32Number)) return FALSE; - // Input has to be RGB, Output may be any but Lab + // Input has to be RGB if (T_COLORSPACE(*InputFormat) != PT_RGB) return FALSE; - if (T_COLORSPACE(*OutputFormat) == PT_Lab) return FALSE; - + OriginalLut = *Lut; ContextID = cmsGetPipelineContextID(OriginalLut); @@ -286,6 +285,22 @@ cmsBool OptimizeCLUTRGBTransform(_cmsTransform2Fn* TransformFn, cmsPipelineInsertStage(OriginalLut, cmsAT_END, percent); } + else + // If output is Lab, add a conversion stage to get Lab values + if (T_COLORSPACE(*OutputFormat) == PT_Lab) { + + static const cmsFloat64Number mat[] = { 100.0, 0, 0, + 0, 255.0, 0, + 0, 0, 255.0 }; + + static const cmsFloat64Number off[] = { 0, -128.0, -128.0 }; + + cmsStage* lab_fix = cmsStageAllocMatrix(ContextID, 3, 3, mat, off); + if (lab_fix == NULL) goto Error; + + cmsPipelineInsertStage(OriginalLut, cmsAT_END, lab_fix); + } + // Resample the LUT if (!cmsStageSampleCLutFloat(OptimizedCLUTmpe, XFormSampler, (void*)OriginalLut, 0)) goto Error; diff --git a/plugins/fast_float/testbed/fast_float_testbed.c b/plugins/fast_float/testbed/fast_float_testbed.c index b501151..f07c885 100644 --- a/plugins/fast_float/testbed/fast_float_testbed.c +++ b/plugins/fast_float/testbed/fast_float_testbed.c @@ -725,6 +725,55 @@ void CheckToFloatLab(void) } + + +static +void CheckFloatToFloatLab(void) +{ + cmsContext Plugin = cmsCreateContext(cmsFastFloatExtensions(), NULL); + cmsContext Raw = cmsCreateContext(NULL, NULL); + + cmsHPROFILE hsRGB = cmsCreate_sRGBProfile(); + cmsHPROFILE hLab = cmsCreateLab4Profile(NULL); + + cmsHTRANSFORM xform_plugin = cmsCreateTransformTHR(Plugin, hsRGB, TYPE_RGB_FLT, hLab, TYPE_Lab_FLT, INTENT_PERCEPTUAL, 0); + cmsHTRANSFORM xform = cmsCreateTransformTHR(Raw, hsRGB, TYPE_RGB_FLT, hLab, TYPE_Lab_FLT, INTENT_PERCEPTUAL, 0); + + int r, g, b; + cmsCIELab Lab1, Lab2; + cmsFloat32Number rgb[3]; + cmsFloat32Number Lab[3]; + double err; + + + for (r = 0; r < 256; r += 10) + for (g = 0; g < 256; g += 10) + for (b = 0; b < 256; b += 10) + { + rgb[0] = (cmsFloat32Number)r / 255.0f; + rgb[1] = (cmsFloat32Number)g / 255.0f; + rgb[2] = (cmsFloat32Number)b / 255.0f; + + cmsDoTransform(xform_plugin, rgb, Lab, 1); + Lab1.L = Lab[0]; Lab1.a = Lab[1]; Lab1.b = Lab[2]; + cmsDoTransform(xform, rgb, Lab, 1); + Lab2.L = Lab[0]; Lab2.a = Lab[1]; Lab2.b = Lab[2]; + + err = cmsDeltaE(&Lab1, &Lab2); + if (err > 0.5) + { + trace("Error on lab encoded (%f, %f, %f) <> (% f, % f, % f)\n", + Lab1.L, Lab1.a, Lab1.b, Lab2.L, Lab2.a, Lab2.b); + } + } + + + cmsDeleteTransform(xform); cmsDeleteTransform(xform_plugin); + cmsCloseProfile(hsRGB); cmsCloseProfile(hLab); + cmsDeleteContext(Raw); + cmsDeleteContext(Plugin); + +} // -------------------------------------------------------------------------------------------------- // A C C U R A C Y C H E C K S // -------------------------------------------------------------------------------------------------- @@ -1093,45 +1142,46 @@ void CheckLab2Roundtrip(void) static void CheckConversionFloat(void) { - trace("Crash test."); - TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, FALSE); - - trace(".."); - TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, TRUE); - trace("Ok\n"); - - trace("Crash (II) test."); - TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, FALSE); - trace(".."); - TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, TRUE); - trace("Ok\n"); - - trace("Crash (III) test."); - CheckUncommonValues(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL); - trace(".."); - CheckUncommonValues(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); - trace("Ok\n"); - - trace("Checking conversion to Lab..."); - CheckToEncodedLab(); - CheckToFloatLab(); - trace("Ok\n"); - - // Matrix-shaper should be accurate - trace("Checking accuracy on Matrix-shaper..."); - TryAllValuesFloat(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); - trace("Ok\n"); - - // CLUT should be as 16 bits or better - trace("Checking accuracy of CLUT..."); - TryAllValuesFloatVs16(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL); - trace("Ok\n"); - - // Same profile should give same values (we test both methods) - trace("Checking accuracy on same profile ..."); - TryAllValuesFloatVs16(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); - TryAllValuesFloat(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); - trace("Ok\n"); + trace("Crash test."); + TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, FALSE); + + trace(".."); + TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, TRUE); + trace("Ok\n"); + + trace("Crash (II) test."); + TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, FALSE); + trace(".."); + TryAllValuesFloatAlpha(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL, TRUE); + trace("Ok\n"); + + trace("Crash (III) test."); + CheckUncommonValues(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL); + trace(".."); + CheckUncommonValues(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); + trace("Ok\n"); + + trace("Checking conversion to Lab..."); + CheckToEncodedLab(); + CheckToFloatLab(); + CheckFloatToFloatLab(); + trace("Ok\n"); + + // Matrix-shaper should be accurate + trace("Checking accuracy on Matrix-shaper..."); + TryAllValuesFloat(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); + trace("Ok\n"); + + // CLUT should be as 16 bits or better + trace("Checking accuracy of CLUT..."); + TryAllValuesFloatVs16(cmsOpenProfileFromFile("test5.icc", "r"), cmsOpenProfileFromFile("test3.icc", "r"), INTENT_PERCEPTUAL); + trace("Ok\n"); + + // Same profile should give same values (we test both methods) + trace("Checking accuracy on same profile ..."); + TryAllValuesFloatVs16(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); + TryAllValuesFloat(cmsOpenProfileFromFile("test0.icc", "r"), cmsOpenProfileFromFile("test0.icc", "r"), INTENT_PERCEPTUAL); + trace("Ok\n"); } -- cgit v1.2.3