Browse Source

Fix reader and out of range exception

pull/1567/head
James Jackson-South 4 years ago
parent
commit
54856ff945
  1. 1
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs
  2. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs
  3. 8
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs
  4. 1
      src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs
  5. 21
      src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs
  6. 10
      src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs
  7. 10
      tests/ImageSharp.Tests/Colorspaces/Icc/IccProfileConverterTests.cs

1
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System;
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

21
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs

@ -1,15 +1,14 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
internal class LutCalculator : ISingleCalculator internal class LutCalculator : ISingleCalculator
{ {
private float[] lut; private readonly float[] lut;
private bool inverse; private readonly bool inverse;
public LutCalculator(float[] lut, bool inverse) public LutCalculator(float[] lut, bool inverse)
{ {
@ -25,10 +24,8 @@ internal class LutCalculator : ISingleCalculator
{ {
return this.LookupInverse(value); return this.LookupInverse(value);
} }
else
{ return this.Lookup(value);
return this.Lookup(value);
}
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -37,7 +34,13 @@ internal class LutCalculator : ISingleCalculator
float factor = value * (this.lut.Length - 1); float factor = value * (this.lut.Length - 1);
int index = (int)factor; int index = (int)factor;
float low = this.lut[index]; float low = this.lut[index];
float high = this.lut[index + 1];
float high = 1F;
if (index < this.lut.Length - 1)
{
high = this.lut[index + 1];
}
return low + ((high - low) * (factor - index)); return low + ((high - low) * (factor - index));
} }

8
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs

@ -22,8 +22,7 @@ internal abstract partial class IccConverterBase
/// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available</param> /// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available</param>
protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent) protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent)
{ {
ConversionMethod method = GetConversionMethod(profile, renderingIntent); switch (GetConversionMethod(profile, renderingIntent))
switch (method)
{ {
case ConversionMethod.D0: case ConversionMethod.D0:
this.calculator = toPcs ? this.calculator = toPcs ?
@ -83,8 +82,7 @@ internal abstract partial class IccConverterBase
private static IVector4Calculator InitA(IccProfile profile, IccProfileTag tag) private static IVector4Calculator InitA(IccProfile profile, IccProfileTag tag)
{ {
IccTagDataEntry entry = GetTag(profile, tag); switch (GetTag(profile, tag))
switch (entry)
{ {
case IccLut8TagDataEntry lut8: case IccLut8TagDataEntry lut8:
return new LutEntryCalculator(lut8); return new LutEntryCalculator(lut8);
@ -96,6 +94,8 @@ internal abstract partial class IccConverterBase
return new LutABCalculator(lutBtoA); return new LutABCalculator(lutBtoA);
default: default:
// TODO: This is where we likely return a matrix calculator.
throw new InvalidIccProfileException("Invalid entry."); throw new InvalidIccProfileException("Invalid entry.");
} }
} }

1
src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs

@ -206,7 +206,6 @@ public sealed class IccProfile : IDeepCloneable<IccProfile>
return; return;
} }
IccReader reader = new();
this.entries = IccReader.ReadTagData(this.data); this.entries = IccReader.ReadTagData(this.data);
} }
} }

21
src/ImageSharp/Metadata/Profiles/ICC/IccReader.cs

@ -83,28 +83,19 @@ internal sealed class IccReader
{ {
IccTagTableEntry[] tagTable = ReadTagTable(reader); IccTagTableEntry[] tagTable = ReadTagTable(reader);
List<IccTagDataEntry> entries = new(tagTable.Length); List<IccTagDataEntry> entries = new(tagTable.Length);
Dictionary<uint, IccTagDataEntry> store = new();
foreach (IccTagTableEntry tag in tagTable) foreach (IccTagTableEntry tag in tagTable)
{ {
IccTagDataEntry entry; IccTagDataEntry entry;
if (store.ContainsKey(tag.Offset))
try
{ {
entry = store[tag.Offset]; entry = reader.ReadTagDataEntry(tag);
} }
else catch
{ {
try // Ignore tags that could not be read
{ continue;
entry = reader.ReadTagDataEntry(tag);
}
catch
{
// Ignore tags that could not be read
continue;
}
store.Add(tag.Offset, entry);
} }
entry.TagSignature = tag.Signature; entry.TagSignature = tag.Signature;

10
src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Metadata.Profiles.Icc; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc;
@ -49,9 +49,7 @@ internal readonly struct IccTagTableEntry : IEquatable<IccTagTableEntry>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false. /// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns> /// </returns>
public static bool operator ==(IccTagTableEntry left, IccTagTableEntry right) public static bool operator ==(IccTagTableEntry left, IccTagTableEntry right)
{ => left.Equals(right);
return left.Equals(right);
}
/// <summary> /// <summary>
/// Compares two <see cref="IccTagTableEntry"/> objects for equality. /// Compares two <see cref="IccTagTableEntry"/> objects for equality.
@ -62,9 +60,7 @@ internal readonly struct IccTagTableEntry : IEquatable<IccTagTableEntry>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false. /// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns> /// </returns>
public static bool operator !=(IccTagTableEntry left, IccTagTableEntry right) public static bool operator !=(IccTagTableEntry left, IccTagTableEntry right)
{ => !left.Equals(right);
return !left.Equals(right);
}
/// <inheritdoc/> /// <inheritdoc/>
public override bool Equals(object obj) => obj is IccTagTableEntry other && this.Equals(other); public override bool Equals(object obj) => obj is IccTagTableEntry other && this.Equals(other);

10
tests/ImageSharp.Tests/Colorspaces/Icc/IccProfileConverterTests.cs

@ -9,16 +9,15 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Tests.Colorspaces.Icc; namespace SixLabors.ImageSharp.Tests.Colorspaces.Icc;
public class IccProfileConverterTests public class IccProfileConverterTests
{ {
private static PngEncoder Encoder = new PngEncoder(); private static readonly PngEncoder Encoder = new();
[Theory] [Theory]
[WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)] [WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24)] [WithFile(TestImages.Jpeg.ICC.AppleRGB, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24)] [WithFile(TestImages.Jpeg.ICC.ColorMatch, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24)] [WithFile(TestImages.Jpeg.ICC.WideRGB, PixelTypes.Rgb24)]
[WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24)]
// [WithFile(TestImages.Jpeg.ICC.SRgb, PixelTypes.Rgb24)] ConverterBase says this is invalid. [WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24)]
// [WithFile(TestImages.Jpeg.ICC.ProPhoto, PixelTypes.Rgb24)] ConverterBase says this is invalid.
public void CanRoundTripProfile<TPixel>(TestImageProvider<TPixel> provider) public void CanRoundTripProfile<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
@ -37,10 +36,9 @@ public class IccProfileConverterTests
Assert.Equal(expected, actual); Assert.Equal(expected, actual);
} }
// TODO: This fails as the base calculator says sRGB is invalid.
[Theory] [Theory]
[WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)] [WithFile(TestImages.Jpeg.ICC.AdobeRgb, PixelTypes.Rgb24)]
public void CanConvertTosRGB<TPixel>(TestImageProvider<TPixel> provider) public void CanConvertToWide<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using Image<TPixel> image = provider.GetImage(); using Image<TPixel> image = provider.GetImage();

Loading…
Cancel
Save