diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccProfileConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccProfileConverter.cs index 51c34e4c7..632ffa4f0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccProfileConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccProfileConverter.cs @@ -48,10 +48,44 @@ internal static class IccProfileConverter Span row = accessor.GetRowSpan(y); PixelOperations.Instance.ToVector4(configuration, row, vectorsSpan, PixelConversionModifiers.Scale); - for (int x = 0; x < vectorsSpan.Length; x++) + if (inputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieLab + && outputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieXyz) { - Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]); - vectorsSpan[x] = converterPcsToData.Calculate(pcs); + ColorSpaceConverter converter = new(); + for (int x = 0; x < vectorsSpan.Length; x++) + { + Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]); + pcs = PcsToLab(pcs); + CieXyz xyz = converter.ToCieXyz(new CieLab(pcs.X, pcs.Y, pcs.Z, new CieXyz(inputIccProfile.Header.PcsIlluminant))); + pcs = new Vector4(xyz.X, xyz.Y, xyz.Z, pcs.W); + + vectorsSpan[x] = converterPcsToData.Calculate(pcs); + } + } + else if (inputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieXyz + && outputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieLab) + { + Vector3 illuminant = outputIccProfile.Header.PcsIlluminant; + ColorSpaceConverter converter = new(new ColorSpaceConverterOptions() + { + WhitePoint = new(illuminant), + }); + + for (int x = 0; x < vectorsSpan.Length; x++) + { + Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]); + CieLab lab = converter.ToCieLab(new CieXyz(pcs.X, pcs.Y, pcs.Z)); + pcs = LabToPcs(pcs, lab); + vectorsSpan[x] = converterPcsToData.Calculate(pcs); + } + } + else + { + for (int x = 0; x < vectorsSpan.Length; x++) + { + Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]); + vectorsSpan[x] = converterPcsToData.Calculate(pcs); + } } PixelOperations.Instance.FromVector4Destructive(configuration, vectorsSpan, row); @@ -61,6 +95,22 @@ internal static class IccProfileConverter image.Metadata.IccProfile = outputIccProfile; } + private static unsafe Vector4 PcsToLab(Vector4 input) + { + Vector3* v = (Vector3*)&input; + v[0] *= 100F; + v[0] -= new Vector3(0, 128F, 128F); + return input; + } + + private static unsafe Vector4 LabToPcs(Vector4 input, CieLab lab) + { + Vector3* v = (Vector3*)&input; + v[0] = new Vector3(lab.L, lab.A + 128F, lab.B + 128F); + v[0] /= 100F; + return input; + } + private readonly struct IccProfileConverterVisitor : IImageVisitor { private readonly IccProfile inputIccProfile;