Skip to content

Commit

Permalink
Merge pull request #2058 from SixLabors/bp/fixapp1parsing
Browse files Browse the repository at this point in the history
Fix issue with app1 parsing
  • Loading branch information
JimBobSquarePants authored Mar 13, 2022
2 parents e73f21f + c668373 commit f970634
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 12 deletions.
19 changes: 10 additions & 9 deletions src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ private void ProcessApplicationHeaderMarker(BufferedReadStream stream, int remai
}

/// <summary>
/// Processes the App1 marker retrieving any stored metadata
/// Processes the App1 marker retrieving any stored metadata.
/// </summary>
/// <param name="stream">The input stream.</param>
/// <param name="remaining">The remaining bytes in the segment block.</param>
Expand All @@ -687,7 +687,7 @@ private void ProcessApp1Marker(BufferedReadStream stream, int remaining)
const int XmpMarkerLength = 29;
if (remaining < ExifMarkerLength || this.IgnoreMetadata)
{
// Skip the application header length
// Skip the application header length.
stream.Skip(remaining);
return;
}
Expand All @@ -697,12 +697,12 @@ private void ProcessApp1Marker(BufferedReadStream stream, int remaining)
JpegThrowHelper.ThrowInvalidImageContentException("Bad App1 Marker length.");
}

// XMP marker is the longest, so read at least that many bytes into temp.
// XMP marker is the longer then the EXIF marker, so first try read the EXIF marker bytes.
stream.Read(this.temp, 0, ExifMarkerLength);
remaining -= ExifMarkerLength;

if (ProfileResolver.IsProfile(this.temp, ProfileResolver.ExifMarker))
{
remaining -= ExifMarkerLength;
this.hasExif = true;
byte[] profile = new byte[remaining];
stream.Read(profile, 0, remaining);
Expand All @@ -713,7 +713,7 @@ private void ProcessApp1Marker(BufferedReadStream stream, int remaining)
}
else
{
// If the EXIF information exceeds 64K, it will be split over multiple APP1 markers
// If the EXIF information exceeds 64K, it will be split over multiple APP1 markers.
this.ExtendProfile(ref this.exifData, profile);
}

Expand All @@ -722,9 +722,10 @@ private void ProcessApp1Marker(BufferedReadStream stream, int remaining)

if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(0, ExifMarkerLength)))
{
stream.Read(this.temp, 0, XmpMarkerLength - ExifMarkerLength);
remaining -= XmpMarkerLength;
if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(ExifMarkerLength)))
int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength;
stream.Read(this.temp, ExifMarkerLength, remainingXmpMarkerBytes);
remaining -= remainingXmpMarkerBytes;
if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker))
{
this.hasXmp = true;
byte[] profile = new byte[remaining];
Expand All @@ -736,7 +737,7 @@ private void ProcessApp1Marker(BufferedReadStream stream, int remaining)
}
else
{
// If the XMP information exceeds 64K, it will be split over multiple APP1 markers
// If the XMP information exceeds 64K, it will be split over multiple APP1 markers.
this.ExtendProfile(ref this.xmpData, profile);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Metadata;
Expand Down
17 changes: 15 additions & 2 deletions tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
// TODO: Scatter test cases into multiple test classes
[Trait("Format", "Jpg")]
[Trait("Format", "Jpg")]
public partial class JpegDecoderTests
{
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.Bgr24 | PixelTypes.RgbaVector;
Expand Down Expand Up @@ -65,7 +65,7 @@ private static bool SkipTest(ITestImageProvider provider)

private ITestOutputHelper Output { get; }

private static JpegDecoder JpegDecoder => new JpegDecoder();
private static JpegDecoder JpegDecoder => new();

[Fact]
public void ParseStream_BasicPropertiesAreCorrect()
Expand Down Expand Up @@ -213,6 +213,19 @@ public void Issue1732_DecodesWithRgbColorSpace<TPixel>(TestImageProvider<TPixel>
}
}

// https://github.com/SixLabors/ImageSharp/issues/2057
[Theory]
[WithFile(TestImages.Jpeg.Issues.Issue2057App1Parsing, PixelTypes.Rgba32)]
public void Issue2057_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(JpegDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
}

// DEBUG ONLY!
// The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm"
// into "\tests\Images\ActualOutput\JpegDecoderTests\"
Expand Down
1 change: 1 addition & 0 deletions tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ public static class Issues
public const string MalformedUnsupportedComponentCount = "Jpg/issues/issue-1900-malformed-unsupported-255-components.jpg";
public const string MultipleApp01932 = "Jpg/issues/issue-1932-app0-resolution.jpg";
public const string InvalidIptcTag = "Jpg/issues/Issue1942InvalidIptcTag.jpg";
public const string Issue2057App1Parsing = "Jpg/issues/Issue2057-App1Parsing.jpg";
public const string ExifNullArrayTag = "Jpg/issues/issue-2056-exif-null-array.jpg";

public static class Fuzz
Expand Down
3 changes: 3 additions & 0 deletions tests/Images/Input/Jpg/issues/Issue2057-App1Parsing.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f970634

Please sign in to comment.