Skip to content

Commit ea2e6da

Browse files
Merge pull request #2324 from SixLabors/js/2315
Allow zero DPI and only throw at EOF when not enough data
2 parents ad094ff + c224dec commit ea2e6da

File tree

10 files changed

+47
-27
lines changed

10 files changed

+47
-27
lines changed

src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
2626
/// <param name="yDensity">The vertical pixel density.</param>
2727
private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity)
2828
{
29-
if (xDensity <= 0)
30-
{
31-
JpegThrowHelper.ThrowInvalidImageContentException($"X-Density {xDensity} must be greater than 0.");
32-
}
33-
34-
if (yDensity <= 0)
35-
{
36-
JpegThrowHelper.ThrowInvalidImageContentException($"Y-Density {yDensity} must be greater than 0.");
37-
}
38-
3929
this.MajorVersion = majorVersion;
4030
this.MinorVersion = minorVersion;
4131

@@ -64,12 +54,12 @@ private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, shor
6454
public PixelResolutionUnit DensityUnits { get; }
6555

6656
/// <summary>
67-
/// Gets the horizontal pixel density. Must not be zero.
57+
/// Gets the horizontal pixel density.
6858
/// </summary>
6959
public short XDensity { get; }
7060

7161
/// <summary>
72-
/// Gets the vertical pixel density. Must not be zero.
62+
/// Gets the vertical pixel density.
7363
/// </summary>
7464
public short YDensity { get; }
7565

@@ -88,12 +78,8 @@ public static bool TryParse(byte[] bytes, out JFifMarker marker)
8878
byte densityUnits = bytes[7];
8979
short xDensity = (short)((bytes[8] << 8) | bytes[9]);
9080
short yDensity = (short)((bytes[10] << 8) | bytes[11]);
91-
92-
if (xDensity > 0 && yDensity > 0)
93-
{
94-
marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity);
95-
return true;
96-
}
81+
marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity);
82+
return true;
9783
}
9884

9985
marker = default;

src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,10 @@ public static Size CalculateResultingImageSize(Size size, Size? targetSize, out
121121

122122
return size;
123123
}
124+
125+
/// <summary>
126+
/// Gets a value indicating whether the converter has a pixel buffer.
127+
/// </summary>
128+
/// <returns><see langword="true"/> if the converter has a pixel buffer; otherwise, <see langword="false"/>.</returns>
129+
public abstract bool HasPixelBuffer();
124130
}

src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ public SpectralConverter(Configuration configuration, Size? targetSize = null)
8585
/// </summary>
8686
public Configuration Configuration { get; }
8787

88+
/// <summary>
89+
/// Gets a value indicating whether the converter has a pixel buffer.
90+
/// </summary>
91+
/// <returns><see langword="true"/> if the converter has a pixel buffer; otherwise, <see langword="false"/>.</returns>
92+
public override bool HasPixelBuffer() => this.pixelBuffer is not null;
93+
8894
/// <summary>
8995
/// Gets converted pixel buffer.
9096
/// </summary>

src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,18 @@ internal void ParseStream(BufferedReadStream stream, SpectralConverter spectralC
356356
// to uint to avoid sign extension.
357357
if (stream.RemainingBytes < (uint)markerContentByteSize)
358358
{
359+
if (metadataOnly && this.Metadata != null && this.Frame != null)
360+
{
361+
// We have enough data to decode the image, so we can stop parsing.
362+
return;
363+
}
364+
365+
if (this.Metadata != null && this.Frame != null && spectralConverter.HasPixelBuffer())
366+
{
367+
// We have enough data to decode the image, so we can stop parsing.
368+
return;
369+
}
370+
359371
JpegThrowHelper.ThrowNotEnoughBytesForMarker(fileMarker.Marker);
360372
}
361373

tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public override void ConvertStrideBaseline()
5454
{
5555
}
5656

57+
public override bool HasPixelBuffer() => throw new NotImplementedException();
58+
5759
public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData)
5860
{
5961
}

tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ public void MarkerIgnoresIncorrectValue()
4646
Assert.Equal(default, marker);
4747
}
4848

49-
[Fact]
50-
public void MarkerIgnoresCorrectHeaderButInvalidDensities()
51-
{
52-
bool isJFif = JFifMarker.TryParse(this.bytes3, out JFifMarker marker);
53-
54-
Assert.False(isJFif);
55-
Assert.Equal(default, marker);
56-
}
57-
5849
[Fact]
5950
public void MarkerEqualityIsCorrect()
6051
{

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,4 +300,15 @@ public void Issue2136_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
300300
image.DebugSave(provider);
301301
image.CompareToOriginal(provider);
302302
}
303+
304+
// https://github.com/SixLabors/ImageSharp/issues/2315
305+
[Theory]
306+
[WithFile(TestImages.Jpeg.Issues.Issue2315_NotEnoughBytes, PixelTypes.Rgba32)]
307+
public void Issue2315_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
308+
where TPixel : unmanaged, IPixel<TPixel>
309+
{
310+
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance);
311+
image.DebugSave(provider);
312+
image.CompareToOriginal(provider);
313+
}
303314
}

tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ public override void ConvertStrideBaseline()
187187
}
188188
}
189189

190+
public override bool HasPixelBuffer() => throw new NotImplementedException();
191+
190192
public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData)
191193
{
192194
this.frame = frame;

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ public static class Issues
281281
public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg";
282282
public const string Issue2133_DeduceColorSpace = "Jpg/issues/Issue2133.jpg";
283283
public const string Issue2136_ScanMarkerExtraneousBytes = "Jpg/issues/Issue2136-scan-segment-extraneous-bytes.jpg";
284+
public const string Issue2315_NotEnoughBytes = "Jpg/issues/issue-2315.jpg";
284285

285286
public static class Fuzz
286287
{
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)