@@ -14,100 +14,61 @@ internal static partial class ImageProcessor
1414 public static partial async Task < Stream > RotateImageAsync ( Stream inputStream , string ? originalFileName )
1515 {
1616 using var data = NSData . FromStream ( inputStream ) ;
17- if ( data == null )
17+
18+ if ( data is null )
19+ {
1820 return inputStream ;
19-
21+ }
22+
2023 using var image = UIImage . LoadFromData ( data ) ;
2124
22- if ( image ? . CGImage == null )
25+ if ( image ? . CGImage is null )
26+ {
2327 return inputStream ;
28+ }
2429
2530 // Check if rotation is needed based on image orientation
2631 if ( image . Orientation == UIImageOrientation . Up )
32+ {
2733 return inputStream ;
34+ }
2835
29- // Get the size for the corrected orientation
30- var ( width , height ) = GetSizeForOrientation ( image ) ;
36+ // Create a new image with corrected orientation metadata (no pixel manipulation)
37+ // This preserves the original image data while fixing the display orientation
38+ var correctedImage = UIImage . FromImage ( image . CGImage , image . CurrentScale , UIImageOrientation . Up ) ;
3139
32- // Create a new image with correct orientation
33- var renderer = new UIGraphicsImageRenderer ( new CGSize ( width , height ) ) ;
34- var correctedImage = renderer . CreateImage ( ( context ) =>
35- {
36- ApplyOrientationTransformation ( context . CGContext , image , width , height ) ;
37- image . Draw ( new CGRect ( 0 , 0 , image . Size . Width , image . Size . Height ) ) ;
38- } ) ;
40+ // Write the corrected image back to a stream, preserving original quality
41+ var outputStream = new MemoryStream ( ) ;
3942
40- if ( correctedImage != null && correctedImage . CGImage != null )
43+ // Determine output format based on original file
44+ NSData ? imageData = null ;
45+ if ( ! string . IsNullOrEmpty ( originalFileName ) )
4146 {
42- // Create image with Up orientation
43- var finalImage = UIImage . FromImage ( correctedImage . CGImage , correctedImage . CurrentScale , UIImageOrientation . Up ) ;
44-
45- var outputStream = new MemoryStream ( ) ;
46- var imageData = finalImage . AsJPEG ( 1.0f ) ;
47- if ( imageData != null )
47+ var extension = Path . GetExtension ( originalFileName ) . ToLowerInvariant ( ) ;
48+ if ( extension == ".png" )
49+ {
50+ imageData = correctedImage . AsPNG ( ) ;
51+ }
52+ else
4853 {
49- await imageData . AsStream ( ) . CopyToAsync ( outputStream ) ;
50- outputStream . Position = 0 ;
51-
52- return outputStream ;
54+ // For JPEG and other formats, use maximum quality (1.0)
55+ // People can downscale themselves through the MediaPickerOptions
56+ imageData = correctedImage . AsJPEG ( 1f ) ;
5357 }
5458 }
55-
56- return inputStream ;
57- }
58-
59- static ( nfloat width , nfloat height ) GetSizeForOrientation ( UIImage image )
60- {
61- return image . Orientation switch
59+ else
6260 {
63- UIImageOrientation . Left or
64- UIImageOrientation . LeftMirrored or
65- UIImageOrientation . Right or
66- UIImageOrientation . RightMirrored => ( image . Size . Height , image . Size . Width ) ,
67- _ => ( image . Size . Width , image . Size . Height )
68- } ;
69- }
70-
71- static void ApplyOrientationTransformation ( CGContext context , UIImage image , nfloat width , nfloat height )
72- {
73- switch ( image . Orientation )
74- {
75- case UIImageOrientation . Down :
76- case UIImageOrientation . DownMirrored :
77- context . TranslateCTM ( width , height ) ;
78- context . RotateCTM ( ( nfloat ) Math . PI ) ;
79- break ;
80-
81- case UIImageOrientation . Left :
82- case UIImageOrientation . LeftMirrored :
83- context . TranslateCTM ( width , 0 ) ;
84- context . RotateCTM ( ( nfloat ) ( Math . PI / 2 ) ) ;
85- break ;
86-
87- case UIImageOrientation . Right :
88- case UIImageOrientation . RightMirrored :
89- context . TranslateCTM ( 0 , height ) ;
90- context . RotateCTM ( ( nfloat ) ( - Math . PI / 2 ) ) ;
91- break ;
92-
93- case UIImageOrientation . Up :
94- case UIImageOrientation . UpMirrored :
95- break ;
61+ // Default to JPEG with maximum quality (1.0)
62+ imageData = correctedImage . AsJPEG ( 1f ) ;
9663 }
97-
98- switch ( image . Orientation )
64+
65+ if ( imageData is not null )
9966 {
100- case UIImageOrientation . UpMirrored :
101- case UIImageOrientation . DownMirrored :
102- context . TranslateCTM ( width , 0 ) ;
103- context . ScaleCTM ( - 1 , 1 ) ;
104- break ;
105-
106- case UIImageOrientation . LeftMirrored :
107- case UIImageOrientation . RightMirrored :
108- context . TranslateCTM ( height , 0 ) ;
109- context . ScaleCTM ( - 1 , 1 ) ;
110- break ;
67+ await imageData . AsStream ( ) . CopyToAsync ( outputStream ) ;
68+ outputStream . Position = 0 ;
69+ return outputStream ;
11170 }
71+
72+ return inputStream ;
11273 }
11374}
0 commit comments