Browse Source

Merge pull request #1923 from IldarKhayrutdinov/ifd-pointer

EXIF IDF pointer
pull/1934/head
James Jackson-South 4 years ago
committed by GitHub
parent
commit
ce34e845fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs
  2. 31
      tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs

31
src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs

@ -46,23 +46,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
public byte[] GetData()
{
const uint startIndex = 0;
uint length;
IExifValue exifOffset = GetOffsetValue(this.ifdValues, this.exifValues, ExifTag.SubIFDOffset);
IExifValue gpsOffset = GetOffsetValue(this.ifdValues, this.gpsValues, ExifTag.GPSIFDOffset);
if (this.ifdValues.Count == 0 && this.exifValues.Count == 0 && this.gpsValues.Count == 0)
{
return Array.Empty<byte>();
}
uint ifdLength = this.GetLength(this.ifdValues) + 4U;
uint ifdLength = this.GetLength(this.ifdValues);
uint exifLength = this.GetLength(this.exifValues);
uint gpsLength = this.GetLength(this.gpsValues);
length = ifdLength + exifLength + gpsLength;
uint length = ifdLength + exifLength + gpsLength;
if (length == 4U)
if (length == 0)
{
return Array.Empty<byte>();
}
@ -70,9 +64,10 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
// two bytes for the byte Order marker 'II' or 'MM', followed by the number 42 (0x2A) and a 0, making 4 bytes total
length += (uint)ExifConstants.LittleEndianByteOrderMarker.Length;
length += 4 + 2;
// first IFD offset
length += 4;
var result = new byte[length];
byte[] result = new byte[length];
int i = 0;
@ -80,15 +75,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
ExifConstants.LittleEndianByteOrderMarker.CopyTo(result.AsSpan(start: i));
i += ExifConstants.LittleEndianByteOrderMarker.Length;
uint ifdOffset = ((uint)i - startIndex) + 4U;
uint thumbnailOffset = ifdOffset + ifdLength + exifLength + gpsLength;
uint ifdOffset = (uint)i - startIndex + 4U;
exifOffset?.TrySetValue(ifdOffset + ifdLength);
gpsOffset?.TrySetValue(ifdOffset + ifdLength + exifLength);
i = WriteUInt32(ifdOffset, result, i);
i = this.WriteHeaders(this.ifdValues, result, i);
i = WriteUInt32(thumbnailOffset, result, i);
i = this.WriteData(startIndex, this.ifdValues, result, i);
if (exifLength > 0)
@ -103,8 +96,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
i = this.WriteData(startIndex, this.gpsValues, result, i);
}
WriteUInt16(0, result, i);
return result;
}
@ -263,7 +254,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
uint valueLength = GetLength(value);
length += 2 + 2 + 4 + 4;
length += 12;
if (valueLength > 4)
{
@ -271,6 +262,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
}
}
// next IFD offset
length += 4;
return length;
}
@ -361,6 +355,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
newOffset += 4;
}
// next IFD offset
newOffset = WriteUInt32(0, destination, newOffset);
return newOffset;
}

31
tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -86,6 +87,18 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
new ExifProfile(Array.Empty<byte>());
}
[Fact]
public void EmptyWriter()
{
var profile = new ExifProfile() { Parts = ExifParts.GpsTags };
profile.SetValue(ExifTag.Copyright, "Copyright text");
byte[] bytes = profile.ToByteArray();
Assert.NotNull(bytes);
Assert.Empty(bytes);
}
[Fact]
public void ConstructorCopy()
{
@ -420,7 +433,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
Assert.Equal(2, profile.Values.Count(v => (ExifTagValue)(ushort)v.Tag == ExifTagValue.DateTime));
byte[] bytes = profile.ToByteArray();
Assert.Equal(525, bytes.Length);
Assert.Equal(531, bytes.Length);
var profile2 = new ExifProfile(bytes);
Assert.Equal(25, profile2.Values.Count);
@ -487,6 +500,22 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
return profile;
}
[Fact]
public void IfdStructure()
{
var exif = new ExifProfile();
exif.SetValue(ExifTag.XPAuthor, Encoding.GetEncoding("UCS-2").GetBytes("Dan Petitt"));
Span<byte> actualBytes = exif.ToByteArray();
// Assert
int ifdOffset = ExifConstants.LittleEndianByteOrderMarker.Length;
Assert.Equal(8U, BinaryPrimitives.ReadUInt32LittleEndian(actualBytes.Slice(ifdOffset, 4)));
int nextIfdPointerOffset = ExifConstants.LittleEndianByteOrderMarker.Length + 4 + 2 + 12;
Assert.Equal(0U, BinaryPrimitives.ReadUInt32LittleEndian(actualBytes.Slice(nextIfdPointerOffset, 4)));
}
internal static ExifProfile GetExifProfile()
{
using Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image();

Loading…
Cancel
Save