mirror of https://github.com/SixLabors/ImageSharp
5 changed files with 177 additions and 64 deletions
@ -0,0 +1,72 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Processing; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorProfiles; |
|||
|
|||
internal static class ColorProfileConverterExtensionsPixelCompatible |
|||
{ |
|||
/// <summary>
|
|||
/// Converts the pixel data of the specified image from the source color profile to the target color profile using
|
|||
/// the provided color profile converter.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This method modifies the source image in place by converting its pixel data according to the
|
|||
/// color profiles specified in the converter. The method does not verify whether the profiles are RGB compatible;
|
|||
/// if they are not, the conversion may produce incorrect results. Ensure that both the source and target ICC
|
|||
/// profiles are set on the converter before calling this method.
|
|||
/// </remarks>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="converter">The color profile converter configured with source and target ICC profiles.</param>
|
|||
/// <param name="source">
|
|||
/// The image whose pixel data will be converted. The conversion is performed in place, modifying the original
|
|||
/// image.
|
|||
/// </param>
|
|||
/// <exception cref="InvalidOperationException">
|
|||
/// Thrown if the converter's source or target ICC profile is not specified.
|
|||
/// </exception>
|
|||
public static void Convert<TPixel>(this ColorProfileConverter converter, Image<TPixel> source) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
// These checks actually take place within the converter, but we want to fail fast here.
|
|||
// Note. we do not check to see whether the profiles themselves are RGB compatible,
|
|||
// if they are not, then the converter will simply produce incorrect results.
|
|||
if (converter.Options.SourceIccProfile is null) |
|||
{ |
|||
throw new InvalidOperationException("Source ICC profile is missing."); |
|||
} |
|||
|
|||
if (converter.Options.TargetIccProfile is null) |
|||
{ |
|||
throw new InvalidOperationException("Target ICC profile is missing."); |
|||
} |
|||
|
|||
// Process the rows in parallel chnks, the converter itself is thread safe.
|
|||
source.Mutate(o => o.ProcessPixelRowsAsVector4( |
|||
row => |
|||
{ |
|||
// Gather and convert the pixels in the row to Rgb.
|
|||
using IMemoryOwner<Rgb> rgbBuffer = converter.Options.MemoryAllocator.Allocate<Rgb>(row.Length); |
|||
Span<Rgb> rgbSpan = rgbBuffer.Memory.Span; |
|||
Rgb.FromScaledVector4(row, rgbSpan); |
|||
|
|||
// Perform the actual color conversion.
|
|||
converter.ConvertUsingIccProfile<Rgb, Rgb>(rgbSpan, rgbSpan); |
|||
|
|||
// Copy the converted Rgb pixels back to the row as TPixel.
|
|||
ref Vector4 rowRef = ref MemoryMarshal.GetReference(row); |
|||
for (int i = 0; i < rgbSpan.Length; i++) |
|||
{ |
|||
Vector3 rgb = rgbSpan[i].AsVector3Unsafe(); |
|||
Unsafe.As<Vector4, Vector3>(ref Unsafe.Add(ref rowRef, i)) = rgb; |
|||
} |
|||
}, |
|||
PixelConversionModifiers.Scale)); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue