Skip to content

Commit

Permalink
Added extra properties to the ColorProfile class (#443).
Browse files Browse the repository at this point in the history
  • Loading branch information
dlemstra committed Jun 14, 2019
1 parent 92dad19 commit ff68b36
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 41 deletions.
69 changes: 28 additions & 41 deletions src/Magick.NET/Shared/Profiles/Color/ColorProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;

namespace ImageMagick
{
Expand Down Expand Up @@ -96,6 +93,26 @@ internal ColorProfile(string name, byte[] data)
/// </summary>
public ColorSpace ColorSpace { get; private set; }

/// <summary>
/// Gets the copyright of the profile.
/// </summary>
public string Copyright { get; private set; }

/// <summary>
/// Gets the description of the profile.
/// </summary>
public string Description { get; private set; }

/// <summary>
/// Gets the manufacturer of the profile.
/// </summary>
public string Manufacturer { get; private set; }

/// <summary>
/// Gets the model of the profile.
/// </summary>
public string Model { get; private set; }

private static ColorProfile Load(string resourcePath, string resourceName)
{
lock (_SyncRoot)
Expand All @@ -112,46 +129,16 @@ private static ColorProfile Load(string resourcePath, string resourceName)
return _profiles[resourceName];
}

[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Cannot avoid it here.")]
private static ColorSpace DetermineColorSpace(string colorSpace)
{
switch (colorSpace)
{
case "CMY":
return ColorSpace.CMY;
case "CMYK":
return ColorSpace.CMYK;
case "GRAY":
return ColorSpace.Gray;
case "HLS":
return ColorSpace.HSL;
case "HSV":
return ColorSpace.HSV;
case "Lab":
return ColorSpace.Lab;
case "Luv":
return ColorSpace.YUV;
case "RGB":
return ColorSpace.sRGB;
case "XYZ":
return ColorSpace.XYZ;
case "YCbr":
return ColorSpace.YCbCr;
case "Yxy":
return ColorSpace.XyY;
default:
throw new NotSupportedException(colorSpace);
}
}

private void Initialize()
{
ColorSpace = ColorSpace.Undefined;
if (Data.Length < 20)
return;

string colorSpace = Encoding.ASCII.GetString(Data, 16, 4).TrimEnd();
ColorSpace = DetermineColorSpace(colorSpace);
var reader = new ColorProfileReader();
reader.Read(Data);

ColorSpace = reader.ColorSpace;
Copyright = reader.Copyright;
Description = reader.Description;
Manufacturer = reader.Manufacturer;
Model = reader.Model;
}
}
}
165 changes: 165 additions & 0 deletions src/Magick.NET/Shared/Profiles/Color/ColorProfileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright 2013-2019 Dirk Lemstra <https://github.com/dlemstra/Magick.NET/>
//
// Licensed under the ImageMagick License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// https://www.imagemagick.org/script/license.php
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;

namespace ImageMagick
{
internal sealed class ColorProfileReader
{
private EndianReader _reader;

public ColorSpace ColorSpace { get; private set; }

public string Copyright { get; private set; }

public string Description { get; private set; }

public string Manufacturer { get; private set; }

public string Model { get; private set; }

public void Read(byte[] data)
{
if (data == null || data.Length < 20)
return;

_reader = new EndianReader(data);

ReadColorSpace();
ReadTagTable();
}

private static ColorSpace DetermineColorSpace(string colorSpace)
{
switch (colorSpace)
{
case "CMY":
return ColorSpace.CMY;
case "CMYK":
return ColorSpace.CMYK;
case "GRAY":
return ColorSpace.Gray;
case "HLS":
return ColorSpace.HSL;
case "HSV":
return ColorSpace.HSV;
case "Lab":
return ColorSpace.Lab;
case "Luv":
return ColorSpace.YUV;
case "RGB":
return ColorSpace.sRGB;
case "XYZ":
return ColorSpace.XYZ;
case "YCbr":
return ColorSpace.YCbCr;
case "Yxy":
return ColorSpace.XyY;
default:
throw new NotSupportedException(colorSpace);
}
}

private void ReadColorSpace()
{
_reader.Seek(16);

var colorSpace = _reader.ReadString(4).TrimEnd();
ColorSpace = DetermineColorSpace(colorSpace);
}

private void ReadTagTable()
{
if (!_reader.Seek(128))
return;

var count = _reader.ReadLongMSB();
for (var i = 0; i < count; i++)
{
var tag = _reader.ReadLongMSB();
switch (tag)
{
case 0x63707274:
Copyright = ReadTag();
break;
case 0x64657363:
Description = ReadTag();
break;
case 0x646D6E64:
Manufacturer = ReadTag();
break;
case 0x646D6464:
Model = ReadTag();
break;
default:
_reader.Skip(8);
break;
}
}
}

private string ReadTag()
{
var offset = _reader.ReadLongMSB();
var length = _reader.ReadLongMSB();

if (offset == null || length == null)
return null;

var originalIndex = _reader.Index;

if (!_reader.Seek(offset.Value))
return null;

var value = ReadTagValue(length.Value);

_reader.Seek(originalIndex);

return value;
}

private string ReadTagValue(uint length)
{
var type = _reader.ReadString(4);
switch (type)
{
case "desc":
return ReadTextDescriptionTypeValue();
case "text":
return ReadTextTypeValue(length);
default:
throw new NotSupportedException(type);
}
}

private string ReadTextDescriptionTypeValue()
{
if (!_reader.Skip(4))
return null;

var length = _reader.ReadLongMSB();
if (length == null)
return null;

return _reader.ReadString(length.Value);
}

private string ReadTextTypeValue(uint length)
{
if (!_reader.Skip(4))
return null;

return _reader.ReadString(length);
}
}
}
10 changes: 10 additions & 0 deletions src/Magick.NET/Shared/Profiles/EndianReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ public bool Seek(uint index)
return true;
}

public bool Skip(uint value)
{
if (Index + value >= _data.Length)
return false;

Index += value;

return true;
}

public byte? ReadByte()
{
if (Index >= _data.Length)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2013-2019 Dirk Lemstra <https://github.com/dlemstra/Magick.NET/>
//
// Licensed under the ImageMagick License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// https://www.imagemagick.org/script/license.php
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using ImageMagick;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Magick.NET.Tests
{
public partial class ColorProfileTests
{
[TestClass]
public class TheCopyrightProperty
{
[TestMethod]
public void ShouldReturnTheCorrectValue()
{
Assert.AreEqual("Copyright 2000 Adobe Systems Incorporated", ColorProfile.AdobeRGB1998.Copyright);
Assert.AreEqual("Copyright 2000 Adobe Systems Incorporated", ColorProfile.AppleRGB.Copyright);
Assert.AreEqual("Copyright 2007 Adobe Systems, Inc.", ColorProfile.CoatedFOGRA39.Copyright);
Assert.AreEqual("Copyright 2000 Adobe Systems Incorporated", ColorProfile.ColorMatchRGB.Copyright);
Assert.AreEqual("Copyright (c) 1998 Hewlett-Packard Company", ColorProfile.SRGB.Copyright);
Assert.AreEqual("Copyright 2000 Adobe Systems, Inc.", ColorProfile.USWebCoatedSWOP.Copyright);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2013-2019 Dirk Lemstra <https://github.com/dlemstra/Magick.NET/>
//
// Licensed under the ImageMagick License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// https://www.imagemagick.org/script/license.php
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using ImageMagick;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Magick.NET.Tests
{
public partial class ColorProfileTests
{
[TestClass]
public class TheDescriptionProperty
{
[TestMethod]
public void ShouldReturnTheCorrectValue()
{
Assert.AreEqual("Adobe RGB (1998)", ColorProfile.AdobeRGB1998.Description);
Assert.AreEqual("Apple RGB", ColorProfile.AppleRGB.Description);
Assert.AreEqual("Coated FOGRA39 (ISO 12647-2:2004)", ColorProfile.CoatedFOGRA39.Description);
Assert.AreEqual("ColorMatch RGB", ColorProfile.ColorMatchRGB.Description);
Assert.AreEqual("sRGB IEC61966-2.1", ColorProfile.SRGB.Description);
Assert.AreEqual("U.S. Web Coated (SWOP) v2", ColorProfile.USWebCoatedSWOP.Description);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2013-2019 Dirk Lemstra <https://github.com/dlemstra/Magick.NET/>
//
// Licensed under the ImageMagick License (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
//
// https://www.imagemagick.org/script/license.php
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using ImageMagick;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Magick.NET.Tests
{
public partial class ColorProfileTests
{
[TestClass]
public class TheManufacturerProperty
{
[TestMethod]
public void ShouldReturnTheCorrectValue()
{
Assert.IsNull(ColorProfile.AdobeRGB1998.Manufacturer);
Assert.IsNull(ColorProfile.AppleRGB.Manufacturer);
Assert.IsNull(ColorProfile.CoatedFOGRA39.Manufacturer);
Assert.IsNull(ColorProfile.ColorMatchRGB.Manufacturer);
Assert.AreEqual("IEC http://www.iec.ch", ColorProfile.SRGB.Manufacturer);
Assert.IsNull(ColorProfile.USWebCoatedSWOP.Manufacturer);
}
}
}
}
Loading

0 comments on commit ff68b36

Please sign in to comment.