Skip to content

Commit 06f1edf

Browse files
Merge branch 'main' into stefannikolei/nullable/zlib
2 parents b41611a + ea2e6da commit 06f1edf

File tree

18 files changed

+300
-138
lines changed

18 files changed

+300
-138
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

src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs

Lines changed: 207 additions & 95 deletions
Large diffs are not rendered by default.

src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public DrawImageProcessor(
6363
public IImageProcessor<TPixelBg> CreatePixelSpecificProcessor<TPixelBg>(Configuration configuration, Image<TPixelBg> source, Rectangle sourceRectangle)
6464
where TPixelBg : unmanaged, IPixel<TPixelBg>
6565
{
66-
var visitor = new ProcessorFactoryVisitor<TPixelBg>(configuration, this, source, sourceRectangle);
66+
ProcessorFactoryVisitor<TPixelBg> visitor = new(configuration, this, source, sourceRectangle);
6767
this.Image.AcceptVisitor(visitor);
6868
return visitor.Result;
6969
}
@@ -88,8 +88,7 @@ public ProcessorFactoryVisitor(Configuration configuration, DrawImageProcessor d
8888

8989
public void Visit<TPixelFg>(Image<TPixelFg> image)
9090
where TPixelFg : unmanaged, IPixel<TPixelFg>
91-
{
92-
this.Result = new DrawImageProcessor<TPixelBg, TPixelFg>(
91+
=> this.Result = new DrawImageProcessor<TPixelBg, TPixelFg>(
9392
this.configuration,
9493
image,
9594
this.source,
@@ -98,6 +97,5 @@ public void Visit<TPixelFg>(Image<TPixelFg> image)
9897
this.definition.ColorBlendingMode,
9998
this.definition.AlphaCompositionMode,
10099
this.definition.Opacity);
101-
}
102100
}
103101
}

src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ protected override void OnFrameApply(ImageFrame<TPixelBg> source)
8989

9090
int width = maxX - minX;
9191

92-
var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
92+
Rectangle workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);
9393

9494
// Not a valid operation because rectangle does not overlap with this image.
9595
if (workingRect.Width <= 0 || workingRect.Height <= 0)
@@ -98,7 +98,7 @@ protected override void OnFrameApply(ImageFrame<TPixelBg> source)
9898
"Cannot draw image because the source image does not overlap the target image.");
9999
}
100100

101-
var operation = new RowOperation(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity);
101+
DrawImageProcessor<TPixelBg, TPixelFg>.RowOperation operation = new(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity);
102102
ParallelRowIterator.IterateRows(
103103
configuration,
104104
workingRect,

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/Drawing/DrawImageTests.cs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,7 @@ public void DrawImageOfDifferentPixelType<TPixel>(TestImageProvider<TPixel> prov
119119
public void WorksWithDifferentLocations(TestImageProvider<Rgba32> provider, int x, int y)
120120
{
121121
using Image<Rgba32> background = provider.GetImage();
122-
using Image<Rgba32> overlay = new(50, 50);
123-
Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory<Rgba32> overlayMem));
124-
overlayMem.Span.Fill(Color.Black);
122+
using Image<Rgba32> overlay = new(50, 50, Color.Black.ToRgba32());
125123

126124
background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F));
127125

@@ -138,6 +136,31 @@ public void WorksWithDifferentLocations(TestImageProvider<Rgba32> provider, int
138136
appendSourceFileOrDescription: false);
139137
}
140138

139+
[Theory]
140+
[WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 10, 10)]
141+
[WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 25)]
142+
[WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 50)]
143+
[WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 50)]
144+
public void WorksWithDifferentBounds(TestImageProvider<Rgba32> provider, int width, int height)
145+
{
146+
using Image<Rgba32> background = provider.GetImage();
147+
using Image<Rgba32> overlay = new(50, 50, Color.Black.ToRgba32());
148+
149+
background.Mutate(c => c.DrawImage(overlay, new Rectangle(0, 0, width, height), PixelColorBlendingMode.Normal, 1F));
150+
151+
background.DebugSave(
152+
provider,
153+
testOutputDetails: $"{width}_{height}",
154+
appendPixelTypeToFileName: false,
155+
appendSourceFileOrDescription: false);
156+
157+
background.CompareToReferenceOutput(
158+
provider,
159+
testOutputDetails: $"{width}_{height}",
160+
appendPixelTypeToFileName: false,
161+
appendSourceFileOrDescription: false);
162+
}
163+
141164
[Theory]
142165
[WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)]
143166
public void DrawTransformed<TPixel>(TestImageProvider<TPixel> provider)
@@ -158,12 +181,12 @@ public void DrawTransformed<TPixel>(TestImageProvider<TPixel> provider)
158181
Point position = new((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2);
159182
image.Mutate(x => x.DrawImage(blend, position, .75F));
160183

161-
image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false);
184+
image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false);
162185
image.CompareToReferenceOutput(
163186
ImageComparer.TolerantPercentage(0.002f),
164187
provider,
165-
appendSourceFileOrDescription: false,
166-
appendPixelTypeToFileName: false);
188+
appendPixelTypeToFileName: false,
189+
appendSourceFileOrDescription: false);
167190
}
168191

169192
[Theory]
@@ -179,9 +202,6 @@ public void NonOverlappingImageThrows(TestImageProvider<Rgba32> provider, int x,
179202

180203
Assert.Contains("does not overlap", ex.ToString());
181204

182-
void Test()
183-
{
184-
background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions()));
185-
}
205+
void Test() => background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions()));
186206
}
187207
}

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
{

0 commit comments

Comments
 (0)