Browse Source

Merge branch 'main' into bp/extrasamples2

pull/2062/head
Brian Popow 4 years ago
committed by GitHub
parent
commit
9b8256c4e8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  2. 2
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs
  3. 14
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
  4. 17
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  5. 2
      tests/ImageSharp.Tests/TestImages.cs
  6. 3
      tests/Images/Input/Jpg/issues/Issue2057-App1Parsing.jpg
  7. 3
      tests/Images/Input/Jpg/issues/issue-2056-exif-null-array.jpg

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

@ -677,7 +677,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
} }
/// <summary> /// <summary>
/// Processes the App1 marker retrieving any stored metadata /// Processes the App1 marker retrieving any stored metadata.
/// </summary> /// </summary>
/// <param name="stream">The input stream.</param> /// <param name="stream">The input stream.</param>
/// <param name="remaining">The remaining bytes in the segment block.</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; const int XmpMarkerLength = 29;
if (remaining < ExifMarkerLength || this.IgnoreMetadata) if (remaining < ExifMarkerLength || this.IgnoreMetadata)
{ {
// Skip the application header length // Skip the application header length.
stream.Skip(remaining); stream.Skip(remaining);
return; return;
} }
@ -697,12 +697,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
JpegThrowHelper.ThrowInvalidImageContentException("Bad App1 Marker length."); 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); stream.Read(this.temp, 0, ExifMarkerLength);
remaining -= ExifMarkerLength;
if (ProfileResolver.IsProfile(this.temp, ProfileResolver.ExifMarker)) if (ProfileResolver.IsProfile(this.temp, ProfileResolver.ExifMarker))
{ {
remaining -= ExifMarkerLength;
this.hasExif = true; this.hasExif = true;
byte[] profile = new byte[remaining]; byte[] profile = new byte[remaining];
stream.Read(profile, 0, remaining); stream.Read(profile, 0, remaining);
@ -713,7 +713,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
} }
else 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); 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))) if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(0, ExifMarkerLength)))
{ {
stream.Read(this.temp, 0, XmpMarkerLength - ExifMarkerLength); int remainingXmpMarkerBytes = XmpMarkerLength - ExifMarkerLength;
remaining -= XmpMarkerLength; stream.Read(this.temp, ExifMarkerLength, remainingXmpMarkerBytes);
if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker.Slice(ExifMarkerLength))) remaining -= remainingXmpMarkerBytes;
if (ProfileResolver.IsProfile(this.temp, ProfileResolver.XmpMarker))
{ {
this.hasXmp = true; this.hasXmp = true;
byte[] profile = new byte[remaining]; byte[] profile = new byte[remaining];
@ -736,7 +737,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
} }
else 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); this.ExtendProfile(ref this.xmpData, profile);
} }

2
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{ {
// All array types are value types so Clone() is sufficient here. // All array types are value types so Clone() is sufficient here.
var array = (Array)other.GetValue(); var array = (Array)other.GetValue();
this.TrySetValue(array.Clone()); this.TrySetValue(array?.Clone());
} }
} }

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

@ -4,7 +4,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata;
@ -302,6 +301,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Null(ex); Assert.Null(ex);
} }
[Theory]
[WithFile(TestImages.Jpeg.Issues.ExifNullArrayTag, PixelTypes.Rgba32)]
public void Clone_WithNullRationalArrayTag_DoesNotThrowException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Exception ex = Record.Exception(() =>
{
using Image<TPixel> image = provider.GetImage(JpegDecoder);
var clone = image.Metadata.ExifProfile.DeepClone();
});
Assert.Null(ex);
}
[Fact] [Fact]
public void EncodedStringTags_WriteAndRead() public void EncodedStringTags_WriteAndRead()
{ {

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

@ -21,7 +21,7 @@ using Xunit.Abstractions;
namespace SixLabors.ImageSharp.Tests.Formats.Jpg namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
// TODO: Scatter test cases into multiple test classes // TODO: Scatter test cases into multiple test classes
[Trait("Format", "Jpg")] [Trait("Format", "Jpg")]
public partial class JpegDecoderTests public partial class JpegDecoderTests
{ {
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.Bgr24 | PixelTypes.RgbaVector; 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 ITestOutputHelper Output { get; }
private static JpegDecoder JpegDecoder => new JpegDecoder(); private static JpegDecoder JpegDecoder => new();
[Fact] [Fact]
public void ParseStream_BasicPropertiesAreCorrect() 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! // DEBUG ONLY!
// The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm" // The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm"
// into "\tests\Images\ActualOutput\JpegDecoderTests\" // into "\tests\Images\ActualOutput\JpegDecoderTests\"

2
tests/ImageSharp.Tests/TestImages.cs

@ -262,6 +262,8 @@ namespace SixLabors.ImageSharp.Tests
public const string MalformedUnsupportedComponentCount = "Jpg/issues/issue-1900-malformed-unsupported-255-components.jpg"; 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 MultipleApp01932 = "Jpg/issues/issue-1932-app0-resolution.jpg";
public const string InvalidIptcTag = "Jpg/issues/Issue1942InvalidIptcTag.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 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

3
tests/Images/Input/Jpg/issues/issue-2056-exif-null-array.jpg

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