Skip to content

Commit 45c4352

Browse files
Fix XY position.
1 parent b4fd913 commit 45c4352

3 files changed

Lines changed: 149 additions & 62 deletions

File tree

src/ImageSharp.Web/FormattedImage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static FormattedImage Load(Configuration configuration, Stream source)
102102
/// Returns a value indicating whether the source image contains EXIF metadata for <see cref="ExifTag.Orientation"/>
103103
/// indicating that the image is rotated (not flipped).
104104
/// </summary>
105-
/// <param name="orientation">The captured orientation. Use <see cref="ExifOrientationMode"/> for comparison.</param>
105+
/// <param name="orientation">The decoded orientation. Use <see cref="ExifOrientationMode"/> for comparison.</param>
106106
/// <returns>The <see cref="bool"/> indicating whether the image contains EXIF metadata indicating that the image is rotated.</returns>
107107
public bool IsExifRotated(out ushort orientation)
108108
{

src/ImageSharp.Web/Processors/ResizeWebProcessor.cs

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.Globalization;
6+
using System.Numerics;
67
using Microsoft.Extensions.Logging;
78
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
89
using SixLabors.ImageSharp.Processing;
@@ -123,7 +124,7 @@ internal static ResizeOptions GetResizeOptions(
123124
ResizeOptions options = new()
124125
{
125126
Size = size,
126-
CenterCoordinates = GetCenter(rotated, commands, parser, culture),
127+
CenterCoordinates = GetCenter(image, orientation, commands, parser, culture),
127128
Position = GetAnchor(orientation, commands, parser, culture),
128129
Mode = GetMode(commands, parser, culture),
129130
Compand = GetCompandMode(commands, parser, culture),
@@ -148,7 +149,8 @@ private static Size ParseSize(
148149
}
149150

150151
private static PointF? GetCenter(
151-
bool rotated,
152+
FormattedImage image,
153+
ushort orientation,
152154
CommandCollection commands,
153155
CommandParser parser,
154156
CultureInfo culture)
@@ -160,7 +162,48 @@ private static Size ParseSize(
160162
return null;
161163
}
162164

163-
return rotated ? new PointF(coordinates[1], coordinates[0]) : new PointF(coordinates[0], coordinates[1]);
165+
PointF center = new(coordinates[0], coordinates[1]);
166+
if (orientation is >= ExifOrientationMode.Unknown and <= ExifOrientationMode.TopLeft)
167+
{
168+
return center;
169+
}
170+
171+
AffineTransformBuilder builder = new();
172+
Size size = image.Image.Size();
173+
174+
// New XY is calculated based on flipping and rotating the input XY.
175+
// Operations are based upon AutoOrientProcessor implementation.
176+
switch (orientation)
177+
{
178+
case ExifOrientationMode.TopRight:
179+
builder.AppendTranslation(new PointF(size.Width - center.X, 0));
180+
break;
181+
case ExifOrientationMode.BottomRight:
182+
builder.AppendRotationDegrees(180);
183+
break;
184+
case ExifOrientationMode.BottomLeft:
185+
builder.AppendTranslation(new PointF(0, size.Height - center.Y));
186+
break;
187+
case ExifOrientationMode.LeftTop:
188+
builder.AppendRotationDegrees(90);
189+
builder.AppendTranslation(new PointF(size.Width - center.X, 0));
190+
break;
191+
case ExifOrientationMode.RightTop:
192+
builder.AppendRotationDegrees(90);
193+
break;
194+
case ExifOrientationMode.RightBottom:
195+
builder.AppendTranslation(new PointF(0, size.Height - center.Y));
196+
builder.AppendRotationDegrees(270);
197+
break;
198+
case ExifOrientationMode.LeftBottom:
199+
builder.AppendRotationDegrees(270);
200+
break;
201+
default:
202+
return center;
203+
}
204+
205+
Matrix3x2 matrix = builder.BuildMatrix(size);
206+
return Vector2.Transform(center, matrix);
164207
}
165208

166209
private static ResizeMode GetMode(
@@ -181,6 +224,25 @@ private static AnchorPositionMode GetAnchor(
181224
return anchor;
182225
}
183226

227+
/*
228+
New anchor position is determined by calculating the direction of the anchor relative to the source image.
229+
In the following example, the TopRight anchor becomes BottomRight
230+
231+
T L
232+
+-----------------------+ +--------------+
233+
| *| | |
234+
| | | |
235+
L | TL | R | |
236+
| | | |
237+
| | B | LB | T
238+
| | | |
239+
+-----------------------+ | |
240+
B | |
241+
| |
242+
| *|
243+
+--------------+
244+
R
245+
*/
184246
return anchor switch
185247
{
186248
AnchorPositionMode.Center => anchor,
@@ -200,44 +262,44 @@ private static AnchorPositionMode GetAnchor(
200262
},
201263
AnchorPositionMode.Left => orientation switch
202264
{
203-
ExifOrientationMode.TopRight or ExifOrientationMode.BottomRight => AnchorPositionMode.Right,
204-
ExifOrientationMode.LeftTop or ExifOrientationMode.LeftBottom => AnchorPositionMode.Bottom,
205-
ExifOrientationMode.RightTop or ExifOrientationMode.RightBottom => AnchorPositionMode.Top,
265+
ExifOrientationMode.TopRight or ExifOrientationMode.BottomLeft => AnchorPositionMode.Right,
266+
ExifOrientationMode.LeftTop or ExifOrientationMode.LeftBottom => AnchorPositionMode.Top,
267+
ExifOrientationMode.RightTop or ExifOrientationMode.RightBottom => AnchorPositionMode.Bottom,
206268
_ => anchor,
207269
},
208270
AnchorPositionMode.Right => orientation switch
209271
{
210-
ExifOrientationMode.TopRight or ExifOrientationMode.BottomRight => AnchorPositionMode.Left,
272+
ExifOrientationMode.TopRight or ExifOrientationMode.BottomLeft => AnchorPositionMode.Left,
211273
ExifOrientationMode.LeftTop or ExifOrientationMode.LeftBottom => AnchorPositionMode.Top,
212274
ExifOrientationMode.RightTop or ExifOrientationMode.RightBottom => AnchorPositionMode.Bottom,
213275
_ => anchor,
214276
},
215277
AnchorPositionMode.TopLeft => orientation switch
216278
{
217-
ExifOrientationMode.BottomLeft or ExifOrientationMode.LeftTop => AnchorPositionMode.BottomLeft,
218-
ExifOrientationMode.TopRight or ExifOrientationMode.RightBottom => AnchorPositionMode.TopRight,
219-
ExifOrientationMode.BottomRight or ExifOrientationMode.LeftBottom => AnchorPositionMode.BottomRight,
279+
ExifOrientationMode.TopRight or ExifOrientationMode.LeftBottom => AnchorPositionMode.TopRight,
280+
ExifOrientationMode.BottomRight or ExifOrientationMode.RightTop => AnchorPositionMode.BottomLeft,
281+
ExifOrientationMode.BottomLeft or ExifOrientationMode.RightBottom => AnchorPositionMode.BottomRight,
220282
_ => anchor,
221283
},
222284
AnchorPositionMode.TopRight => orientation switch
223285
{
224-
ExifOrientationMode.TopRight or ExifOrientationMode.LeftTop => AnchorPositionMode.TopLeft,
225-
ExifOrientationMode.BottomLeft or ExifOrientationMode.RightBottom => AnchorPositionMode.BottomRight,
226-
ExifOrientationMode.BottomRight or ExifOrientationMode.RightTop => AnchorPositionMode.BottomLeft,
286+
ExifOrientationMode.TopRight or ExifOrientationMode.RightTop => AnchorPositionMode.TopLeft,
287+
ExifOrientationMode.BottomRight or ExifOrientationMode.LeftBottom => AnchorPositionMode.BottomRight,
288+
ExifOrientationMode.BottomLeft or ExifOrientationMode.LeftTop => AnchorPositionMode.BottomLeft,
227289
_ => anchor,
228290
},
229291
AnchorPositionMode.BottomRight => orientation switch
230292
{
231-
ExifOrientationMode.TopRight or ExifOrientationMode.RightBottom => AnchorPositionMode.BottomLeft,
232-
ExifOrientationMode.BottomLeft or ExifOrientationMode.LeftTop => AnchorPositionMode.TopRight,
233-
ExifOrientationMode.BottomRight or ExifOrientationMode.LeftBottom => AnchorPositionMode.TopLeft,
293+
ExifOrientationMode.TopRight or ExifOrientationMode.LeftBottom => AnchorPositionMode.BottomLeft,
294+
ExifOrientationMode.BottomRight or ExifOrientationMode.RightTop => AnchorPositionMode.TopRight,
295+
ExifOrientationMode.BottomLeft or ExifOrientationMode.RightBottom => AnchorPositionMode.TopLeft,
234296
_ => anchor,
235297
},
236298
AnchorPositionMode.BottomLeft => orientation switch
237299
{
238-
ExifOrientationMode.TopRight or ExifOrientationMode.LeftTop => AnchorPositionMode.BottomRight,
239-
ExifOrientationMode.BottomLeft or ExifOrientationMode.RightBottom => AnchorPositionMode.TopLeft,
240-
ExifOrientationMode.BottomRight or ExifOrientationMode.RightTop => AnchorPositionMode.TopRight,
300+
ExifOrientationMode.TopRight or ExifOrientationMode.RightTop => AnchorPositionMode.BottomRight,
301+
ExifOrientationMode.BottomRight or ExifOrientationMode.LeftBottom => AnchorPositionMode.TopLeft,
302+
ExifOrientationMode.BottomLeft or ExifOrientationMode.LeftTop => AnchorPositionMode.TopRight,
241303
_ => anchor,
242304
},
243305
_ => anchor,

0 commit comments

Comments
 (0)