Browse Source

Remove bad code and tests

pull/1567/head
James Jackson-South 1 year ago
parent
commit
e8f9841cd9
  1. 2
      src/ImageSharp/ColorProfiles/ColorProfileConverter.cs
  2. 144
      src/ImageSharp/ColorProfiles/Icc/IccProfileConverter.cs
  3. 3
      src/ImageSharp/Formats/DecoderOptions.cs
  4. 26
      src/ImageSharp/Formats/ImageDecoder.cs
  5. 4
      src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs
  6. 68
      tests/ImageSharp.Tests/ColorProfiles/Icc/IccProfileConverterTests.cs

2
src/ImageSharp/ColorProfiles/ColorProfileConverter.cs

@ -12,7 +12,7 @@ public class ColorProfileConverter
/// Initializes a new instance of the <see cref="ColorProfileConverter"/> class.
/// </summary>
public ColorProfileConverter()
: this(new())
: this(new())
{
}

144
src/ImageSharp/ColorProfiles/Icc/IccProfileConverter.cs

@ -1,144 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.ColorProfiles.Icc;
/// <summary>
/// Allows the conversion between ICC profiles.
/// </summary>
internal static class IccProfileConverter
{
/// <summary>
/// Performs a conversion of the image pixels based on the input and output ICC profiles.
/// </summary>
/// <param name="image">The image to convert.</param>
/// <param name="inputIccProfile">The input ICC profile.</param>
/// <param name="outputIccProfile">The output ICC profile. </param>
public static void Convert(Image image, IccProfile inputIccProfile, IccProfile outputIccProfile)
=> image.AcceptVisitor(new IccProfileConverterVisitor(inputIccProfile, outputIccProfile));
/// <summary>
/// Performs a conversion of the image pixels based on the input and output ICC profiles.
/// </summary>
/// <typeparam name="TPixel">The type of pixel.</typeparam>
/// <param name="image">The image to convert.</param>
/// <param name="inputIccProfile">The input ICC profile.</param>
/// <param name="outputIccProfile">The output ICC profile. </param>
public static void Convert<TPixel>(Image<TPixel> image, IccProfile inputIccProfile, IccProfile outputIccProfile)
where TPixel : unmanaged, IPixel<TPixel>
{
IccDataToPcsConverter converterDataToPcs = new(inputIccProfile);
IccPcsToDataConverter converterPcsToData = new(outputIccProfile);
Configuration configuration = image.Configuration;
image.ProcessPixelRows(accessor =>
{
ColorProfileConverter converter = new(new ColorConversionOptions()
{
SourceWhitePoint = new CieXyz(inputIccProfile.Header.PcsIlluminant),
TargetWhitePoint = new CieXyz(outputIccProfile.Header.PcsIlluminant),
});
// TODO: Our Xxy/Lab conversion are dependent on the version number. We are applying the conversion using V4
// but we should use the correct algorithm per version. This includes Lab/Lab Xyz/Xyz.
using IMemoryOwner<Vector4> vectors = configuration.MemoryAllocator.Allocate<Vector4>(accessor.Width);
Span<Vector4> vectorsSpan = vectors.GetSpan();
// TODO: For debugging - remove.
// It appears we have a scaling problem. The pcs values differ by on average 0.000001.
Span<Vector4> temp = new Vector4[vectorsSpan.Length];
for (int y = 0; y < accessor.Height; y++)
{
Span<TPixel> row = accessor.GetRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(configuration, row, vectorsSpan, PixelConversionModifiers.Scale);
if (inputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieLab &&
outputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieXyz)
{
for (int x = 0; x < vectorsSpan.Length; x++)
{
Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]);
temp[x] = pcs;
pcs = PcsToLab(pcs);
CieLab lab = new(pcs.X, pcs.Y, pcs.Z);
CieXyz xyz = converter.Convert<CieLab, CieXyz>(in lab);
pcs = XyzToPcs(pcs, xyz);
vectorsSpan[x] = converterPcsToData.Calculate(pcs);
}
}
else if (inputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieXyz &&
outputIccProfile.Header.ProfileConnectionSpace == IccColorSpaceType.CieLab)
{
for (int x = 0; x < vectorsSpan.Length; x++)
{
Vector4 pcs = converterDataToPcs.Calculate(vectorsSpan[x]);
CieXyz xyz = new(pcs.X, pcs.Y, pcs.Z);
CieLab lab = converter.Convert<CieXyz, CieLab>(in xyz);
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<TPixel>.Instance.FromVector4Destructive(configuration, vectorsSpan, row, PixelConversionModifiers.Scale);
}
});
image.Metadata.IccProfile = outputIccProfile;
}
private static unsafe Vector4 PcsToLab(Vector4 input)
{
Vector3* v = (Vector3*)&input;
v[0] *= new Vector3(100f, 255, 255);
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 static unsafe Vector4 XyzToPcs(Vector4 input, CieXyz xyz)
{
Vector3* v = (Vector3*)&input;
v[0] = xyz.ToVector3();
v[0] *= 32768 / 65535f;
return input;
}
private readonly struct IccProfileConverterVisitor : IImageVisitor
{
private readonly IccProfile inputIccProfile;
private readonly IccProfile outputIccProfile;
public IccProfileConverterVisitor(IccProfile inputIccProfile, IccProfile outputIccProfile)
{
this.inputIccProfile = inputIccProfile;
this.outputIccProfile = outputIccProfile;
}
public void Visit<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel> => Convert(image, this.inputIccProfile, this.outputIccProfile);
}
}

3
src/ImageSharp/Formats/DecoderOptions.cs

@ -62,8 +62,9 @@ public sealed class DecoderOptions
/// <summary>
/// Gets a value that controls how ICC profiles are handled during decode.
/// TODO: Implement this.
/// </summary>
public ColorProfileHandling ColorProfileHandling { get; init; }
internal ColorProfileHandling ColorProfileHandling { get; init; }
internal void SetConfiguration(Configuration configuration) => this.configuration = configuration;
}

26
src/ImageSharp/Formats/ImageDecoder.cs

@ -1,11 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.ColorProfiles.Icc;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@ -26,7 +23,6 @@ public abstract class ImageDecoder : IImageDecoder
stream,
s => this.Decode<TPixel>(options, s, default));
TransformColorProfile(options, image);
this.SetDecoderFormat(options.Configuration, image);
return image;
@ -40,7 +36,6 @@ public abstract class ImageDecoder : IImageDecoder
stream,
s => this.Decode(options, s, default));
TransformColorProfile(options, image);
this.SetDecoderFormat(options.Configuration, image);
return image;
@ -56,7 +51,6 @@ public abstract class ImageDecoder : IImageDecoder
(s, ct) => this.Decode<TPixel>(options, s, ct),
cancellationToken).ConfigureAwait(false);
TransformColorProfile(options, image);
this.SetDecoderFormat(options.Configuration, image);
return image;
@ -71,7 +65,6 @@ public abstract class ImageDecoder : IImageDecoder
(s, ct) => this.Decode(options, s, ct),
cancellationToken).ConfigureAwait(false);
TransformColorProfile(options, image);
this.SetDecoderFormat(options.Configuration, image);
return image;
@ -166,25 +159,6 @@ public abstract class ImageDecoder : IImageDecoder
}
}
/// <summary>
/// Converts the decoded image color profile if present to a V4 sRGB profile.
/// </summary>
/// <param name="options">The decoder options.</param>
/// <param name="image">The image.</param>
protected static void TransformColorProfile(DecoderOptions options, Image image)
{
if (options.ColorProfileHandling == ColorProfileHandling.Preserve)
{
return;
}
IccProfile? profile = image.Metadata?.IccProfile;
if (profile is not null)
{
IccProfileConverter.Convert(image, profile, SrgbV4Profile.GetProfile());
}
}
/// <summary>
/// Determines whether the decoded image should be resized.
/// </summary>

4
src/ImageSharp/Formats/SpecializedImageDecoder{T}.cs

@ -23,7 +23,6 @@ public abstract class SpecializedImageDecoder<T> : ImageDecoder, ISpecializedIma
stream,
s => this.Decode<TPixel>(options, s, default));
TransformColorProfile(options.GeneralOptions, image);
this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
return image;
@ -37,7 +36,6 @@ public abstract class SpecializedImageDecoder<T> : ImageDecoder, ISpecializedIma
stream,
s => this.Decode(options, s, default));
TransformColorProfile(options.GeneralOptions, image);
this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
return image;
@ -53,7 +51,6 @@ public abstract class SpecializedImageDecoder<T> : ImageDecoder, ISpecializedIma
(s, ct) => this.Decode<TPixel>(options, s, ct),
cancellationToken).ConfigureAwait(false);
TransformColorProfile(options.GeneralOptions, image);
this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
return image;
@ -68,7 +65,6 @@ public abstract class SpecializedImageDecoder<T> : ImageDecoder, ISpecializedIma
(s, ct) => this.Decode(options, s, ct),
cancellationToken).ConfigureAwait(false);
TransformColorProfile(options.GeneralOptions, image);
this.SetDecoderFormat(options.GeneralOptions.Configuration, image);
return image;

68
tests/ImageSharp.Tests/ColorProfiles/Icc/IccProfileConverterTests.cs

@ -1,68 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.ColorProfiles.Icc;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Metadata.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
namespace SixLabors.ImageSharp.Tests.ColorProfiles.Icc;
public class IccProfileConverterTests
{
private static readonly PngEncoder Encoder = new();
[Theory(Skip = "Skip for now while we refactor the library")]
[WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.CMYK, PixelTypes.Rgb24)]
public void CanRoundTripProfile<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
IccProfile profile = image.Metadata.IccProfile;
TPixel expected = image[0, 0];
IccProfileConverter.Convert(image, profile, profile);
image.DebugSave(provider, extension: "png", appendPixelTypeToFileName: false, appendSourceFileOrDescription: true, encoder: Encoder);
TPixel actual = image[0, 0];
Assert.Equal(expected, actual);
}
[Theory(Skip = "Skip for now while we refactor the library")]
[WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.CMYK, PixelTypes.Rgb24)]
public void CanConvertToSRGB<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using Image<TPixel> image = provider.GetImage();
IccProfile profile = image.Metadata.IccProfile;
IccProfile sRGBProfile = SrgbV4Profile.GetProfile();
IccProfileConverter.Convert(image, profile, sRGBProfile);
Assert.Equal(image.Metadata.IccProfile, sRGBProfile);
image.DebugSave(provider, extension: "png", appendPixelTypeToFileName: false, appendSourceFileOrDescription: true, encoder: Encoder);
// Mac reports a difference of 0.0000%
image.CompareToReferenceOutput(ImageComparer.Tolerant(0.0001F), provider, appendPixelTypeToFileName: false);
}
}
Loading…
Cancel
Save