diff --git a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
index 72c00302d..870c4c8ce 100644
--- a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
+++ b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
@@ -20,6 +20,16 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
private const uint MaxStandardDataTagSize = 0x7FFF;
+ ///
+ /// 1:90 Coded Character Set
+ ///
+ private const byte IptcEnvelopeCodedCharacterSet = 0x5A;
+
+ ///
+ /// This value marks that UTF-8 encoding is used in application records
+ ///
+ private static readonly byte[] CodedCharacterSetUtf8Value = { 0x1B, 0x25, 0x47 };
+
///
/// Initializes a new instance of the class.
///
@@ -194,6 +204,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
this.values.Add(new IptcValue(tag, encoding, value, strict));
}
+ ///
+ /// Sets the value of the specified tag.
+ ///
+ /// The tag of the iptc value.
+ /// The value.
+ ///
+ /// Indicates if length restrictions from the specification should be followed strictly.
+ /// Defaults to true.
+ ///
+ public void SetValue(IptcTag tag, string value, bool strict = true) => this.SetValue(tag, Encoding.UTF8, value, strict);
+
///
/// Makes sure the datetime is formatted according to the iptc specification.
///
@@ -219,17 +240,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
this.SetValue(tag, Encoding.UTF8, formattedDate);
}
- ///
- /// Sets the value of the specified tag.
- ///
- /// The tag of the iptc value.
- /// The value.
- ///
- /// Indicates if length restrictions from the specification should be followed strictly.
- /// Defaults to true.
- ///
- public void SetValue(IptcTag tag, string value, bool strict = true) => this.SetValue(tag, Encoding.UTF8, value, strict);
-
///
/// Updates the data of the profile.
///
@@ -241,9 +251,28 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
length += value.Length + 5;
}
- this.Data = new byte[length];
+ bool hasValuesInUtf8 = this.HasValuesInUtf8();
+
+ if (hasValuesInUtf8)
+ {
+ length += 5 + CodedCharacterSetUtf8Value.Length; // additional length for UTF-8 Tag
+ }
+ this.Data = new byte[length];
int i = 0;
+
+ if (hasValuesInUtf8)
+ {
+ // Standard DataSet Tag
+ this.Data[i++] = IptcTagMarkerByte;
+ this.Data[i++] = 1; // Envelope
+ this.Data[i++] = IptcEnvelopeCodedCharacterSet;
+ this.Data[i++] = (byte)(CodedCharacterSetUtf8Value.Length >> 8);
+ this.Data[i++] = (byte)CodedCharacterSetUtf8Value.Length;
+ Buffer.BlockCopy(CodedCharacterSetUtf8Value, 0, this.Data, i, CodedCharacterSetUtf8Value.Length);
+ i += CodedCharacterSetUtf8Value.Length;
+ }
+
foreach (IptcValue value in this.Values)
{
// Standard DataSet Tag
@@ -264,7 +293,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
// | | | octet 4(most significant bit) always will be 0. |
// +-----------+----------------+---------------------------------------------------------------------------------+
this.Data[i++] = IptcTagMarkerByte;
- this.Data[i++] = 2;
+ this.Data[i++] = 2; // Application
this.Data[i++] = (byte)value.Tag;
this.Data[i++] = (byte)(value.Length >> 8);
this.Data[i++] = (byte)value.Length;
@@ -309,7 +338,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
if (isValidEntry && byteCount > 0 && (offset <= this.Data.Length - byteCount))
{
- var iptcData = new byte[byteCount];
+ byte[] iptcData = new byte[byteCount];
Buffer.BlockCopy(this.Data, offset, iptcData, 0, (int)byteCount);
this.values.Add(new IptcValue(tag, iptcData, false));
}
@@ -317,5 +346,22 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
offset += (int)byteCount;
}
}
+
+ ///
+ /// Gets if any value has UTF-8 encoding
+ ///
+ /// true if any value has UTF-8 encoding
+ private bool HasValuesInUtf8()
+ {
+ foreach (IptcValue value in this.values)
+ {
+ if (value.Encoding == Encoding.UTF8)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
}