diff --git a/src/Essentials/src/MediaPicker/MediaPicker.android.cs b/src/Essentials/src/MediaPicker/MediaPicker.android.cs index 5632c51ad6f3..08a3de2da51b 100644 --- a/src/Essentials/src/MediaPicker/MediaPicker.android.cs +++ b/src/Essentials/src/MediaPicker/MediaPicker.android.cs @@ -23,6 +23,20 @@ partial class MediaPickerImplementation : IMediaPicker public bool IsCaptureSupported => Application.Context?.PackageManager?.HasSystemFeature(PackageManager.FeatureCameraAny) ?? false; + static async Task RotateImageInPlace(string filePath, MediaPickerOptions options) + { + using var inputStream = File.OpenRead(filePath); + var fileName = System.IO.Path.GetFileName(filePath); + using var rotatedStream = await ImageProcessor.RotateImageAsync(inputStream, fileName); + rotatedStream.Position = 0; + inputStream.Dispose(); // explicit close before delete + try + { File.Delete(filePath); } + catch { } + using var outputStream = File.Create(filePath); + await rotatedStream.CopyToAsync(outputStream); + } + internal static bool IsPhotoPickerAvailable => PickVisualMedia.InvokeIsPhotoPickerAvailable(Platform.AppContext); @@ -85,30 +99,10 @@ public async Task CaptureAsync(MediaPickerOptions options, bool phot if (photo) { captureResult = await CapturePhotoAsync(captureIntent); - // Apply rotation if needed for photos - if (captureResult is not null && ImageProcessor.IsRotationNeeded(options)) - { - using var inputStream = File.OpenRead(captureResult); - var fileName = System.IO.Path.GetFileName(captureResult); - using var rotatedStream = await ImageProcessor.RotateImageAsync(inputStream, fileName); - - var rotatedPath = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(captureResult), - System.IO.Path.GetFileNameWithoutExtension(captureResult) + "_rotated" + System.IO.Path.GetExtension(captureResult)); - - using var outputStream = File.Create(rotatedPath); - rotatedStream.Position = 0; - await rotatedStream.CopyToAsync(outputStream); - - // Use the rotated image and delete the original - try - { - File.Delete(captureResult); - } - catch { } - captureResult = rotatedPath; - } - + // Apply rotation if needed for photos + if (captureResult is not null && ImageProcessor.IsRotationNeeded(options)) + await RotateImageInPlace(captureResult, options); + // Apply compression/resizing if needed for photos if (captureResult is not null && ImageProcessor.IsProcessingNeeded(options?.MaximumWidth, options?.MaximumHeight, options?.CompressionQuality ?? 100)) { @@ -161,22 +155,7 @@ void OnResult(Intent intent) { // Apply rotation if needed if (ImageProcessor.IsRotationNeeded(options)) - { - using var inputStream = File.OpenRead(path); - var fileName = System.IO.Path.GetFileName(path); - using var rotatedStream = await ImageProcessor.RotateImageAsync(inputStream, fileName); - - var rotatedPath = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(path), - System.IO.Path.GetFileNameWithoutExtension(path) + "_rotated" + System.IO.Path.GetExtension(path)); - - using var outputStream = File.Create(rotatedPath); - rotatedStream.Position = 0; - await rotatedStream.CopyToAsync(outputStream); - - // Use the rotated image - path = rotatedPath; - } + await RotateImageInPlace(path, options); // Apply compression/resizing if needed if (ImageProcessor.IsProcessingNeeded(options?.MaximumWidth, options?.MaximumHeight, options?.CompressionQuality ?? 100)) @@ -184,7 +163,7 @@ void OnResult(Intent intent) path = await CompressImageIfNeeded(path, options); } } - + return new FileResult(path); } @@ -215,22 +194,7 @@ async Task PickUsingPhotoPicker(MediaPickerOptions options, bool pho { // Apply rotation if needed if (ImageProcessor.IsRotationNeeded(options)) - { - using var inputStream = File.OpenRead(path); - var fileName = System.IO.Path.GetFileName(path); - using var rotatedStream = await ImageProcessor.RotateImageAsync(inputStream, fileName); - - var rotatedPath = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(path), - System.IO.Path.GetFileNameWithoutExtension(path) + "_rotated" + System.IO.Path.GetExtension(path)); - - using var outputStream = File.Create(rotatedPath); - rotatedStream.Position = 0; - await rotatedStream.CopyToAsync(outputStream); - - // Use the rotated image - path = rotatedPath; - } + await RotateImageInPlace(path, options); // Apply compression/resizing if needed if (ImageProcessor.IsProcessingNeeded(options?.MaximumWidth, options?.MaximumHeight, options?.CompressionQuality ?? 100)) @@ -281,27 +245,12 @@ async Task> PickMultipleUsingPhotoPicker(MediaPickerOptions opt if (!uri?.Equals(AndroidUri.Empty) ?? false) { var path = FileSystemUtils.EnsurePhysicalPath(uri); - + if (photo) { // Apply rotation if needed if (ImageProcessor.IsRotationNeeded(options)) - { - using var inputStream = File.OpenRead(path); - var fileName = System.IO.Path.GetFileName(path); - using var rotatedStream = await ImageProcessor.RotateImageAsync(inputStream, fileName); - - var rotatedPath = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(path), - System.IO.Path.GetFileNameWithoutExtension(path) + "_rotated" + System.IO.Path.GetExtension(path)); - - using var outputStream = File.Create(rotatedPath); - rotatedStream.Position = 0; - await rotatedStream.CopyToAsync(outputStream); - - // Use the rotated image - path = rotatedPath; - } + await RotateImageInPlace(path, options); // Apply compression/resizing if needed if (ImageProcessor.IsProcessingNeeded(options?.MaximumWidth, options?.MaximumHeight, options?.CompressionQuality ?? 100)) @@ -368,21 +317,29 @@ static async Task CompressImageIfNeeded(string imagePath, MediaPickerOpt if (processedStream != null) { - // Determine output extension based on processed data and original filename + // Determine the correct output extension based on the processed format + processedStream.Position = 0; var outputExtension = ImageProcessor.DetermineOutputExtension(processedStream, options?.CompressionQuality ?? 100, inputFileName); - var processedFileName = System.IO.Path.GetFileNameWithoutExtension(imagePath) + "_processed" + outputExtension; - var processedPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(imagePath), processedFileName); + var originalExtension = System.IO.Path.GetExtension(imagePath); - // Write processed image to file - using var outputStream = File.Create(processedPath); - processedStream.Position = 0; - await processedStream.CopyToAsync(outputStream); + // If format changed (e.g., PNG -> JPEG), use new extension + string outputPath = imagePath; + if (!string.Equals(outputExtension, originalExtension, StringComparison.OrdinalIgnoreCase)) + { + outputPath = System.IO.Path.ChangeExtension(imagePath, outputExtension); + } - // Delete original file + // Delete original file first try { originalFile.Delete(); } catch { } - return processedPath; + + // Write processed image to output path with correct extension + using var outputStream = File.Create(outputPath); + processedStream.Position = 0; + await processedStream.CopyToAsync(outputStream); + + return outputPath; } // If ImageProcessor returns null (e.g., on .NET Standard), ImageProcessor.IsProcessingNeeded would have returned false, @@ -481,32 +438,17 @@ void OnResult(Intent resultIntent) foreach (var path in tempResultList) { string processedPath = path; - + // Apply rotation if needed if (ImageProcessor.IsRotationNeeded(options)) - { - using var inputStream = File.OpenRead(processedPath); - var fileName = System.IO.Path.GetFileName(processedPath); - using var rotatedStream = await ImageProcessor.RotateImageAsync(inputStream, fileName); - - var rotatedPath = System.IO.Path.Combine( - System.IO.Path.GetDirectoryName(processedPath), - System.IO.Path.GetFileNameWithoutExtension(processedPath) + "_rotated" + System.IO.Path.GetExtension(processedPath)); - - using var outputStream = File.Create(rotatedPath); - rotatedStream.Position = 0; - await rotatedStream.CopyToAsync(outputStream); - - // Use the rotated image - processedPath = rotatedPath; - } + await RotateImageInPlace(processedPath, options); // Apply compression/resizing if needed if (ImageProcessor.IsProcessingNeeded(options?.MaximumWidth, options?.MaximumHeight, options?.CompressionQuality ?? 100)) { processedPath = await CompressImageIfNeeded(processedPath, options); } - + resultList.Add(new FileResult(processedPath)); } }