mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 872 additions and 9 deletions
@ -0,0 +1,204 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Buffers.Binary; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.ObjectModel; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Class that can be used to access an Iptc profile.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>This source code is from the Magick.Net project:
|
||||
|
/// https://github.com/dlemstra/Magick.NET/tree/master/src/Magick.NET/Shared/Profiles/Iptc/IptcProfile.cs
|
||||
|
/// </remarks>
|
||||
|
public sealed class IptcProfile |
||||
|
{ |
||||
|
private Collection<IptcValue> values; |
||||
|
|
||||
|
private byte[] data; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="IptcProfile"/> class.
|
||||
|
/// </summary>
|
||||
|
public IptcProfile() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="IptcProfile"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="data">The byte array to read the iptc profile from.</param>
|
||||
|
public IptcProfile(byte[] data) |
||||
|
{ |
||||
|
this.data = data; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the values of this iptc profile.
|
||||
|
/// </summary>
|
||||
|
public IEnumerable<IptcValue> Values |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
this.Initialize(); |
||||
|
return this.values; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the value with the specified tag.
|
||||
|
/// </summary>
|
||||
|
/// <param name="tag">The tag of the iptc value.</param>
|
||||
|
/// <returns>The value with the specified tag.</returns>
|
||||
|
public IptcValue GetValue(IptcTag tag) |
||||
|
{ |
||||
|
foreach (IptcValue iptcValue in this.Values) |
||||
|
{ |
||||
|
if (iptcValue.Tag == tag) |
||||
|
{ |
||||
|
return iptcValue; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Removes the value with the specified tag.
|
||||
|
/// </summary>
|
||||
|
/// <param name="tag">The tag of the iptc value.</param>
|
||||
|
/// <returns>True when the value was fount and removed.</returns>
|
||||
|
public bool RemoveValue(IptcTag tag) |
||||
|
{ |
||||
|
this.Initialize(); |
||||
|
|
||||
|
for (int i = 0; i < this.values.Count; i++) |
||||
|
{ |
||||
|
if (this.values[i].Tag == tag) |
||||
|
{ |
||||
|
this.values.RemoveAt(i); |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Changes the encoding for all the values.
|
||||
|
/// </summary>
|
||||
|
/// <param name="encoding">The encoding to use when storing the bytes.</param>
|
||||
|
public void SetEncoding(Encoding encoding) |
||||
|
{ |
||||
|
Guard.NotNull(encoding, nameof(encoding)); |
||||
|
|
||||
|
foreach (IptcValue value in this.Values) |
||||
|
{ |
||||
|
value.Encoding = encoding; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the specified tag.
|
||||
|
/// </summary>
|
||||
|
/// <param name="tag">The tag of the iptc value.</param>
|
||||
|
/// <param name="encoding">The encoding to use when storing the bytes.</param>
|
||||
|
/// <param name="value">The value.</param>
|
||||
|
public void SetValue(IptcTag tag, Encoding encoding, string value) |
||||
|
{ |
||||
|
Guard.NotNull(encoding, nameof(encoding)); |
||||
|
|
||||
|
foreach (IptcValue iptcValue in this.Values) |
||||
|
{ |
||||
|
if (iptcValue.Tag == tag) |
||||
|
{ |
||||
|
iptcValue.Encoding = encoding; |
||||
|
iptcValue.Value = value; |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this.values.Add(new IptcValue(tag, encoding, value)); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sets the value of the specified tag.
|
||||
|
/// </summary>
|
||||
|
/// <param name="tag">The tag of the iptc value.</param>
|
||||
|
/// <param name="value">The value.</param>
|
||||
|
public void SetValue(IptcTag tag, string value) => this.SetValue(tag, Encoding.UTF8, value); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Updates the data of the profile.
|
||||
|
/// </summary>
|
||||
|
public void UpdateData() |
||||
|
{ |
||||
|
var length = 0; |
||||
|
foreach (IptcValue value in this.Values) |
||||
|
{ |
||||
|
length += value.Length + 5; |
||||
|
} |
||||
|
|
||||
|
this.data = new byte[length]; |
||||
|
|
||||
|
int i = 0; |
||||
|
foreach (IptcValue value in this.Values) |
||||
|
{ |
||||
|
this.data[i++] = 28; |
||||
|
this.data[i++] = 2; |
||||
|
this.data[i++] = (byte)value.Tag; |
||||
|
this.data[i++] = (byte)(value.Length >> 8); |
||||
|
this.data[i++] = (byte)value.Length; |
||||
|
if (value.Length > 0) |
||||
|
{ |
||||
|
Buffer.BlockCopy(value.ToByteArray(), 0, this.data, i, value.Length); |
||||
|
i += value.Length; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void Initialize() |
||||
|
{ |
||||
|
if (this.values != null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
this.values = new Collection<IptcValue>(); |
||||
|
|
||||
|
if (this.data == null || this.data[0] != 0x1c) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
int i = 0; |
||||
|
while (i + 4 < this.data.Length) |
||||
|
{ |
||||
|
if (this.data[i++] != 28) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
i++; |
||||
|
|
||||
|
var tag = (IptcTag)this.data[i++]; |
||||
|
|
||||
|
int count = BinaryPrimitives.ReadInt16BigEndian(this.data.AsSpan(i, 2)); |
||||
|
i += 2; |
||||
|
|
||||
|
var iptcData = new byte[count]; |
||||
|
if ((count > 0) && (i + count <= this.data.Length)) |
||||
|
{ |
||||
|
Buffer.BlockCopy(this.data, i, iptcData, 0, count); |
||||
|
this.values.Add(new IptcValue(tag, iptcData)); |
||||
|
} |
||||
|
|
||||
|
i += count; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,351 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// All iptc tags.
|
||||
|
/// </summary>
|
||||
|
public enum IptcTag |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Unknown
|
||||
|
/// </summary>
|
||||
|
Unknown = -1, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Record version
|
||||
|
/// </summary>
|
||||
|
RecordVersion = 0, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Object type
|
||||
|
/// </summary>
|
||||
|
ObjectType = 3, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Object attribute
|
||||
|
/// </summary>
|
||||
|
ObjectAttribute = 4, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Title
|
||||
|
/// </summary>
|
||||
|
Title = 5, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Edit status
|
||||
|
/// </summary>
|
||||
|
EditStatus = 7, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Editorial update
|
||||
|
/// </summary>
|
||||
|
EditorialUpdate = 8, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Priority
|
||||
|
/// </summary>
|
||||
|
Priority = 10, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Category
|
||||
|
/// </summary>
|
||||
|
Category = 15, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Supplemental categories
|
||||
|
/// </summary>
|
||||
|
SupplementalCategories = 20, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Fixture identifier
|
||||
|
/// </summary>
|
||||
|
FixtureIdentifier = 22, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Keyword
|
||||
|
/// </summary>
|
||||
|
Keyword = 25, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Location code
|
||||
|
/// </summary>
|
||||
|
LocationCode = 26, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Location name
|
||||
|
/// </summary>
|
||||
|
LocationName = 27, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Release date
|
||||
|
/// </summary>
|
||||
|
ReleaseDate = 30, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Release time
|
||||
|
/// </summary>
|
||||
|
ReleaseTime = 35, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Expiration date
|
||||
|
/// </summary>
|
||||
|
ExpirationDate = 37, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Expiration time
|
||||
|
/// </summary>
|
||||
|
ExpirationTime = 38, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Special instructions
|
||||
|
/// </summary>
|
||||
|
SpecialInstructions = 40, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Action advised
|
||||
|
/// </summary>
|
||||
|
ActionAdvised = 42, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Reference service
|
||||
|
/// </summary>
|
||||
|
ReferenceService = 45, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Reference date
|
||||
|
/// </summary>
|
||||
|
ReferenceDate = 47, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// ReferenceNumber
|
||||
|
/// </summary>
|
||||
|
ReferenceNumber = 50, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Created date
|
||||
|
/// </summary>
|
||||
|
CreatedDate = 55, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Created time
|
||||
|
/// </summary>
|
||||
|
CreatedTime = 60, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Digital creation date
|
||||
|
/// </summary>
|
||||
|
DigitalCreationDate = 62, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Digital creation time
|
||||
|
/// </summary>
|
||||
|
DigitalCreationTime = 63, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Originating program
|
||||
|
/// </summary>
|
||||
|
OriginatingProgram = 65, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Program version
|
||||
|
/// </summary>
|
||||
|
ProgramVersion = 70, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Object cycle
|
||||
|
/// </summary>
|
||||
|
ObjectCycle = 75, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Byline
|
||||
|
/// </summary>
|
||||
|
Byline = 80, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Byline title
|
||||
|
/// </summary>
|
||||
|
BylineTitle = 85, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// City
|
||||
|
/// </summary>
|
||||
|
City = 90, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Sub location
|
||||
|
/// </summary>
|
||||
|
SubLocation = 92, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Province/State
|
||||
|
/// </summary>
|
||||
|
ProvinceState = 95, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Country code
|
||||
|
/// </summary>
|
||||
|
CountryCode = 100, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Country
|
||||
|
/// </summary>
|
||||
|
Country = 101, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Original transmission reference
|
||||
|
/// </summary>
|
||||
|
OriginalTransmissionReference = 103, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Headline
|
||||
|
/// </summary>
|
||||
|
Headline = 105, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Credit
|
||||
|
/// </summary>
|
||||
|
Credit = 110, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Source
|
||||
|
/// </summary>
|
||||
|
Source = 115, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copyright notice
|
||||
|
/// </summary>
|
||||
|
CopyrightNotice = 116, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Contact
|
||||
|
/// </summary>
|
||||
|
Contact = 118, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Caption
|
||||
|
/// </summary>
|
||||
|
Caption = 120, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Local caption
|
||||
|
/// </summary>
|
||||
|
LocalCaption = 121, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Caption writer
|
||||
|
/// </summary>
|
||||
|
CaptionWriter = 122, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Image type
|
||||
|
/// </summary>
|
||||
|
ImageType = 130, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Image orientation
|
||||
|
/// </summary>
|
||||
|
ImageOrientation = 131, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 1
|
||||
|
/// </summary>
|
||||
|
CustomField1 = 200, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 2
|
||||
|
/// </summary>
|
||||
|
CustomField2 = 201, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 3
|
||||
|
/// </summary>
|
||||
|
CustomField3 = 202, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 4
|
||||
|
/// </summary>
|
||||
|
CustomField4 = 203, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 5
|
||||
|
/// </summary>
|
||||
|
CustomField5 = 204, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 6
|
||||
|
/// </summary>
|
||||
|
CustomField6 = 205, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 7
|
||||
|
/// </summary>
|
||||
|
CustomField7 = 206, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 8
|
||||
|
/// </summary>
|
||||
|
CustomField8 = 207, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 9
|
||||
|
/// </summary>
|
||||
|
CustomField9 = 208, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 10
|
||||
|
/// </summary>
|
||||
|
CustomField10 = 209, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 11
|
||||
|
/// </summary>
|
||||
|
CustomField11 = 210, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 12
|
||||
|
/// </summary>
|
||||
|
CustomField12 = 211, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 13
|
||||
|
/// </summary>
|
||||
|
CustomField13 = 212, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 14
|
||||
|
/// </summary>
|
||||
|
CustomField14 = 213, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 15
|
||||
|
/// </summary>
|
||||
|
CustomField15 = 214, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 16
|
||||
|
/// </summary>
|
||||
|
CustomField16 = 215, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 17
|
||||
|
/// </summary>
|
||||
|
CustomField17 = 216, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 18
|
||||
|
/// </summary>
|
||||
|
CustomField18 = 217, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 19
|
||||
|
/// </summary>
|
||||
|
CustomField19 = 218, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Custom field 20
|
||||
|
/// </summary>
|
||||
|
CustomField20 = 219, |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,167 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Text; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A value of the iptc profile.
|
||||
|
/// </summary>
|
||||
|
public sealed class IptcValue |
||||
|
{ |
||||
|
private byte[] data; |
||||
|
private Encoding encoding; |
||||
|
|
||||
|
internal IptcValue(IptcTag tag, byte[] value) |
||||
|
{ |
||||
|
Guard.NotNull(value, nameof(value)); |
||||
|
|
||||
|
this.Tag = tag; |
||||
|
this.data = value; |
||||
|
this.encoding = Encoding.UTF8; |
||||
|
} |
||||
|
|
||||
|
internal IptcValue(IptcTag tag, Encoding encoding, string value) |
||||
|
{ |
||||
|
this.Tag = tag; |
||||
|
this.encoding = encoding; |
||||
|
this.Value = value; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the encoding to use for the Value.
|
||||
|
/// </summary>
|
||||
|
public Encoding Encoding |
||||
|
{ |
||||
|
get => this.encoding; |
||||
|
set |
||||
|
{ |
||||
|
if (value != null) |
||||
|
{ |
||||
|
this.encoding = value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the tag of the iptc value.
|
||||
|
/// </summary>
|
||||
|
public IptcTag Tag { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the value.
|
||||
|
/// </summary>
|
||||
|
public string Value |
||||
|
{ |
||||
|
get => this.encoding.GetString(this.data); |
||||
|
set |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(value)) |
||||
|
{ |
||||
|
this.data = new byte[0]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
this.data = this.encoding.GetBytes(value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the length of the value.
|
||||
|
/// </summary>
|
||||
|
public int Length => this.data.Length; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines whether the specified object is equal to the current <see cref="IptcValue"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="obj">The object to compare this <see cref="IptcValue"/> with.</param>
|
||||
|
/// <returns>True when the specified object is equal to the current <see cref="IptcValue"/>.</returns>
|
||||
|
public override bool Equals(object obj) |
||||
|
{ |
||||
|
if (ReferenceEquals(this, obj)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return this.Equals(obj as IptcValue); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines whether the specified iptc value is equal to the current <see cref="IptcValue"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="other">The iptc value to compare this <see cref="IptcValue"/> with.</param>
|
||||
|
/// <returns>True when the specified iptc value is equal to the current <see cref="IptcValue"/>.</returns>
|
||||
|
public bool Equals(IptcValue other) |
||||
|
{ |
||||
|
if (other is null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (ReferenceEquals(this, other)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (this.Tag != other.Tag) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
byte[] data = other.ToByteArray(); |
||||
|
|
||||
|
if (this.data.Length != data.Length) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < this.data.Length; i++) |
||||
|
{ |
||||
|
if (this.data[i] != data[i]) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Serves as a hash of this type.
|
||||
|
/// </summary>
|
||||
|
/// <returns>A hash code for the current instance.</returns>
|
||||
|
public override int GetHashCode() => HashCode.Combine(this.data, this.Tag); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts this instance to a byte array.
|
||||
|
/// </summary>
|
||||
|
/// <returns>A <see cref="byte"/> array.</returns>
|
||||
|
public byte[] ToByteArray() |
||||
|
{ |
||||
|
var result = new byte[this.data.Length]; |
||||
|
this.data.CopyTo(result, 0); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a string that represents the current value.
|
||||
|
/// </summary>
|
||||
|
/// <returns>A string that represents the current value.</returns>
|
||||
|
public override string ToString() => this.Value; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns a string that represents the current value with the specified encoding.
|
||||
|
/// </summary>
|
||||
|
/// <param name="enc">The encoding to use.</param>
|
||||
|
/// <returns>A string that represents the current value with the specified encoding.</returns>
|
||||
|
public string ToString(Encoding enc) |
||||
|
{ |
||||
|
Guard.NotNull(enc, nameof(enc)); |
||||
|
|
||||
|
return enc.GetString(this.data); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
IPTC source code is from [Magick.NET](https://github.com/dlemstra/Magick.NET) |
||||
|
|
||||
|
Information about IPTC can be found here in the folowing sources: |
||||
|
|
||||
|
- [metacpan.org, APP13-segment](https://metacpan.org/pod/Image::MetaData::JPEG::Structures#Structure-of-a-Photoshop-style-APP13-segment) |
||||
|
|
||||
|
- [iptc.org](https://www.iptc.org/std/photometadata/documentation/userguide/) |
||||
|
|
||||
|
- [Adobe File Formats Specification](http://oldschoolprg.x10.mx/downloads/ps6ffspecsv2.pdf) |
||||
Loading…
Reference in new issue