Browse Source

Merge pull request #2058 from SixLabors/bp/fixapp1parsing

Fix issue with app1 parsing
pull/2065/head
James Jackson-South 4 years ago
committed by GitHub
parent
commit
f9706344ab
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  2. 1
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
  3. 17
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  4. 1
      tests/ImageSharp.Tests/TestImages.cs
  5. 3
      tests/Images/Input/Jpg/issues/Issue2057-App1Parsing.jpg

19
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -677,7 +677,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
}
/// <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>
@ -687,7 +687,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
const int XmpMarkerLength = 29;
if (remaining < ExifMarkerLength || this.IgnoreMetadata)
{
// Skip the application header length
// Skip the application header length.
stream.Skip(remaining);
return;
}
@ -697,12 +697,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
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);
@ -713,7 +713,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
}
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);
}
@ -722,9 +722,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
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];
@ -736,7 +737,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
}
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);
}

1
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs

@ -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;

17
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -21,7 +21,7 @@ using Xunit.Abstractions;
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;
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
private ITestOutputHelper Output { get; }
private static JpegDecoder JpegDecoder => new JpegDecoder();
private static JpegDecoder JpegDecoder => new();
[Fact]
public void ParseStream_BasicPropertiesAreCorrect()
@ -213,6 +213,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
}
// 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\"

1
tests/ImageSharp.Tests/TestImages.cs

@ -262,6 +262,7 @@ namespace SixLabors.ImageSharp.Tests
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

3
tests/Images/Input/Jpg/issues/Issue2057-App1Parsing.jpg

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7048dee15946bf981e5b0d2481ffcb8a64684fddca07172275b13a05f01b6b63
size 1631109
Loading…
Cancel
Save