|
|
@ -5,6 +5,7 @@ using SixLabors.ImageSharp.ColorProfiles; |
|
|
using SixLabors.ImageSharp.ColorProfiles.Icc; |
|
|
using SixLabors.ImageSharp.ColorProfiles.Icc; |
|
|
using SixLabors.ImageSharp.IO; |
|
|
using SixLabors.ImageSharp.IO; |
|
|
using SixLabors.ImageSharp.Memory; |
|
|
using SixLabors.ImageSharp.Memory; |
|
|
|
|
|
using SixLabors.ImageSharp.Metadata; |
|
|
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|
|
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|
|
using SixLabors.ImageSharp.PixelFormats; |
|
|
using SixLabors.ImageSharp.PixelFormats; |
|
|
|
|
|
|
|
|
@ -164,4 +165,56 @@ internal abstract class ImageDecoderCore |
|
|
converter.Convert(image); |
|
|
converter.Convert(image); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Converts the ICC color profile of the specified image frame to the compact sRGB v4 profile if a source profile is
|
|
|
|
|
|
/// available.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// This method should only be used by decoders that gurantee that the encoded image data is in a color space
|
|
|
|
|
|
/// compatible with sRGB (e.g. standard RGB, Adobe RGB, ProPhoto RGB).
|
|
|
|
|
|
/// <br/>
|
|
|
|
|
|
/// If the image does not have a valid ICC profile for color conversion, no changes are made.
|
|
|
|
|
|
/// This operation may affect the color appearance of the image to ensure consistency with the sRGB color
|
|
|
|
|
|
/// space.
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
|
|
|
|
/// <param name="frame">The image frame whose ICC profile will be converted to the compact sRGB v4 profile.</param>
|
|
|
|
|
|
/// <returns>
|
|
|
|
|
|
/// <see langword="true"/> if the conversion was performed; otherwise, <see langword="false"/>.
|
|
|
|
|
|
/// </returns>
|
|
|
|
|
|
protected bool TryConvertIccProfile<TPixel>(ImageFrame<TPixel> frame) |
|
|
|
|
|
where TPixel : unmanaged, IPixel<TPixel> |
|
|
|
|
|
{ |
|
|
|
|
|
if (!this.Options.TryGetIccProfileForColorConversion(frame.Metadata.IccProfile, out IccProfile? profile)) |
|
|
|
|
|
{ |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ColorConversionOptions options = new() |
|
|
|
|
|
{ |
|
|
|
|
|
SourceIccProfile = profile, |
|
|
|
|
|
TargetIccProfile = CompactSrgbV4Profile.Profile, |
|
|
|
|
|
MemoryAllocator = frame.Configuration.MemoryAllocator, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
ColorProfileConverter converter = new(options); |
|
|
|
|
|
|
|
|
|
|
|
ImageMetadata metadata = new() |
|
|
|
|
|
{ |
|
|
|
|
|
IccProfile = frame.Metadata.IccProfile |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
IMemoryGroup<TPixel> m = frame.PixelBuffer.MemoryGroup; |
|
|
|
|
|
|
|
|
|
|
|
// Safe: ToArray only materializes the Memory<TPixel> segment list, not the underlying pixel buffers,
|
|
|
|
|
|
// and Wrap(Memory<T>[]) creates a Consumed MemoryGroup that does not own the buffers (Dispose just
|
|
|
|
|
|
// invalidates the view). This means no pixel data is cloned and disposing the temporary image will
|
|
|
|
|
|
// not dispose or leak the frame's pixel buffer.
|
|
|
|
|
|
MemoryGroup<TPixel> memorySource = MemoryGroup<TPixel>.Wrap(m.ToArray()); |
|
|
|
|
|
|
|
|
|
|
|
using Image<TPixel> image = new(frame.Configuration, memorySource, frame.Width, frame.Height, metadata); |
|
|
|
|
|
converter.Convert(image); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|