mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
5 changed files with 168 additions and 106 deletions
@ -1,31 +0,0 @@ |
|||||
// Copyright (c) Six Labors.
|
|
||||
// Licensed under the Six Labors Split License.
|
|
||||
|
|
||||
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; |
|
||||
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Spectral converter for YCbCr TIFF's which use the JPEG compression.
|
|
||||
/// The jpeg data should be always treated as RGB color space.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
|
|
||||
internal sealed class RgbJpegSpectralConverter<TPixel> : SpectralConverter<TPixel> |
|
||||
where TPixel : unmanaged, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="RgbJpegSpectralConverter{TPixel}"/> class.
|
|
||||
/// This Spectral converter will always convert the pixel data to RGB color.
|
|
||||
/// </summary>
|
|
||||
/// <param name="configuration">The configuration.</param>
|
|
||||
public RgbJpegSpectralConverter(Configuration configuration) |
|
||||
: base(configuration) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override JpegColorConverterBase GetColorConverter(JpegFrame frame, IRawJpegData jpegData) => JpegColorConverterBase.GetConverter(JpegColorSpace.RGB, frame.Precision); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,50 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; |
||||
|
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; |
||||
|
using SixLabors.ImageSharp.Formats.Tiff.Constants; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Spectral converter for YCbCr TIFF's which use the JPEG compression.
|
||||
|
/// The jpeg data should be always treated as RGB color space.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
|
||||
|
internal sealed class TiffJpegSpectralConverter<TPixel> : SpectralConverter<TPixel> |
||||
|
where TPixel : unmanaged, IPixel<TPixel> |
||||
|
{ |
||||
|
private readonly TiffPhotometricInterpretation photometricInterpretation; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="TiffJpegSpectralConverter{TPixel}"/> class.
|
||||
|
/// This Spectral converter will always convert the pixel data to RGB color.
|
||||
|
/// </summary>
|
||||
|
/// <param name="configuration">The configuration.</param>
|
||||
|
/// <param name="photometricInterpretation">Tiff photometric interpretation.</param>
|
||||
|
public TiffJpegSpectralConverter(Configuration configuration, TiffPhotometricInterpretation photometricInterpretation) |
||||
|
: base(configuration) |
||||
|
=> this.photometricInterpretation = photometricInterpretation; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override JpegColorConverterBase GetColorConverter(JpegFrame frame, IRawJpegData jpegData) |
||||
|
{ |
||||
|
JpegColorSpace colorSpace = GetJpegColorSpaceFromPhotometricInterpretation(this.photometricInterpretation); |
||||
|
return JpegColorConverterBase.GetConverter(colorSpace, frame.Precision); |
||||
|
} |
||||
|
|
||||
|
/// <remarks>
|
||||
|
/// This converter must be used only for RGB and YCbCr color spaces for performance reasons.
|
||||
|
/// For grayscale images <see cref="GrayJpegSpectralConverter{TPixel}"/> must be used.
|
||||
|
/// </remarks>
|
||||
|
private static JpegColorSpace GetJpegColorSpaceFromPhotometricInterpretation(TiffPhotometricInterpretation interpretation) |
||||
|
=> interpretation switch |
||||
|
{ |
||||
|
TiffPhotometricInterpretation.Rgb => JpegColorSpace.RGB, |
||||
|
TiffPhotometricInterpretation.YCbCr => JpegColorSpace.RGB, |
||||
|
_ => throw new InvalidImageContentException($"Invalid tiff photometric interpretation for jpeg encoding: {interpretation}"), |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using SixLabors.ImageSharp.Formats.Jpeg; |
||||
|
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; |
||||
|
using SixLabors.ImageSharp.IO; |
||||
|
using SixLabors.ImageSharp.Memory; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; |
||||
|
using SixLabors.ImageSharp.Tests.TestUtilities; |
||||
|
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
||||
|
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; |
||||
|
using Xunit; |
||||
|
using Xunit.Abstractions; |
||||
|
|
||||
|
// ReSharper disable InconsistentNaming
|
||||
|
namespace SixLabors.ImageSharp.Tests.Formats.Jpg |
||||
|
{ |
||||
|
[Trait("Format", "Jpg")] |
||||
|
public partial class JpegDecoderTests |
||||
|
{ |
||||
|
[Theory] |
||||
|
[InlineData(1, 0, JpegColorSpace.Grayscale)] |
||||
|
[InlineData(3, JpegConstants.Adobe.ColorTransformUnknown, JpegColorSpace.RGB)] |
||||
|
[InlineData(3, JpegConstants.Adobe.ColorTransformYCbCr, JpegColorSpace.YCbCr)] |
||||
|
[InlineData(4, JpegConstants.Adobe.ColorTransformUnknown, JpegColorSpace.Cmyk)] |
||||
|
[InlineData(4, JpegConstants.Adobe.ColorTransformYcck, JpegColorSpace.Ycck)] |
||||
|
internal void DeduceJpegColorSpaceAdobeMarker_ShouldReturnValidColorSpace(byte componentCount, byte adobeFlag, JpegColorSpace expectedColorSpace) |
||||
|
{ |
||||
|
byte[] adobeMarkerPayload = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, adobeFlag }; |
||||
|
ProfileResolver.AdobeMarker.CopyTo(adobeMarkerPayload); |
||||
|
_ = AdobeMarker.TryParse(adobeMarkerPayload, out AdobeMarker adobeMarker); |
||||
|
|
||||
|
JpegColorSpace actualColorSpace = JpegDecoderCore.DeduceJpegColorSpace(componentCount, ref adobeMarker); |
||||
|
|
||||
|
Assert.Equal(expectedColorSpace, actualColorSpace); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(2)] |
||||
|
[InlineData(5)] |
||||
|
public void DeduceJpegColorSpaceAdobeMarker_ShouldThrowOnUnsupportedComponentCount(byte componentCount) |
||||
|
{ |
||||
|
AdobeMarker adobeMarker = default; |
||||
|
|
||||
|
Assert.Throws<NotSupportedException>(() => JpegDecoderCore.DeduceJpegColorSpace(componentCount, ref adobeMarker)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(1, JpegColorSpace.Grayscale)] |
||||
|
[InlineData(3, JpegColorSpace.YCbCr)] |
||||
|
[InlineData(4, JpegColorSpace.Cmyk)] |
||||
|
internal void DeduceJpegColorSpace_ShouldReturnValidColorSpace(byte componentCount, JpegColorSpace expectedColorSpace) |
||||
|
{ |
||||
|
JpegColorSpace actualColorSpace = JpegDecoderCore.DeduceJpegColorSpace(componentCount); |
||||
|
|
||||
|
Assert.Equal(expectedColorSpace, actualColorSpace); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(2)] |
||||
|
[InlineData(5)] |
||||
|
public void DeduceJpegColorSpace_ShouldThrowOnUnsupportedComponentCount(byte componentCount) |
||||
|
=> Assert.Throws<NotSupportedException>(() => JpegDecoderCore.DeduceJpegColorSpace(componentCount)); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue