@@ -18,14 +18,19 @@ public class ImageBrush : IBrush
1818 /// </summary>
1919 private readonly Image image ;
2020
21- private readonly RectangleF ? region ;
21+ /// <summary>
22+ /// The region of the source image we will be using to paint.
23+ /// </summary>
24+ private readonly RectangleF region ;
2225
2326 /// <summary>
2427 /// Initializes a new instance of the <see cref="ImageBrush"/> class.
2528 /// </summary>
2629 /// <param name="image">The image.</param>
2730 public ImageBrush ( Image image )
28- => this . image = image ;
31+ : this ( image , image . Bounds ( ) )
32+ {
33+ }
2934
3035 /// <summary>
3136 /// Initializes a new instance of the <see cref="ImageBrush"/> class.
@@ -49,16 +54,13 @@ public BrushApplicator<TPixel> CreateApplicator<TPixel>(
4954 RectangleF region )
5055 where TPixel : unmanaged, IPixel < TPixel >
5156 {
52- RectangleF interest = this . region ?? region ;
53-
5457 if ( this . image is Image < TPixel > specificImage )
5558 {
56- return new ImageBrushApplicator < TPixel > ( configuration , options , source , specificImage , interest , false ) ;
59+ return new ImageBrushApplicator < TPixel > ( configuration , options , source , specificImage , region , this . region , false ) ;
5760 }
5861
5962 specificImage = this . image . CloneAs < TPixel > ( ) ;
60-
61- return new ImageBrushApplicator < TPixel > ( configuration , options , source , specificImage , interest , true ) ;
63+ return new ImageBrushApplicator < TPixel > ( configuration , options , source , specificImage , region , this . region , true ) ;
6264 }
6365
6466 /// <summary>
@@ -75,14 +77,9 @@ private class ImageBrushApplicator<TPixel> : BrushApplicator<TPixel>
7577 private readonly bool shouldDisposeImage ;
7678
7779 /// <summary>
78- /// The y-length .
80+ /// The region of the source image we will be using to draw from .
7981 /// </summary>
80- private readonly int yLength ;
81-
82- /// <summary>
83- /// The x-length.
84- /// </summary>
85- private readonly int xLength ;
82+ private readonly Rectangle sourceRegion ;
8683
8784 /// <summary>
8885 /// The Y offset.
@@ -93,7 +90,6 @@ private class ImageBrushApplicator<TPixel> : BrushApplicator<TPixel>
9390 /// The X offset.
9491 /// </summary>
9592 private readonly int offsetX ;
96-
9793 private bool isDisposed ;
9894
9995 /// <summary>
@@ -103,32 +99,35 @@ private class ImageBrushApplicator<TPixel> : BrushApplicator<TPixel>
10399 /// <param name="options">The graphics options.</param>
104100 /// <param name="target">The target image.</param>
105101 /// <param name="image">The image.</param>
106- /// <param name="region">The region.</param>
102+ /// <param name="targetRegion">The region of the target image we will be drawing to.</param>
103+ /// <param name="sourceRegion">The region of the source image we will be using to source pixels to draw from.</param>
107104 /// <param name="shouldDisposeImage">Whether to dispose the image on disposal of the applicator.</param>
108105 public ImageBrushApplicator (
109106 Configuration configuration ,
110107 GraphicsOptions options ,
111108 ImageFrame < TPixel > target ,
112109 Image < TPixel > image ,
113- RectangleF region ,
110+ RectangleF targetRegion ,
111+ RectangleF sourceRegion ,
114112 bool shouldDisposeImage )
115113 : base ( configuration , options , target )
116114 {
117115 this . sourceImage = image ;
118116 this . sourceFrame = image . Frames . RootFrame ;
119117 this . shouldDisposeImage = shouldDisposeImage ;
120- this . xLength = image . Width ;
121- this . yLength = image . Height ;
122- this . offsetY = ( int ) MathF . Max ( MathF . Floor ( region . Top ) , 0 ) ;
123- this . offsetX = ( int ) MathF . Max ( MathF . Floor ( region . Left ) , 0 ) ;
118+
119+ this . sourceRegion = Rectangle . Intersect ( image . Bounds ( ) , ( Rectangle ) sourceRegion ) ;
120+
121+ this . offsetY = ( int ) MathF . Max ( MathF . Floor ( targetRegion . Top ) , 0 ) ;
122+ this . offsetX = ( int ) MathF . Max ( MathF . Floor ( targetRegion . Left ) , 0 ) ;
124123 }
125124
126125 internal TPixel this [ int x , int y ]
127126 {
128127 get
129128 {
130- int srcX = ( x - this . offsetX ) % this . xLength ;
131- int srcY = ( y - this . offsetY ) % this . yLength ;
129+ int srcX = ( ( x - this . offsetX ) % this . sourceRegion . Width ) + this . sourceRegion . X ;
130+ int srcY = ( ( y - this . offsetY ) % this . sourceRegion . Width ) + this . sourceRegion . Y ;
132131 return this . sourceFrame [ srcX , srcY ] ;
133132 }
134133 }
@@ -161,15 +160,16 @@ public override void Apply(Span<float> scanline, int x, int y)
161160 Span < float > amountSpan = amountBuffer . Memory . Span ;
162161 Span < TPixel > overlaySpan = overlay . Memory . Span ;
163162
164- int sourceY = ( y - this . offsetY ) % this . yLength ;
165163 int offsetX = x - this . offsetX ;
164+ int sourceY = ( ( y - this . offsetY ) % this . sourceRegion . Width ) + this . sourceRegion . Y ;
166165 Span < TPixel > sourceRow = this . sourceFrame . GetPixelRowSpan ( sourceY ) ;
167166
168167 for ( int i = 0 ; i < scanline . Length ; i ++ )
169168 {
170169 amountSpan [ i ] = scanline [ i ] * this . Options . BlendPercentage ;
171170
172- int sourceX = ( i + offsetX ) % this . xLength ;
171+ int sourceX = ( ( i + offsetX ) % this . sourceRegion . Width ) + this . sourceRegion . X ;
172+
173173 overlaySpan [ i ] = sourceRow [ sourceX ] ;
174174 }
175175
0 commit comments