Browse Source

if exif data exceeds 64k, it will be written in multiple APP1 markers

pull/616/head
popow 8 years ago
parent
commit
e6bcb2b1cd
  1. 47
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

47
src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

@ -213,6 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// Write the Start Of Image marker.
this.WriteApplicationHeader((short)image.MetaData.HorizontalResolution, (short)image.MetaData.VerticalResolution);
// Write Exif and ICC profiles
this.WriteProfiles(image);
// Write the quantization tables.
@ -608,27 +609,57 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// </exception>
private void WriteExifProfile(ExifProfile exifProfile)
{
const int Max = 65533;
const int MaxBytesApp1 = 65533;
const int MaxBytesWithExifId = 65527;
byte[] data = exifProfile?.ToByteArray(ProfileResolver.ExifMarker);
if (data == null || data.Length == 0)
{
return;
}
if (data.Length > Max)
int remaining = data.Length;
int bytesToWrite = remaining > MaxBytesApp1 ? MaxBytesApp1 : remaining;
int app1Length = bytesToWrite + 2;
// write the app1 header
this.WriteApp1Header(app1Length);
// write the exif data
this.outputStream.Write(data, 0, bytesToWrite);
remaining -= bytesToWrite;
// if the exif data exceeds 64K, write it in multiple APP1 Markers
for (int idx = MaxBytesApp1; idx < data.Length; idx += MaxBytesWithExifId)
{
throw new ImageFormatException($"Exif profile size exceeds limit of {Max} bytes.");
}
bytesToWrite = remaining > MaxBytesWithExifId ? MaxBytesWithExifId : remaining;
app1Length = bytesToWrite + 2 + 6;
// write the app1 header
this.WriteApp1Header(app1Length);
// write Exif00 marker
ProfileResolver.ExifMarker.AsSpan().CopyTo(this.buffer.AsSpan());
this.outputStream.Write(this.buffer, 0, 6);
int length = data.Length + 2;
// write the exif data
this.outputStream.Write(data, idx, bytesToWrite);
remaining -= bytesToWrite;
}
}
/// <summary>
/// Writes the App1 header.
/// </summary>
/// <param name="app1Length">The length of the data the app1 marker contains</param>
private void WriteApp1Header(int app1Length)
{
this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = JpegConstants.Markers.APP1; // Application Marker
this.buffer[2] = (byte)((length >> 8) & 0xFF);
this.buffer[3] = (byte)(length & 0xFF);
this.buffer[2] = (byte)((app1Length >> 8) & 0xFF);
this.buffer[3] = (byte)(app1Length & 0xFF);
this.outputStream.Write(this.buffer, 0, 4);
this.outputStream.Write(data, 0, data.Length);
}
/// <summary>

Loading…
Cancel
Save