diff --git a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
index 306924e62c..f123e62d5f 100644
--- a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
+++ b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
@@ -228,6 +228,10 @@ public void SetDateTimeValue(IptcTag tag, DateTimeOffset dateTimeOffset)
///
/// Updates the data of the profile.
///
+ ///
+ /// When any value uses UTF-8 encoding, which is the default encoding of a value, the data starts with the
+ /// 1:90 Coded Character Set dataset declaring UTF-8, also when the text is ASCII only.
+ ///
public void UpdateData()
{
int length = 0;
@@ -337,7 +341,9 @@ private bool HasValuesInUtf8()
{
foreach (IptcValue value in this.values)
{
- if (value.Encoding == Encoding.UTF8)
+ // Compare the code page rather than the instance. Cloned values hold a copy of their encoding,
+ // and callers can pass their own UTF8Encoding, but both still write UTF-8 bytes.
+ if (value.Encoding.CodePage == Encoding.UTF8.CodePage)
{
return true;
}
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs
index 37f99517c7..4ae475c653 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs
@@ -34,6 +34,57 @@ public void IptcProfile_WithUtf8Data_WritesEnvelopeRecord_Works()
Assert.True(profileBytes.AsSpan(0, 8).SequenceEqual(expectedEnvelopeData));
}
+ [Fact]
+ public void IptcProfile_DeepClone_WithUtf8Data_WritesEnvelopeRecord_Works()
+ {
+ // arrange
+ IptcProfile profile = new();
+ profile.SetValue(IptcTag.City, "ESPAÑA");
+ IptcProfile clone = profile.DeepClone();
+ byte[] expectedEnvelopeData = [28, 1, 90, 0, 3, 27, 37, 71];
+
+ // act
+ clone.UpdateData();
+
+ // assert
+ Assert.True(clone.Data.AsSpan(0, 8).SequenceEqual(expectedEnvelopeData));
+ }
+
+ [Fact]
+ public void IptcProfile_WithUtf8EncodingInstance_WritesEnvelopeRecord_Works()
+ {
+ // arrange
+ IptcProfile profile = new();
+ profile.SetValue(IptcTag.City, new System.Text.UTF8Encoding(false), "ESPAÑA");
+ byte[] expectedEnvelopeData = [28, 1, 90, 0, 3, 27, 37, 71];
+
+ // act
+ profile.UpdateData();
+
+ // assert
+ Assert.True(profile.Data.AsSpan(0, 8).SequenceEqual(expectedEnvelopeData));
+ }
+
+ [Fact]
+ public void WritingClonedImage_WithUtf8Data_WritesEnvelopeRecordOnce()
+ {
+ // arrange
+ using Image image = new(1, 1);
+ image.Metadata.IptcProfile = new IptcProfile();
+ image.Metadata.IptcProfile.SetValue(IptcTag.Caption, "ESPAÑA");
+ byte[] expectedData = [28, 1, 90, 0, 3, 27, 37, 71, 28, 2, 120, 0, 7, 69, 83, 80, 65, 195, 145, 65];
+
+ // act
+ using Image once = WriteAndReadJpeg(image.Clone());
+ using Image twice = WriteAndReadJpeg(once.Clone());
+
+ // assert
+ IptcProfile actual = twice.Metadata.IptcProfile;
+ Assert.Equal(expectedData, actual.Data);
+ IptcValue value = Assert.Single(actual.Values);
+ Assert.Equal("ESPAÑA", value.Value);
+ }
+
[Theory]
[MemberData(nameof(AllIptcTags))]
public void IptcProfile_SetValue_WithStrictEnabled_Works(IptcTag tag)