.NET MAUI 在保存到相册之前,从相机中缩小图像。

huangapple go评论73阅读模式
英文:

.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&lt;byte[]&gt; ResizePhotoStream(FileResult photo)
        {
            byte[] result = null;

            using (var stream = await photo.OpenReadAsync())
            {
                if (stream.Length &gt; _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;
        }

huangapple
  • 本文由 发表于 2023年5月25日 08:18:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76328144.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定