英文:
.NET MAUI Downsize image from camera before saving to gallery
问题
我试图摸索着制作一个跨平台相机应用程序在 .Net MAUI 中。
我已经实现了我想要的一切,但最后一步是在保存之前使应用程序调整图像大小。
我正在尝试理解如何使用 Microsoft.Maui.Graphics,但我对 C# 的理解还有一些不足,让我无法理解。
这是我用来捕获和保存图像的方法。我认为我需要在保存之前对捕获的流使用 Downsize 方法来调整大小,但无论我尝试什么,都会出现错误。
async void Button_Clicked(object sender, EventArgs e)
{
var result = await MediaPicker.CapturePhotoAsync();
setAsset();
if (result != null)
{
using var stream = await result.OpenReadAsync();
using var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
stream.Position = 0;
memoryStream.Position = 0;
var fName = projID.Text + "-"+ assID.Text + "-"+ wDetail.Text + ".jpg";
// 以下是不同平台的保存逻辑
// ...
// (代码中的平台相关逻辑,根据不同平台选择对应操作)
// ...
fileSaveLoc.Text = fName;
await GetCurrentLocation();
if (latlong != null)
{
double lat = Math.Round(latlong.Latitude, 6);
double lng = Math.Round(latlong.Longitude, 6);
latlngRes.Text = lat.ToString() + " : " + lng.ToString();
}
else
{
latlngRes.Text = "Unable to Retreive Location";
}
}
}
这似乎很简单,但我无法将其集成到我的现有代码中。
using Microsoft.Maui.Graphics.Platform;
...
IImage image;
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
{
image = PlatformImage.FromStream(stream);
}
// 将图像保存到内存流
if (image != null)
{
IImage newImage = image.Downsize(150, true);
using (MemoryStream memStream = new MemoryStream())
{
newImage.Save(memStream);
}
}
任何帮助将不胜感激。
我猜想将现有的 memoryStream 转换为 IImage 是关键,但我该如何做呢?
...
stream.CopyTo(memoryStream);
stream.Position = 0;
memoryStream.Position = 0;
IImage image;
// 在这里将 memoryStream 转换为 image
if (image != null)
{
IImage newImage = image.Downsize(150, true);
using (MemoryStream memStream = new MemoryStream())
{
newImage.Save(memStream);
}
}
// 继续并保存 memStream 以继续保存到手机相册
...
英文:
I'm trying to bumble my way through making a cross platform camera app in .Net MAUI.
I've achieved everything I want so far, but the last step is having the app resize the image before saving.
I'm trying to understand how to use Microsoft.Maui.Graphics but there's just enough missing from my understanding of C# to have it elude me.
https://learn.microsoft.com/en-us/dotnet/maui/user-interface/graphics/images
This is what I have to capture and save the image. I presume I need to use Downsize on the captured stream before saving, but it doesn't seem to matter what I try, I just get errors.
async void Button_Clicked(object sender, EventArgs e)
{
var result = await MediaPicker.CapturePhotoAsync();
setAsset();
if (result != null)
{
using var stream = await result.OpenReadAsync();
using var memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
stream.Position = 0;
memoryStream.Position = 0;
var fName = projID.Text + "-" + assID.Text + "-" + wDetail.Text + ".jpg";
#if WINDOWS
//await System.IO.File.WriteAllBytesAsync(@"C:\Users\dentk\Desktop\VenPhotos\" + fName, memoryStream.ToArray);
#elif ANDROID
var context = Platform.CurrentActivity;
if (OperatingSystem.IsAndroidVersionAtLeast(29))
{
Android.Content.ContentResolver resolver = context.ContentResolver;
Android.Content.ContentValues contentValues = new();
contentValues.Put(Android.Provider.MediaStore.IMediaColumns.DisplayName, fName);
contentValues.Put(Android.Provider.MediaStore.IMediaColumns.MimeType, "image/jpg");
contentValues.Put(Android.Provider.MediaStore.IMediaColumns.RelativePath, "DCIM/" + "test");
Android.Net.Uri imageUri = resolver.Insert(Android.Provider.MediaStore.Images.Media.ExternalContentUri, contentValues);
var os = resolver.OpenOutputStream(imageUri);
Android.Graphics.BitmapFactory.Options options = new();
options.InJustDecodeBounds = true;
var bitmap = Android.Graphics.BitmapFactory.DecodeStream(stream);
bitmap.Compress(Android.Graphics.Bitmap.CompressFormat.Jpeg, 60, os);
os.Flush();
os.Close();
}
else
{
Java.IO.File storagePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
string pathIO = System.IO.Path.Combine(storagePath.ToString(), fName);
System.IO.File.WriteAllBytes(pathIO, memoryStream.ToArray());
var mediaScanIntent = new Android.Content.Intent(Android.Content.Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(pathIO)));
context.SendBroadcast(mediaScanIntent);
}
#elif IOS || MACCATALYST
var image = new UIKit.UIImage(Foundation.NSData.FromArray(memoryStream.ToArray()));
image.SaveToPhotosAlbum((image, error) =>
{
});
#endif
fileSaveLoc.Text = fName;
await GetCurrentLocation();
if (latlong != null)
{
double lat = Math.Round(latlong.Latitude, 6);
double lng = Math.Round(latlong.Longitude, 6);
latlngRes.Text = lat.ToString() + " : " + lng.ToString();
}
else
{
latlngRes.Text = "Unable to Retreive Location";
}
}
}
This seems so straightforward, but I just cannot get it integrated into my existing code:
using Microsoft.Maui.Graphics.Platform;
...
IImage image;
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("GraphicsViewDemos.Resources.Images.dotnet_bot.png"))
{
image = PlatformImage.FromStream(stream);
}
// Save image to a memory stream
if (image != null)
{
IImage newImage = image.Downsize(150, true);
using (MemoryStream memStream = new MemoryStream())
{
newImage.Save(memStream);
}
}
Any help would be greatly appreciated.
I'm guessing getting the existing memoryStream into an IImage is the key, but how do I do that?
......
stream.CopyTo(memoryStream);
stream.Position = 0;
memoryStream.Position = 0;
IImage image;
// something here to get memoryStream into image
if (image != null)
{
IImage newImage = image.Downsize(150, true);
using (MemoryStream memStream = new MemoryStream())
{
newImage.Save(memStream);
}
}
// something to continue and save memStream to continue on and save into the phones gallery
......
答案1
得分: 1
I needed something similar, wasn't able to get exact compression but if the image was larger than a certain size then I downsized it to a max resolution
private async Task<byte[]> ResizePhotoStream(FileResult photo)
{
byte[] result = null;
using (var stream = await photo.OpenReadAsync())
{
if (stream.Length > _imageMaxSizeBytes)
{
var image = PlatformImage.FromStream(stream);
if (image != null)
{
var newImage = image.Downsize(_imageMaxResolution, true);
result = newImage.AsBytes();
}
}
else
{
using (var binaryReader = new BinaryReader(stream))
{
result = binaryReader.ReadBytes((int)stream.Length);
}
}
}
return result;
}
英文:
I needed something similar, wasn't able to get exact compression but if the image was larger than a certain size then I downsized it to a max resolution
private async Task<byte[]> ResizePhotoStream(FileResult photo)
{
byte[] result = null;
using (var stream = await photo.OpenReadAsync())
{
if (stream.Length > _imageMaxSizeBytes)
{
var image = PlatformImage.FromStream(stream);
if (image != null)
{
var newImage = image.Downsize(_imageMaxResolution, true);
result = newImage.AsBytes();
}
}
else
{
using (var binaryReader = new BinaryReader(stream))
{
result = binaryReader.ReadBytes((int)stream.Length);
}
}
}
return result;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论