Skip to content

Commit 464598c

Browse files
Refactor cloning processors and tests
1 parent ab856a3 commit 464598c

26 files changed

+221
-259
lines changed

src/ImageSharp/Advanced/AotCompilerTools.cs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System.Numerics;
5+
using System.Runtime.CompilerServices;
56
using SixLabors.ImageSharp.Formats;
67
using SixLabors.ImageSharp.Formats.Jpeg.Components;
78
using SixLabors.ImageSharp.PixelFormats;
8-
using SixLabors.ImageSharp.Processing;
99
using SixLabors.ImageSharp.Processing.Processors.Dithering;
1010
using SixLabors.ImageSharp.Processing.Processors.Quantization;
11-
using SixLabors.ImageSharp.Processing.Processors.Transforms;
1211

1312
namespace SixLabors.ImageSharp.Advanced
1413
{
@@ -81,9 +80,8 @@ private static void Seed<TPixel>()
8180
AotCompileWuQuantizer<TPixel>();
8281
AotCompileDithering<TPixel>();
8382
AotCompilePixelOperations<TPixel>();
84-
AotCompileResizeOperations<TPixel>();
8583

86-
System.Runtime.CompilerServices.Unsafe.SizeOf<TPixel>();
84+
Unsafe.SizeOf<TPixel>();
8785

8886
AotCodec<TPixel>(new Formats.Png.PngDecoder(), new Formats.Png.PngEncoder());
8987
AotCodec<TPixel>(new Formats.Bmp.BmpDecoder(), new Formats.Bmp.BmpEncoder());
@@ -107,8 +105,10 @@ private static void Seed<TPixel>()
107105
private static void AotCompileOctreeQuantizer<TPixel>()
108106
where TPixel : struct, IPixel<TPixel>
109107
{
110-
var test = new OctreeFrameQuantizer<TPixel>(new OctreeQuantizer(false));
111-
test.AotGetPalette();
108+
using (var test = new OctreeFrameQuantizer<TPixel>(new OctreeQuantizer(false)))
109+
{
110+
test.AotGetPalette();
111+
}
112112
}
113113

114114
/// <summary>
@@ -118,9 +118,11 @@ private static void AotCompileOctreeQuantizer<TPixel>()
118118
private static void AotCompileWuQuantizer<TPixel>()
119119
where TPixel : struct, IPixel<TPixel>
120120
{
121-
var test = new WuFrameQuantizer<TPixel>(Configuration.Default.MemoryAllocator, new WuQuantizer(false));
122-
test.QuantizeFrame(new ImageFrame<TPixel>(Configuration.Default, 1, 1));
123-
test.AotGetPalette();
121+
using (var test = new WuFrameQuantizer<TPixel>(Configuration.Default.MemoryAllocator, new WuQuantizer(false)))
122+
{
123+
test.QuantizeFrame(new ImageFrame<TPixel>(Configuration.Default, 1, 1));
124+
test.AotGetPalette();
125+
}
124126
}
125127

126128
/// <summary>
@@ -132,7 +134,10 @@ private static void AotCompileDithering<TPixel>()
132134
{
133135
var test = new FloydSteinbergDiffuser();
134136
TPixel pixel = default;
135-
test.Dither(new ImageFrame<TPixel>(Configuration.Default, 1, 1), pixel, pixel, 0, 0, 0, 0, 0, 0);
137+
using (var image = new ImageFrame<TPixel>(Configuration.Default, 1, 1))
138+
{
139+
test.Dither(image, pixel, pixel, 0, 0, 0, 0, 0, 0);
140+
}
136141
}
137142

138143
/// <summary>
@@ -171,16 +176,5 @@ private static void AotCompilePixelOperations<TPixel>()
171176
var pixelOp = new PixelOperations<TPixel>();
172177
pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear);
173178
}
174-
175-
/// <summary>
176-
/// This method pre-seeds the ResizeProcessor for the AoT compiler on iOS.
177-
/// </summary>
178-
/// <typeparam name="TPixel">The pixel format.</typeparam>
179-
private static void AotCompileResizeOperations<TPixel>()
180-
where TPixel : struct, IPixel<TPixel>
181-
{
182-
var genericResizeProcessor = (ResizeProcessor<TPixel>)new ResizeProcessor(new ResizeOptions(), default).CreatePixelSpecificProcessor(new Image<TPixel>(0, 0), default);
183-
genericResizeProcessor.AotCreateDestination();
184-
}
185179
}
186180
}

src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectang
6969
{
7070
// When cloning an image we can optimize the processing pipeline by avoiding an unnecessary
7171
// interim clone if the first processor in the pipeline is a cloning processor.
72-
if (processor is CloningImageProcessor cloningImageProcessor)
72+
if (processor is ICloningImageProcessor cloningImageProcessor)
7373
{
74-
using (ICloningImageProcessor<TPixel> pixelProcessor = cloningImageProcessor.CreatePixelSpecificProcessor(this.source, rectangle))
74+
using (ICloningImageProcessor<TPixel> pixelProcessor = cloningImageProcessor.CreatePixelSpecificCloningProcessor(this.source, rectangle))
7575
{
7676
this.destination = pixelProcessor.CloneAndExecute();
7777
return this;

src/ImageSharp/Processing/Processors/CloningImageProcessor.cs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,14 @@ namespace SixLabors.ImageSharp.Processing.Processors
99
/// <summary>
1010
/// The base class for all cloning image processors.
1111
/// </summary>
12-
public abstract class CloningImageProcessor : IImageProcessor
12+
public abstract class CloningImageProcessor : ICloningImageProcessor
1313
{
14-
/// <summary>
15-
/// Creates a pixel specific <see cref="ICloningImageProcessor{TPixel}"/> that is capable of executing
16-
/// the processing algorithm on an <see cref="Image{TPixel}"/>.
17-
/// </summary>
18-
/// <typeparam name="TPixel">The pixel type.</typeparam>
19-
/// <param name="source">The source image. Cannot be null.</param>
20-
/// <param name="sourceRectangle">
21-
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
22-
/// </param>
23-
/// <returns>The <see cref="ICloningImageProcessor{TPixel}"/></returns>
24-
public abstract ICloningImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>(Image<TPixel> source, Rectangle sourceRectangle)
14+
/// <inheritdoc/>
15+
public abstract ICloningImageProcessor<TPixel> CreatePixelSpecificCloningProcessor<TPixel>(Image<TPixel> source, Rectangle sourceRectangle)
2516
where TPixel : struct, IPixel<TPixel>;
2617

2718
/// <inheritdoc/>
2819
IImageProcessor<TPixel> IImageProcessor.CreatePixelSpecificProcessor<TPixel>(Image<TPixel> source, Rectangle sourceRectangle)
29-
=> this.CreatePixelSpecificProcessor(source, sourceRectangle);
20+
=> this.CreatePixelSpecificCloningProcessor(source, sourceRectangle);
3021
}
3122
}

src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
57
using SixLabors.ImageSharp.Advanced;
68
using SixLabors.ImageSharp.PixelFormats;
79
using SixLabors.Primitives;
@@ -40,16 +42,16 @@ protected CloningImageProcessor(Image<TPixel> source, Rectangle sourceRectangle)
4042
protected Rectangle SourceRectangle { get; }
4143

4244
/// <summary>
43-
/// Gets the <see cref="ImageSharp.Configuration"/> instance to use when performing operations.
45+
/// Gets the <see cref="Configuration"/> instance to use when performing operations.
4446
/// </summary>
4547
protected Configuration Configuration { get; }
4648

4749
/// <inheritdoc/>
48-
public Image<TPixel> CloneAndExecute()
50+
Image<TPixel> ICloningImageProcessor<TPixel>.CloneAndExecute()
4951
{
5052
try
5153
{
52-
Image<TPixel> clone = this.CreateDestination();
54+
Image<TPixel> clone = this.CreateTarget();
5355
this.CheckFrameCount(this.Source, clone);
5456

5557
Configuration configuration = this.Source.GetConfiguration();
@@ -82,15 +84,15 @@ public Image<TPixel> CloneAndExecute()
8284
}
8385

8486
/// <inheritdoc/>
85-
public void Execute()
87+
void IImageProcessor<TPixel>.Execute()
8688
{
8789
// Create an interim clone of the source image to operate on.
8890
// Doing this allows for the application of transforms that will alter
8991
// the dimensions of the image.
9092
Image<TPixel> clone = default;
9193
try
9294
{
93-
clone = this.CloneAndExecute();
95+
clone = ((ICloningImageProcessor<TPixel>)this).CloneAndExecute();
9496

9597
// We now need to move the pixel data/size data from the clone to the source.
9698
this.CheckFrameCount(this.Source, clone);
@@ -111,10 +113,10 @@ public void Dispose()
111113
}
112114

113115
/// <summary>
114-
/// Generates a deep clone of the source image that operations should be applied to.
116+
/// Gets the size of the target image.
115117
/// </summary>
116-
/// <returns>The cloned image.</returns>
117-
protected virtual Image<TPixel> CreateDestination() => this.Source.Clone();
118+
/// <returns>The <see cref="Size"/>.</returns>
119+
protected abstract Size GetTargetSize();
118120

119121
/// <summary>
120122
/// This method is called before the process is applied to prepare the processor.
@@ -166,6 +168,23 @@ protected virtual void Dispose(bool disposing)
166168
{
167169
}
168170

171+
private Image<TPixel> CreateTarget()
172+
{
173+
Image<TPixel> source = this.Source;
174+
Size targetSize = this.GetTargetSize();
175+
176+
// We will always be creating the clone even for mutate because we may need to resize the canvas
177+
IEnumerable<ImageFrame<TPixel>> frames = source.Frames.Select<ImageFrame<TPixel>, ImageFrame<TPixel>>(
178+
x => new ImageFrame<TPixel>(
179+
source.GetConfiguration(),
180+
targetSize.Width,
181+
targetSize.Height,
182+
x.Metadata.DeepClone()));
183+
184+
// Use the overload to prevent an extra frame being added
185+
return new Image<TPixel>(this.Configuration, source.Metadata.DeepClone(), frames);
186+
}
187+
169188
private void CheckFrameCount(Image<TPixel> a, Image<TPixel> b)
170189
{
171190
if (a.Frames.Count != b.Frames.Count)

src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected override void BeforeImageApply()
5454
{
5555
if (this.Grayscale)
5656
{
57-
new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle);
57+
new GrayscaleBt709Processor(1F).Execute(this.Source, this.SourceRectangle);
5858
}
5959

6060
base.BeforeImageApply();

src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected override void BeforeImageApply()
4545
{
4646
if (this.Grayscale)
4747
{
48-
new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle);
48+
new GrayscaleBt709Processor(1F).Execute(this.Source, this.SourceRectangle);
4949
}
5050

5151
base.BeforeImageApply();

src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected override void BeforeImageApply()
4141
{
4242
if (this.Grayscale)
4343
{
44-
new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle);
44+
new GrayscaleBt709Processor(1F).Execute(this.Source, this.SourceRectangle);
4545
}
4646

4747
base.BeforeImageApply();

src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public LomographProcessor(LomographProcessor definition, Image<TPixel> source, R
2929
/// <inheritdoc/>
3030
protected override void AfterImageApply()
3131
{
32-
new VignetteProcessor(VeryDarkGreen).Apply(this.Source, this.SourceRectangle);
32+
new VignetteProcessor(VeryDarkGreen).Execute(this.Source, this.SourceRectangle);
3333
base.AfterImageApply();
3434
}
3535
}

src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public PolaroidProcessor(PolaroidProcessor definition, Image<TPixel> source, Rec
3131
/// <inheritdoc/>
3232
protected override void AfterImageApply()
3333
{
34-
new VignetteProcessor(VeryDarkOrange).Apply(this.Source, this.SourceRectangle);
35-
new GlowProcessor(LightOrange, this.Source.Width / 4F).Apply(this.Source, this.SourceRectangle);
34+
new VignetteProcessor(VeryDarkOrange).Execute(this.Source, this.SourceRectangle);
35+
new GlowProcessor(LightOrange, this.Source.Width / 4F).Execute(this.Source, this.SourceRectangle);
3636
base.AfterImageApply();
3737
}
3838
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Six Labors and contributors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using SixLabors.ImageSharp.PixelFormats;
5+
using SixLabors.Primitives;
6+
7+
namespace SixLabors.ImageSharp.Processing.Processors
8+
{
9+
/// <summary>
10+
/// Defines an algorithm to alter the pixels of a cloned image.
11+
/// </summary>
12+
public interface ICloningImageProcessor : IImageProcessor
13+
{
14+
/// <summary>
15+
/// Creates a pixel specific <see cref="ICloningImageProcessor{TPixel}"/> that is capable of executing
16+
/// the processing algorithm on an <see cref="Image{TPixel}"/>.
17+
/// </summary>
18+
/// <typeparam name="TPixel">The pixel type.</typeparam>
19+
/// <param name="source">The source image. Cannot be null.</param>
20+
/// <param name="sourceRectangle">
21+
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
22+
/// </param>
23+
/// <returns>The <see cref="ICloningImageProcessor{TPixel}"/></returns>
24+
ICloningImageProcessor<TPixel> CreatePixelSpecificCloningProcessor<TPixel>(Image<TPixel> source, Rectangle sourceRectangle)
25+
where TPixel : struct, IPixel<TPixel>;
26+
}
27+
}

0 commit comments

Comments
 (0)