Browse Source

add missing ICC V2 types (CRD Info, Screening, UCR/BG)

Device Settings and Named Color are still unsupported
pull/181/head
Johannes Bildstein 9 years ago
parent
commit
d2586b8d8d
  1. 12
      src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs
  2. 83
      src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
  3. 12
      src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs
  4. 92
      src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
  5. 41
      src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningFlag.cs
  6. 53
      src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningSpotType.cs
  7. 35
      src/ImageSharp/MetaData/Profiles/ICC/Enums/IccTypeSignature.cs
  8. 111
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs
  9. 70
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs
  10. 81
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs
  11. 105
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
  12. 11
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs
  13. 33
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs
  14. 12
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs
  15. 36
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs
  16. 27
      tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs
  17. 8
      tests/ImageSharp.Tests/TestDataIcc/IccTestDataPrimitives.cs
  18. 91
      tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs

12
src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs

@ -153,5 +153,17 @@ namespace ImageSharp
pcs2: this.ReadUInt16(),
pcs3: this.ReadUInt16());
}
/// <summary>
/// Reads a screening channel
/// </summary>
/// <returns>the screening channel</returns>
public IccScreeningChannel ReadScreeningChannel()
{
return new IccScreeningChannel(
frequency: this.ReadFix16(),
angle: this.ReadFix16(),
spotShape: (IccScreeningSpotType)this.ReadInt32());
}
}
}

83
src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs

@ -83,10 +83,19 @@ namespace ImageSharp
case IccTypeSignature.Xyz:
return this.ReadXyzTagDataEntry(info.DataSize);
// V2 Type:
// V2 Types:
case IccTypeSignature.TextDescription:
return this.ReadTextDescriptionTagDataEntry();
case IccTypeSignature.CrdInfo:
return this.ReadCrdInfoTagDataEntry();
case IccTypeSignature.Screening:
return this.ReadScreeningTagDataEntry();
case IccTypeSignature.UcrBg:
return this.ReadUcrBgTagDataEntry(info.DataSize);
// Unsupported or unknown
case IccTypeSignature.DeviceSettings:
case IccTypeSignature.NamedColor:
case IccTypeSignature.Unknown:
default:
return this.ReadUnknownTagDataEntry(info.DataSize);
@ -790,5 +799,75 @@ namespace ImageSharp
unicodeLangCode,
scriptcodeCode);
}
/// <summary>
/// Reads a <see cref="IccTextDescriptionTagDataEntry"/>
/// </summary>
/// <returns>The read entry</returns>
public IccCrdInfoTagDataEntry ReadCrdInfoTagDataEntry()
{
uint productNameCount = this.ReadUInt32();
string productName = this.ReadAsciiString((int)productNameCount);
uint crd0Count = this.ReadUInt32();
string crd0Name = this.ReadAsciiString((int)crd0Count);
uint crd1Count = this.ReadUInt32();
string crd1Name = this.ReadAsciiString((int)crd1Count);
uint crd2Count = this.ReadUInt32();
string crd2Name = this.ReadAsciiString((int)crd2Count);
uint crd3Count = this.ReadUInt32();
string crd3Name = this.ReadAsciiString((int)crd3Count);
return new IccCrdInfoTagDataEntry(productName, crd0Name, crd1Name, crd2Name, crd3Name);
}
/// <summary>
/// Reads a <see cref="IccScreeningTagDataEntry"/>
/// </summary>
/// <returns>The read entry</returns>
public IccScreeningTagDataEntry ReadScreeningTagDataEntry()
{
IccScreeningFlag flags = (IccScreeningFlag)this.ReadInt32();
uint channelCount = this.ReadUInt32();
IccScreeningChannel[] channels = new IccScreeningChannel[channelCount];
for (int i = 0; i < channels.Length; i++)
{
channels[i] = this.ReadScreeningChannel();
}
return new IccScreeningTagDataEntry(flags, channels);
}
/// <summary>
/// Reads a <see cref="IccUcrBgTagDataEntry"/>
/// </summary>
/// <param name="size">The size of the entry in bytes</param>
/// <returns>The read entry</returns>
public IccUcrBgTagDataEntry ReadUcrBgTagDataEntry(uint size)
{
uint ucrCount = this.ReadUInt32();
ushort[] ucrCurve = new ushort[ucrCount];
for (int i = 0; i < ucrCurve.Length; i++)
{
ucrCurve[i] = this.ReadUInt16();
}
uint bgCount = this.ReadUInt32();
ushort[] bgCurve = new ushort[bgCount];
for (int i = 0; i < bgCurve.Length; i++)
{
bgCurve[i] = this.ReadUInt16();
}
// ((ucr length + bg length) * UInt16 size) + (ucrCount + bgCount)
uint dataSize = ((ucrCount + bgCount) * 2) + 8;
int descriptionLength = (int)(size - 8 - dataSize); // 8 is the tag header size
string description = this.ReadAsciiString(descriptionLength);
return new IccUcrBgTagDataEntry(ucrCurve, bgCurve, description);
}
}
}

12
src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs

@ -119,5 +119,17 @@ namespace ImageSharp
+ this.WriteTagDataEntryHeader(IccTypeSignature.MultiLocalizedUnicode)
+ this.WriteMultiLocalizedUnicodeTagDataEntry(new IccMultiLocalizedUnicodeTagDataEntry(value.DeviceModelInfo));
}
/// <summary>
/// Writes a screening channel
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteScreeningChannel(IccScreeningChannel value)
{
return this.WriteFix16(value.Frequency)
+ this.WriteFix16(value.Angle)
+ this.WriteInt32((int)value.SpotShape);
}
}
}

92
src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs

@ -121,11 +121,23 @@ namespace ImageSharp
count += this.WriteXyzTagDataEntry(entry as IccXyzTagDataEntry);
break;
// V2 Type:
// V2 Types:
case IccTypeSignature.TextDescription:
count += this.WriteTextDescriptionTagDataEntry(entry as IccTextDescriptionTagDataEntry);
break;
case IccTypeSignature.CrdInfo:
count += this.WriteCrdInfoTagDataEntry(entry as IccCrdInfoTagDataEntry);
break;
case IccTypeSignature.Screening:
count += this.WriteScreeningTagDataEntry(entry as IccScreeningTagDataEntry);
break;
case IccTypeSignature.UcrBg:
count += this.WriteUcrBgTagDataEntry(entry as IccUcrBgTagDataEntry);
break;
// Unsupported or unknown
case IccTypeSignature.DeviceSettings:
case IccTypeSignature.NamedColor:
case IccTypeSignature.Unknown:
default:
count += this.WriteUnknownTagDataEntry(entry as IccUnknownTagDataEntry);
@ -909,5 +921,83 @@ namespace ImageSharp
return count;
}
/// <summary>
/// Writes a <see cref="IccCrdInfoTagDataEntry"/>
/// </summary>
/// <param name="value">The entry to write</param>
/// <returns>The number of bytes written</returns>
public int WriteCrdInfoTagDataEntry(IccCrdInfoTagDataEntry value)
{
int count = 0;
WriteString(value.PostScriptProductName);
WriteString(value.RenderingIntent0Crd);
WriteString(value.RenderingIntent1Crd);
WriteString(value.RenderingIntent2Crd);
WriteString(value.RenderingIntent3Crd);
return count;
void WriteString(string text)
{
int textLength;
if (string.IsNullOrEmpty(text))
{
textLength = 0;
}
else
{
textLength = text.Length + 1; // + 1 for null terminator
}
count += this.WriteUInt32((uint)textLength);
count += this.WriteAsciiString(text, textLength, true);
}
}
/// <summary>
/// Writes a <see cref="IccScreeningTagDataEntry"/>
/// </summary>
/// <param name="value">The entry to write</param>
/// <returns>The number of bytes written</returns>
public int WriteScreeningTagDataEntry(IccScreeningTagDataEntry value)
{
int count = 0;
count += this.WriteInt32((int)value.Flags);
count += this.WriteUInt32((uint)value.Channels.Length);
for (int i = 0; i < value.Channels.Length; i++)
{
count += this.WriteScreeningChannel(value.Channels[i]);
}
return count;
}
/// <summary>
/// Writes a <see cref="IccUcrBgTagDataEntry"/>
/// </summary>
/// <param name="value">The entry to write</param>
/// <returns>The number of bytes written</returns>
public int WriteUcrBgTagDataEntry(IccUcrBgTagDataEntry value)
{
int count = 0;
count += this.WriteUInt32((uint)value.UcrCurve.Length);
for (int i = 0; i < value.UcrCurve.Length; i++)
{
count += this.WriteUInt16(value.UcrCurve[i]);
}
count += this.WriteUInt32((uint)value.BgCurve.Length);
for (int i = 0; i < value.BgCurve.Length; i++)
{
count += this.WriteUInt16(value.BgCurve[i]);
}
count += this.WriteAsciiString(value.Description + '\0');
return count;
}
}
}

41
src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningFlag.cs

@ -0,0 +1,41 @@
// <copyright file="IccScreeningFlag.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
/// <summary>
/// Screening flags. Can be combined with a logical OR.
/// </summary>
[Flags]
internal enum IccScreeningFlag : int
{
/// <summary>
/// No flags (equivalent to NotDefaultScreens and UnitLinesPerCm)
/// </summary>
None = 0,
/// <summary>
/// Use printer default screens
/// </summary>
DefaultScreens = 1 << 0,
/// <summary>
/// Don't use printer default screens
/// </summary>
NotDefaultScreens = 0,
/// <summary>
/// Frequency units in Lines/Inch
/// </summary>
UnitLinesPerInch = 1 << 1,
/// <summary>
/// Frequency units in Lines/cm
/// </summary>
UnitLinesPerCm = 0,
}
}

53
src/ImageSharp/MetaData/Profiles/ICC/Enums/IccScreeningSpotType.cs

@ -0,0 +1,53 @@
// <copyright file="IccScreeningSpotType.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Enumerates the screening spot types
/// </summary>
internal enum IccScreeningSpotType : int
{
/// <summary>
/// Unknown spot type
/// </summary>
Unknown = 0,
/// <summary>
/// Default printer spot type
/// </summary>
PrinterDefault = 1,
/// <summary>
/// Round stop type
/// </summary>
Round = 2,
/// <summary>
/// Diamond spot type
/// </summary>
Diamond = 3,
/// <summary>
/// Ellipse spot type
/// </summary>
Ellipse = 4,
/// <summary>
/// Line spot type
/// </summary>
Line = 5,
/// <summary>
/// Square spot type
/// </summary>
Square = 6,
/// <summary>
/// Cross spot type
/// </summary>
Cross = 7,
}
}

35
src/ImageSharp/MetaData/Profiles/ICC/Enums/IccTypeSignature.cs

@ -229,8 +229,8 @@ namespace ImageSharp
Xyz = 0x58595A20,
/// <summary>
/// The textDescriptionType is a complex structure that contains three types of
/// text description structures: 7-bit ASCII, Unicode and ScriptCode. Since no
/// REMOVED IN V4 - The textDescriptionType is a complex structure that contains three
/// types of text description structures: 7-bit ASCII, Unicode and ScriptCode. Since no
/// single standard method for specifying localizable character sets exists across
/// the major platform vendors, including all three provides access for the major
/// operating systems. The 7-bit ASCII description is to be an invariant,
@ -238,5 +238,36 @@ namespace ImageSharp
/// Unicode and ScriptCode structures be properly localized.
/// </summary>
TextDescription = 0x64657363,
/// <summary>
/// REMOVED IN V4 - This type contains the PostScript product name to which this
/// profile corresponds and the names of the companion CRDs
/// </summary>
CrdInfo = 0x63726469,
/// <summary>
/// REMOVED IN V4 - The screeningType describes various screening parameters including
/// screen frequency, screening angle, and spot shape
/// </summary>
Screening = 0x7363726E,
/// <summary>
/// REMOVED IN V4 - This type contains curves representing the under color removal and
/// black generation and a text string which is a general description of the method
/// used for the UCR and BG
/// </summary>
UcrBg = 0x62666420,
/// <summary>
/// REMOVED IN V4 - This type is an array of structures each of which contains
/// platform-specific information about the settings of the device for which
/// this profile is valid. This type is not supported.
/// </summary>
DeviceSettings = 0x64657673, // not supported
/// <summary>
/// REMOVED IN V2 - use <see cref="NamedColor2"/> instead. This type is not supported.
/// </summary>
NamedColor = 0x6E636F6C, // not supported
}
}

111
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs

@ -0,0 +1,111 @@
// <copyright file="IccCrdInfoTagDataEntry.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
/// <summary>
/// This type contains the PostScript product name to which this profile
/// corresponds and the names of the companion CRDs
/// </summary>
internal sealed class IccCrdInfoTagDataEntry : IccTagDataEntry, IEquatable<IccCrdInfoTagDataEntry>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccCrdInfoTagDataEntry"/> class.
/// </summary>
/// <param name="postScriptProductName">the PostScript product name</param>
/// <param name="renderingIntent0Crd">the rendering intent 0 CRD name</param>
/// <param name="renderingIntent1Crd">the rendering intent 1 CRD name</param>
/// <param name="renderingIntent2Crd">the rendering intent 2 CRD name</param>
/// <param name="renderingIntent3Crd">the rendering intent 3 CRD name</param>
public IccCrdInfoTagDataEntry(
string postScriptProductName,
string renderingIntent0Crd,
string renderingIntent1Crd,
string renderingIntent2Crd,
string renderingIntent3Crd)
: this(
postScriptProductName,
renderingIntent0Crd,
renderingIntent1Crd,
renderingIntent2Crd,
renderingIntent3Crd,
IccProfileTag.Unknown)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="IccCrdInfoTagDataEntry"/> class.
/// </summary>
/// <param name="postScriptProductName">the PostScript product name</param>
/// <param name="renderingIntent0Crd">the rendering intent 0 CRD name</param>
/// <param name="renderingIntent1Crd">the rendering intent 1 CRD name</param>
/// <param name="renderingIntent2Crd">the rendering intent 2 CRD name</param>
/// <param name="renderingIntent3Crd">the rendering intent 3 CRD name</param>
/// <param name="tagSignature">Tag Signature</param>
public IccCrdInfoTagDataEntry(
string postScriptProductName,
string renderingIntent0Crd,
string renderingIntent1Crd,
string renderingIntent2Crd,
string renderingIntent3Crd,
IccProfileTag tagSignature)
: base(IccTypeSignature.CrdInfo, tagSignature)
{
this.PostScriptProductName = postScriptProductName;
this.RenderingIntent0Crd = renderingIntent0Crd;
this.RenderingIntent1Crd = renderingIntent1Crd;
this.RenderingIntent2Crd = renderingIntent2Crd;
this.RenderingIntent3Crd = renderingIntent3Crd;
}
/// <summary>
/// Gets the PostScript product name
/// </summary>
public string PostScriptProductName { get; }
/// <summary>
/// Gets the rendering intent 0 CRD name
/// </summary>
public string RenderingIntent0Crd { get; }
/// <summary>
/// Gets the rendering intent 1 CRD name
/// </summary>
public string RenderingIntent1Crd { get; }
/// <summary>
/// Gets the rendering intent 2 CRD name
/// </summary>
public string RenderingIntent2Crd { get; }
/// <summary>
/// Gets the rendering intent 3 CRD name
/// </summary>
public string RenderingIntent3Crd { get; }
/// <inheritdoc />
public override bool Equals(IccTagDataEntry other)
{
if (base.Equals(other) && other is IccCrdInfoTagDataEntry entry)
{
return this.PostScriptProductName == entry.PostScriptProductName
&& this.RenderingIntent0Crd == entry.RenderingIntent0Crd
&& this.RenderingIntent1Crd == entry.RenderingIntent1Crd
&& this.RenderingIntent2Crd == entry.RenderingIntent2Crd
&& this.RenderingIntent3Crd == entry.RenderingIntent3Crd;
}
return false;
}
/// <inheritdoc />
public bool Equals(IccCrdInfoTagDataEntry other)
{
return this.Equals((IccTagDataEntry)other);
}
}
}

70
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs

@ -0,0 +1,70 @@
// <copyright file="IccScreeningTagDataEntry.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Linq;
/// <summary>
/// This type describes various screening parameters including
/// screen frequency, screening angle, and spot shape.
/// </summary>
internal sealed class IccScreeningTagDataEntry : IccTagDataEntry, IEquatable<IccScreeningTagDataEntry>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccScreeningTagDataEntry"/> class.
/// </summary>
/// <param name="flags">Screening flags</param>
/// <param name="channels">Channel information</param>
public IccScreeningTagDataEntry(IccScreeningFlag flags, IccScreeningChannel[] channels)
: this(flags, channels, IccProfileTag.Unknown)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="IccScreeningTagDataEntry"/> class.
/// </summary>
/// <param name="flags">Screening flags</param>
/// <param name="channels">Channel information</param>
/// <param name="tagSignature">Tag Signature</param>
public IccScreeningTagDataEntry(IccScreeningFlag flags, IccScreeningChannel[] channels, IccProfileTag tagSignature)
: base(IccTypeSignature.Screening, tagSignature)
{
Guard.NotNull(channels, nameof(channels));
this.Flags = flags;
this.Channels = channels;
}
/// <summary>
/// Gets the screening flags
/// </summary>
public IccScreeningFlag Flags { get; }
/// <summary>
/// Gets the channel information
/// </summary>
public IccScreeningChannel[] Channels { get; }
/// <inheritdoc />
public override bool Equals(IccTagDataEntry other)
{
if (base.Equals(other) && other is IccScreeningTagDataEntry entry)
{
return this.Flags == entry.Flags
&& this.Channels.SequenceEqual(entry.Channels);
}
return false;
}
/// <inheritdoc />
public bool Equals(IccScreeningTagDataEntry other)
{
return this.Equals((IccTagDataEntry)other);
}
}
}

81
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs

@ -0,0 +1,81 @@
// <copyright file="IccUcrBgTagDataEntry.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Linq;
/// <summary>
/// This type contains curves representing the under color removal and black generation
/// and a text string which is a general description of the method used for the UCR and BG.
/// </summary>
internal sealed class IccUcrBgTagDataEntry : IccTagDataEntry, IEquatable<IccUcrBgTagDataEntry>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccUcrBgTagDataEntry"/> class.
/// </summary>
/// <param name="ucrCurve">UCR (under color removal) curve values</param>
/// <param name="bgCurve">BG (black generation) curve values</param>
/// <param name="description">Description of the used UCR and BG method</param>
public IccUcrBgTagDataEntry(ushort[] ucrCurve, ushort[] bgCurve, string description)
: this(ucrCurve, bgCurve, description, IccProfileTag.Unknown)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="IccUcrBgTagDataEntry"/> class.
/// </summary>
/// <param name="ucrCurve">UCR (under color removal) curve values</param>
/// <param name="bgCurve">BG (black generation) curve values</param>
/// <param name="description">Description of the used UCR and BG method</param>
/// <param name="tagSignature">Tag Signature</param>
public IccUcrBgTagDataEntry(ushort[] ucrCurve, ushort[] bgCurve, string description, IccProfileTag tagSignature)
: base(IccTypeSignature.UcrBg, tagSignature)
{
Guard.NotNull(ucrCurve, nameof(ucrCurve));
Guard.NotNull(bgCurve, nameof(bgCurve));
Guard.NotNull(description, nameof(description));
this.UcrCurve = ucrCurve;
this.BgCurve = bgCurve;
this.Description = description;
}
/// <summary>
/// Gets the UCR (under color removal) curve values
/// </summary>
public ushort[] UcrCurve { get; }
/// <summary>
/// Gets the BG (black generation) curve values
/// </summary>
public ushort[] BgCurve { get; }
/// <summary>
/// Gets a description of the used UCR and BG method
/// </summary>
public string Description { get; }
/// <inheritdoc />
public override bool Equals(IccTagDataEntry other)
{
if (base.Equals(other) && other is IccUcrBgTagDataEntry entry)
{
return this.Description == entry.Description
&& this.UcrCurve.SequenceEqual(entry.UcrCurve)
&& this.BgCurve.SequenceEqual(entry.BgCurve);
}
return false;
}
/// <inheritdoc />
public bool Equals(IccUcrBgTagDataEntry other)
{
return this.Equals((IccTagDataEntry)other);
}
}
}

105
src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs

@ -0,0 +1,105 @@
// <copyright file="IccScreeningChannel.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
/// <summary>
/// A single channel of a <see cref="IccScreeningTagDataEntry"/>
/// </summary>
internal struct IccScreeningChannel : IEquatable<IccScreeningChannel>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccScreeningChannel"/> struct.
/// </summary>
/// <param name="frequency">Screen frequency</param>
/// <param name="angle">Angle in degrees</param>
/// <param name="spotShape">Spot shape</param>
public IccScreeningChannel(float frequency, float angle, IccScreeningSpotType spotShape)
{
this.Frequency = frequency;
this.Angle = angle;
this.SpotShape = spotShape;
}
/// <summary>
/// Gets the screen frequency
/// </summary>
public float Frequency { get; }
/// <summary>
/// Gets the angle in degrees
/// </summary>
public float Angle { get; }
/// <summary>
/// Gets the spot shape
/// </summary>
public IccScreeningSpotType SpotShape { get; }
/// <summary>
/// Compares two <see cref="IccScreeningChannel"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="IccScreeningChannel"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="IccScreeningChannel"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator ==(IccScreeningChannel left, IccScreeningChannel right)
{
return left.Equals(right);
}
/// <summary>
/// Compares two <see cref="IccScreeningChannel"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="IccScreeningChannel"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="IccScreeningChannel"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator !=(IccScreeningChannel left, IccScreeningChannel right)
{
return !left.Equals(right);
}
/// <inheritdoc/>
public override bool Equals(object other)
{
return (other is IccScreeningChannel) && this.Equals((IccScreeningChannel)other);
}
/// <inheritdoc/>
public bool Equals(IccScreeningChannel other)
{
return this.Frequency == other.Frequency
&& this.Angle == other.Angle
&& this.SpotShape == other.SpotShape;
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
int hashCode = this.Frequency.GetHashCode();
hashCode = (hashCode * 397) ^ this.Angle.GetHashCode();
hashCode = (hashCode * 397) ^ this.SpotShape.GetHashCode();
return hashCode;
}
}
/// <inheritdoc/>
public override string ToString()
{
return $"{this.Frequency}Hz; {this.Angle}°; {this.SpotShape}";
}
}
}

11
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs

@ -110,6 +110,17 @@ namespace ImageSharp.Tests.Icc
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataNonPrimitives.ScreeningChannelTestData), MemberType = typeof(IccTestDataNonPrimitives))]
internal void ReadScreeningChannel(byte[] data, IccScreeningChannel expected)
{
IccDataReader reader = CreateReader(data);
IccScreeningChannel output = reader.ReadScreeningChannel();
Assert.Equal(expected, output);
}
private IccDataReader CreateReader(byte[] data)
{
return new IccDataReader(data);

33
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs

@ -339,6 +339,39 @@ namespace ImageSharp.Tests.Icc
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.CrdInfoTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadCrdInfoTagDataEntry(byte[] data, IccCrdInfoTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccCrdInfoTagDataEntry output = reader.ReadCrdInfoTagDataEntry();
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ScreeningTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadScreeningTagDataEntry(byte[] data, IccScreeningTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccScreeningTagDataEntry output = reader.ReadScreeningTagDataEntry();
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UcrBgTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUcrBgTagDataEntry(byte[] data, IccUcrBgTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccUcrBgTagDataEntry output = reader.ReadUcrBgTagDataEntry(size);
Assert.Equal(expected, output);
}
private IccDataReader CreateReader(byte[] data)
{
return new IccDataReader(data);

12
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs

@ -107,6 +107,18 @@ namespace ImageSharp.Tests.Icc
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataNonPrimitives.ScreeningChannelTestData), MemberType = typeof(IccTestDataNonPrimitives))]
internal void WriteScreeningChannel(byte[] expected, IccScreeningChannel data)
{
IccDataWriter writer = CreateWriter();
writer.WriteScreeningChannel(data);
byte[] output = writer.GetData();
Assert.Equal(expected, output);
}
private IccDataWriter CreateWriter()
{
return new IccDataWriter();

36
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs

@ -369,6 +369,42 @@ namespace ImageSharp.Tests.Icc
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.CrdInfoTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void WriteCrdInfoTagDataEntry(byte[] expected, IccCrdInfoTagDataEntry data)
{
IccDataWriter writer = CreateWriter();
writer.WriteCrdInfoTagDataEntry(data);
byte[] output = writer.GetData();
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ScreeningTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void WriteScreeningTagDataEntry(byte[] expected, IccScreeningTagDataEntry data)
{
IccDataWriter writer = CreateWriter();
writer.WriteScreeningTagDataEntry(data);
byte[] output = writer.GetData();
Assert.Equal(expected, output);
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UcrBgTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void WriteUcrBgTagDataEntry(byte[] expected, IccUcrBgTagDataEntry data, uint size)
{
IccDataWriter writer = CreateWriter();
writer.WriteUcrBgTagDataEntry(data);
byte[] output = writer.GetData();
Assert.Equal(expected, output);
}
private IccDataWriter CreateWriter()
{
return new IccDataWriter();

27
tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs

@ -330,5 +330,32 @@
};
#endregion
#region ScreeningChannel
public static readonly IccScreeningChannel ScreeningChannel_ValRand1 = new IccScreeningChannel(4, 6, IccScreeningSpotType.Cross);
public static readonly IccScreeningChannel ScreeningChannel_ValRand2 = new IccScreeningChannel(8, 5, IccScreeningSpotType.Diamond);
public static readonly byte[] ScreeningChannel_Rand1 = ArrayHelper.Concat
(
IccTestDataPrimitives.Fix16_4,
IccTestDataPrimitives.Fix16_6,
IccTestDataPrimitives.Int32_7
);
public static readonly byte[] ScreeningChannel_Rand2 = ArrayHelper.Concat
(
IccTestDataPrimitives.Fix16_8,
IccTestDataPrimitives.Fix16_5,
IccTestDataPrimitives.Int32_3
);
public static readonly object[][] ScreeningChannelTestData =
{
new object[] { ScreeningChannel_Rand1, ScreeningChannel_ValRand1 },
new object[] { ScreeningChannel_Rand2, ScreeningChannel_ValRand2 },
};
#endregion
}
}

8
tests/ImageSharp.Tests/TestDataIcc/IccTestDataPrimitives.cs

@ -245,10 +245,18 @@ namespace ImageSharp.Tests
#region ASCII String
public const string Ascii_ValRand = "aBcdEf1234";
public const string Ascii_ValRand1 = "Ecf3a";
public const string Ascii_ValRand2 = "2Bd4c";
public const string Ascii_ValRand3 = "cad14";
public const string Ascii_ValRand4 = "fd4E1";
public const string Ascii_ValRandLength4 = "aBcd";
public const string Ascii_ValNullRand = "aBcd\0Ef\0123";
public static readonly byte[] Ascii_Rand = { 97, 66, 99, 100, 69, 102, 49, 50, 51, 52 };
public static readonly byte[] Ascii_Rand1 = { 69, 99, 102, 51, 97 };
public static readonly byte[] Ascii_Rand2 = { 50, 66, 100, 52, 99 };
public static readonly byte[] Ascii_Rand3 = { 99, 97, 100, 49, 52 };
public static readonly byte[] Ascii_Rand4 = { 102, 100, 52, 69, 49 };
public static readonly byte[] Ascii_RandLength4 = { 97, 66, 99, 100 };
public static readonly byte[] Ascii_PaddedRand = { 97, 66, 99, 100, 69, 102, 49, 50, 51, 52, 0, 0, 0, 0 };
public static readonly byte[] Ascii_NullRand = { 97, 66, 99, 100, 0, 69, 102, 0, 49, 50, 51 };

91
tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs

@ -872,6 +872,97 @@ namespace ImageSharp.Tests
#endregion
#region CrdInfoTagDataEntry
public static readonly IccCrdInfoTagDataEntry CrdInfo_Val = new IccCrdInfoTagDataEntry(
IccTestDataPrimitives.Ascii_ValRand4,
IccTestDataPrimitives.Ascii_ValRand1,
IccTestDataPrimitives.Ascii_ValRand2,
IccTestDataPrimitives.Ascii_ValRand3,
IccTestDataPrimitives.Ascii_ValRand4
);
public static readonly byte[] CrdInfo_Arr = ArrayHelper.Concat
(
IccTestDataPrimitives.UInt32_6,
IccTestDataPrimitives.Ascii_Rand4,
new byte[] { 0 },
IccTestDataPrimitives.UInt32_6,
IccTestDataPrimitives.Ascii_Rand1,
new byte[] { 0 },
IccTestDataPrimitives.UInt32_6,
IccTestDataPrimitives.Ascii_Rand2,
new byte[] { 0 },
IccTestDataPrimitives.UInt32_6,
IccTestDataPrimitives.Ascii_Rand3,
new byte[] { 0 },
IccTestDataPrimitives.UInt32_6,
IccTestDataPrimitives.Ascii_Rand4,
new byte[] { 0 }
);
public static readonly object[][] CrdInfoTagDataEntryTestData =
{
new object[] { CrdInfo_Arr, CrdInfo_Val },
};
#endregion
#region ScreeningTagDataEntry
public static readonly IccScreeningTagDataEntry Screening_Val = new IccScreeningTagDataEntry(
IccScreeningFlag.DefaultScreens | IccScreeningFlag.UnitLinesPerCm,
new IccScreeningChannel[]
{
IccTestDataNonPrimitives.ScreeningChannel_ValRand1,
IccTestDataNonPrimitives.ScreeningChannel_ValRand2,
}
);
public static readonly byte[] Screening_Arr = ArrayHelper.Concat
(
IccTestDataPrimitives.Int32_1,
IccTestDataPrimitives.UInt32_2,
IccTestDataNonPrimitives.ScreeningChannel_Rand1,
IccTestDataNonPrimitives.ScreeningChannel_Rand2
);
public static readonly object[][] ScreeningTagDataEntryTestData =
{
new object[] { Screening_Arr, Screening_Val },
};
#endregion
#region UcrBgTagDataEntry
public static readonly IccUcrBgTagDataEntry UcrBg_Val = new IccUcrBgTagDataEntry(
new ushort[] { 3, 4, 6 },
new ushort[] { 9, 7, 2, 5 },
IccTestDataPrimitives.Ascii_ValRand
);
public static readonly byte[] UcrBg_Arr = ArrayHelper.Concat
(
IccTestDataPrimitives.UInt32_3,
IccTestDataPrimitives.UInt16_3,
IccTestDataPrimitives.UInt16_4,
IccTestDataPrimitives.UInt16_6,
IccTestDataPrimitives.UInt32_4,
IccTestDataPrimitives.UInt16_9,
IccTestDataPrimitives.UInt16_7,
IccTestDataPrimitives.UInt16_2,
IccTestDataPrimitives.UInt16_5,
IccTestDataPrimitives.Ascii_Rand,
new byte[] { 0 }
);
public static readonly object[][] UcrBgTagDataEntryTestData =
{
new object[] { UcrBg_Arr, UcrBg_Val, 41 },
};
#endregion
#region TagDataEntry
public static readonly IccTagDataEntry TagDataEntry_CurveVal = Curve_Val_2;

Loading…
Cancel
Save