diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 1310d90d26..bd5a9e10f0 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
+using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;
@@ -608,7 +609,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
private void WriteExifProfile(ExifProfile exifProfile)
{
const int Max = 65533;
- byte[] data = exifProfile?.ToByteArray();
+ byte[] data = exifProfile?.ToByteArray(ProfileResolver.ExifMarker);
if (data == null || data.Length == 0)
{
return;
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 9e0f5f877e..fedd46063d 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -536,7 +536,7 @@ namespace SixLabors.ImageSharp.Formats.Png
{
if (image.MetaData.ExifProfile?.Values.Count > 0)
{
- this.WriteChunk(stream, PngChunkType.Exif, image.MetaData.ExifProfile.ToByteArray(includeExifIdCode: false));
+ this.WriteChunk(stream, PngChunkType.Exif, image.MetaData.ExifProfile.ToByteArray());
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
index 78fa63ae75..b38097060e 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
@@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
@@ -234,20 +233,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Converts this instance to a byte array.
///
- /// Indicates, if the Exif ID code should be included.
- /// The Exif Id Code is part of the JPEG APP1 segment. This Exif ID code should not be included in case of PNG's.
- /// Defaults to true.
+ /// The Exif Id Code is part of the JPEG APP1 segment (Exif00). Those bytes will be written at
+ /// the beginning of the array. This Exif ID code should not be included in case of PNG's.
/// The
- public byte[] ToByteArray(bool includeExifIdCode = true)
+ public byte[] ToByteArray(ReadOnlySpan exifIdCode = default)
{
if (this.values == null)
{
- if (!includeExifIdCode && this.StartsWithExifIdCode(this.data))
- {
- // skip the first 6 bytes (the Exif Code)
- return this.data.Skip(6).ToArray();
- }
-
return this.data;
}
@@ -257,31 +249,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
var writer = new ExifWriter(this.values, this.Parts);
- return writer.GetData(includeExifIdCode);
- }
-
- ///
- /// Checks if a byte array start with the Exif Code: ASCII "Exif" followed by two zeros.
- ///
- /// The byte array to check for the Exif Code.
- /// True, if the byte array starts with the Exif Code
- private bool StartsWithExifIdCode(byte[] exifBytes)
- {
- if (exifBytes.Length < 6)
- {
- return false;
- }
-
- int exifLength = ProfileResolver.ExifMarker.Length;
- for (int i = 0; i < ProfileResolver.ExifMarker.Length; i++)
- {
- if (exifBytes[i] != ProfileResolver.ExifMarker[i])
- {
- return false;
- }
- }
-
- return true;
+ return writer.GetData(exifIdCode);
}
///
diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
index ff0c6bf5c9..1de5fbd5cf 100644
--- a/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
+++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
@@ -5,7 +5,6 @@ using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Text;
-using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
@@ -42,15 +41,15 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
///
/// Returns the EXIF data.
///
- /// Indicates, if the Exif ID code should be included.
- /// The Exif Id Code is part of the JPEG APP1 segment. This Exif ID code should not be included in case of PNG's.
- /// Defaults to true.
+ /// The Exif Id Code is part of the JPEG APP1 segment (Exif00). Those bytes will be written at
+ /// the beginning of the array. This Exif ID code should not be included in case of PNG's.
///
/// The .
///
- public byte[] GetData(bool includeExifIdCode = true)
+ public byte[] GetData(ReadOnlySpan exifIdCode)
{
- uint startIndex = (uint)ProfileResolver.ExifMarker.Length;
+ uint exifIdCodeLength = exifIdCode.IsEmpty ? 0 : (uint)exifIdCode.Length;
+ uint startIndex = exifIdCodeLength;
uint length;
int exifIndex = -1;
int gpsIndex = -1;
@@ -86,17 +85,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
return null;
}
- if (includeExifIdCode)
- {
- // Exif Id Code "Exif00" (6 bytes)
- length += (uint)ProfileResolver.ExifMarker.Length;
- }
- else
- {
- // special case for PNG eXIf Chunk:
- // if the Exif Code ("Exif00") is not included, the start index is 0 instead of 6
- startIndex = 0;
- }
+ length += exifIdCodeLength;
// two bytes for the byte Order marker 'II', followed by the number 42 (0x2A) and a 0, making 4 bytes total
length += (uint)ExifConstants.LittleEndianByteOrderMarker.Length;
@@ -106,10 +95,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
byte[] result = new byte[length];
int i = 0;
- if (includeExifIdCode)
+ if (!exifIdCode.IsEmpty)
{
- ProfileResolver.ExifMarker.AsSpan().CopyTo(result); // 0-5
- i += ProfileResolver.ExifMarker.Length;
+ exifIdCode.CopyTo(result); // 0-5
+ i += exifIdCode.Length;
}
// the byte order marker for little-endian, followed by the number 42 and a 0
diff --git a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
index 255451e0e6..7d0686aa76 100644
--- a/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
@@ -32,6 +33,7 @@ namespace SixLabors.ImageSharp.Tests
ImageMetaData clone = metaData.Clone();
Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
+ Assert.Equal(exifProfile.ToByteArray(ProfileResolver.ExifMarker), clone.ExifProfile.ToByteArray(ProfileResolver.ExifMarker));
Assert.Equal(4, clone.HorizontalResolution);
Assert.Equal(2, clone.VerticalResolution);
Assert.Equal(imageProperty, clone.Properties[0]);
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
index 2192d134ed..7d4ddd3227 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
@@ -324,7 +324,7 @@ namespace SixLabors.ImageSharp.Tests
// Force parsing of the profile.
Assert.Equal(24, profile.Values.Count);
- byte[] bytes = profile.ToByteArray();
+ byte[] bytes = profile.ToByteArray(ProfileResolver.ExifMarker);
Assert.Equal(495, bytes.Length);
}
@@ -360,21 +360,21 @@ namespace SixLabors.ImageSharp.Tests
// arrange
byte[] exifBytesWithExifCode = ProfileResolver.ExifMarker.Concat(ExifConstants.LittleEndianByteOrderMarker).ToArray();
byte[] exifBytesWithoutExifCode = ExifConstants.LittleEndianByteOrderMarker;
- var profile = new ExifProfile(exifBytesWithExifCode);
+ ExifProfile profile = CreateExifProfile();
// act
- byte[] actual = profile.ToByteArray(includeExifIdCode);
+ byte[] actual = profile.ToByteArray(includeExifIdCode ? ProfileResolver.ExifMarker : default(ReadOnlySpan));
// assert
Assert.NotNull(actual);
Assert.NotEmpty(actual);
if (includeExifIdCode)
{
- Assert.Equal(exifBytesWithExifCode, actual);
+ Assert.Equal(exifBytesWithExifCode, actual.Take(exifBytesWithExifCode.Length).ToArray());
}
else
{
- Assert.Equal(exifBytesWithoutExifCode, actual);
+ Assert.Equal(exifBytesWithoutExifCode, actual.Take(exifBytesWithoutExifCode.Length).ToArray());
}
}
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs
index bae22e7a92..9f353f8132 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs
@@ -9,6 +9,7 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
+ using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.Processing.Transforms;
public class AutoOrientTests : FileTestBase
@@ -65,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
var profile = new ExifProfile();
profile.SetValue(ExifTag.JPEGTables, orientation);
- byte[] bytes = profile.ToByteArray();
+ byte[] bytes = profile.ToByteArray(ProfileResolver.ExifMarker);
// Change the tag into ExifTag.Orientation
bytes[16] = 18;
bytes[17] = 1;