Xamarin表单 - 调整相机图片大小

use*_*879 6 xamarin.forms xamarin.forms.labs

有人帮助我使用xamarin表格实验室相机获取此代码:

picker = DependencyService.Get<IMediaPicker> ();  
                task = picker.TakePhotoAsync (new CameraMediaStorageOptions {
                    DefaultCamera = CameraDevice.Rear, 
                    MaxPixelDimension = 800,

                });

                img.BackgroundColor = Color.Gray;

                Device.StartTimer (TimeSpan.FromMilliseconds (250), () => {
                    if (task != null) {
                        if (task.Status == TaskStatus.RanToCompletion) {
                            Device.BeginInvokeOnMainThread (async () => {
                                //img.Source = ImageSource.FromStream (() => task.Result.Source);
                                var fileAccess = Resolver.Resolve<IFileAccess> ();
                                string imageName = "img_user_" + User.CurrentUser().id + "_" + DateTime.Now.ToString ("yy_MM_dd_HH_mm_ss") + ".jpg";
                                fileName = imageName;

                                fileAccess.WriteStream (imageName, task.Result.Source);
                                fileLocation = fileAccess.FullPath(imageName);

                                FileStream fileStream = new FileStream(fileAccess.FullPath(imageName), FileMode.Open, System.IO.FileAccess.Read);
                                imageUrl = (string)test[0]["url"];
                                img.Source = imageUrl;
                            }); 
                        }

                            return  task.Status != TaskStatus.Canceled
                            && task.Status != TaskStatus.Faulted
                            && task.Status != TaskStatus.RanToCompletion;
                    }
                    return true;
                });
Run Code Online (Sandbox Code Playgroud)

它可以保存图像,但手机拍照的实际尺寸很大,有没有办法调整尺寸.

Ste*_*rov 14

更新:原始答案没有用,请参阅下面的更新答案.问题是PCL库非常慢并且消耗了太多内存.

原始答案(不要使用):

我发现了一个图像I/O库,ImageTools-PCL,我在github上分叉并修剪了在Xamarin中无法编译的内容,将修改保持在最小,结果似乎有效.

要使用它,请下载链接的存储库,使用Xamarin进行编译,并将Build文件夹中的DLL添加到Forms项目中.

要调整图像大小,您可以执行此操作(应该适合您的问题的上下文)

var decoder = new   ImageTools.IO.Jpeg.JpegDecoder ();
ImageTools.ExtendedImage inImage = new ImageTools.ExtendedImage ();

decoder.Decode (inImage, task.Result.Source); 

var outImage = ImageTools.ExtendedImage.Resize (inImage, 1024, new ImageTools.Filtering.BilinearResizer ());

var encoder = new ImageTools.IO.Jpeg.JpegEncoder ();
encoder.Encode (outImage, fileAccess.CreateStream (imageName));


ImageSource imgSource = ImageSource.FromFile (fileAccess.FullPath (imageName));
Run Code Online (Sandbox Code Playgroud)

更新的答案:

从nuget获取Xamarin.XLabs,了解使用Resolver,使用Resize方法创建IImageService接口.

iOS的实现:

public class ImageServiceIOS: IImageService{
   public void ResizeImage(string sourceFile, string targetFile, float maxWidth, float maxHeight)
    {  
        if (File.Exists(sourceFile) && !File.Exists(targetFile))
        {
            using (UIImage sourceImage = UIImage.FromFile(sourceFile))
            {  
                var sourceSize = sourceImage.Size;
                var maxResizeFactor = Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);

                if (!Directory.Exists(Path.GetDirectoryName(targetFile)))
                    Directory.CreateDirectory(Path.GetDirectoryName(targetFile));

                if (maxResizeFactor > 0.9)
                {
                    File.Copy(sourceFile, targetFile);
                }
                else
                { 
                    var width = maxResizeFactor * sourceSize.Width;
                    var height = maxResizeFactor * sourceSize.Height;

                    UIGraphics.BeginImageContextWithOptions(new CGSize((float)width, (float)height), true, 1.0f);  
                    //  UIGraphics.GetCurrentContext().RotateCTM(90 / Math.PI);
                    sourceImage.Draw(new CGRect(0, 0, (float)width, (float)height)); 

                    var resultImage = UIGraphics.GetImageFromCurrentImageContext();
                    UIGraphics.EndImageContext();


                    if (targetFile.ToLower().EndsWith("png"))
                        resultImage.AsPNG().Save(targetFile, true);
                    else
                        resultImage.AsJPEG().Save(targetFile, true);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Android服务的实施:

public class ImageServiceDroid: IImageService{
public void ResizeImage(string sourceFile, string targetFile, float maxWidth, float maxHeight)
{ 
    if (!File.Exists(targetFile) && File.Exists(sourceFile))
    {   
        // First decode with inJustDecodeBounds=true to check dimensions
        var options = new BitmapFactory.Options()
        {
            InJustDecodeBounds = false,
            InPurgeable = true,
        };

        using (var image = BitmapFactory.DecodeFile(sourceFile, options))
        {  
            if (image != null)
            {
                var sourceSize = new Size((int)image.GetBitmapInfo().Height, (int)image.GetBitmapInfo().Width);

                var maxResizeFactor = Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);

                string targetDir = System.IO.Path.GetDirectoryName(targetFile);
                if (!Directory.Exists(targetDir))
                    Directory.CreateDirectory(targetDir);

                if (maxResizeFactor > 0.9)
                { 
                    File.Copy(sourceFile, targetFile);
                }
                else
                { 
                    var width = (int)(maxResizeFactor * sourceSize.Width);
                    var height = (int)(maxResizeFactor * sourceSize.Height);

                    using (var bitmapScaled = Bitmap.CreateScaledBitmap(image, height, width, true))
                    {
                        using (Stream outStream = File.Create(targetFile))
                        {
                            if (targetFile.ToLower().EndsWith("png"))
                                bitmapScaled.Compress(Bitmap.CompressFormat.Png, 100, outStream);
                            else
                                bitmapScaled.Compress(Bitmap.CompressFormat.Jpeg, 95, outStream);
                        }
                        bitmapScaled.Recycle();
                    }
                }

                image.Recycle();
            }
            else
                Log.E("Image scaling failed: " + sourceFile);
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*Jon 5

@Sten 的回答可能会在某些 android 设备上遇到内存不足问题。这是我实现ResizeImage功能的解决方案,这是根据谷歌的“有效加载大位图”文档:

public void ResizeImage (string sourceFile, string targetFile, int reqWidth, int reqHeight)
{ 
    if (!File.Exists (targetFile) && File.Exists (sourceFile)) {   
        var downImg = decodeSampledBitmapFromFile (sourceFile, reqWidth, reqHeight);
        using (var outStream = File.Create (targetFile)) {
            if (targetFile.ToLower ().EndsWith ("png"))
                downImg.Compress (Bitmap.CompressFormat.Png, 100, outStream);
            else
                downImg.Compress (Bitmap.CompressFormat.Jpeg, 95, outStream);
        }
        downImg.Recycle();
    }
}

public static Bitmap decodeSampledBitmapFromFile (string path, int reqWidth, int reqHeight)
{
    // First decode with inJustDecodeBounds=true to check dimensions
    var options = new BitmapFactory.Options ();
    options.InJustDecodeBounds = true;
    BitmapFactory.DecodeFile (path, options);

    // Calculate inSampleSize
    options.InSampleSize = calculateInSampleSize (options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.InJustDecodeBounds = false;
    return BitmapFactory.DecodeFile (path, options);
}

public static int calculateInSampleSize (BitmapFactory.Options options, int reqWidth, int reqHeight)
{
    // Raw height and width of image
    int height = options.OutHeight;
    int width = options.OutWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        int halfHeight = height / 2;
        int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
               && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}
Run Code Online (Sandbox Code Playgroud)