【问题标题】:Xamarin forms android image is not getting compressedXamarin 表单 android 图像未压缩
【发布时间】:2015-09-25 11:48:24
【问题描述】:

我正在开发 xamarin 表单项目。我正在从图库中获取图像并将其上传到服务器。我的后端是解析后端,我们无法上传大小超过 1MB 的文件。所以,我正在尝试压缩图像,以便每次图像大小小于 1MB。 下面提到的是我的代码:-

protected override async void OnActivityResult (int requestCode, Result resultCode, Intent intent)
    {
        if (resultCode == Result.Canceled)
            return;

        try {
            var mediafile = await intent.GetMediaFileExtraAsync (Forms.Context);

            // get byte[] from file stream
            byte[] byteData = ReadFully (mediafile.GetStream ());

            byte[] resizedImage = ResizeAndCompressImage (byteData, 60, 60, mediafile);

            var imageStream = new ByteArrayContent (resizedImage);
            imageStream.Headers.ContentDisposition = new ContentDispositionHeaderValue ("attachment") {
                FileName = Guid.NewGuid () + ".Png"
            };

            var multi = new MultipartContent ();
            multi.Add (imageStream);
            HealthcareProfessionalDataClass lDataClass = HealthcareProfessionalDataClass.Instance;
            lDataClass.Thumbnail = multi;
            App.mByteArrayOfImage = byteData;

            MessagingCenter.Send<IPictureTaker,string> (this, "picturetaken", mediafile.Path);
        } catch (InvocationTargetException e) {
            e.PrintStackTrace ();
        } catch (Java.Lang.Exception e) {
            e.PrintStackTrace ();
        }
    }

public static byte[] ReadFully (System.IO.Stream input)
    {
        using (var ms = new MemoryStream ()) {
            input.CopyTo (ms);
            return ms.ToArray ();
        }
    }


public static byte[] ResizeAndCompressImage (byte[] imageData, float width, float height, MediaFile file)
    {
        try {
            // Load the bitmap
            var options = new BitmapFactory.Options ();
            options.InJustDecodeBounds = true;
            options.InMutable = true;
            BitmapFactory.DecodeFile (file.Path, options);
            // Calculate inSampleSize
            options.InSampleSize = calculateInSampleSize (options, (int)width, (int)height);
            // Decode bitmap with inSampleSize set
            options.InJustDecodeBounds = false;

            var originalBitMap = BitmapFactory.DecodeByteArray (imageData, 0, imageData.Length, options);

            var resizedBitMap = Bitmap.CreateScaledBitmap (originalBitMap, (int)width, (int)height, false);

            if (originalBitMap != null) {
                originalBitMap.Recycle ();
                originalBitMap = null;
            }
            using (var ms = new MemoryStream ()) {

                resizedBitMap.Compress (Bitmap.CompressFormat.Png, 0, ms);

                if (resizedBitMap != null) {
                    resizedBitMap.Recycle ();
                    resizedBitMap = null;
                }
                return ms.ToArray ();
            }
        } catch (Java.Lang.Exception e) {
            e.PrintStackTrace ();
            return null;
        }
    }

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 = 16;

        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;
    }

但问题是我的图像没有被压缩。我无法上传大小 = 2MB 的图像,我想上传大小至少为 30 MB 的图像。我还观察到,calculateInSampleSize 总是返回 16 作为默认值 inSampleSize。

如果我的代码有任何问题,请告诉我。

【问题讨论】:

标签: android xamarin xamarin.android android-bitmap bitmapfactory


【解决方案1】:

这似乎是一种非常复杂且令人费解的方式。这是一个更简洁的示例,可以帮助您调整图像大小:

protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    var stream = this.Resize(data.Data, 60, 60);
    // Send the stream to Parse
}

private Stream Resize(Android.Net.Uri uri, float maxWidth, float maxHeight)
{
    var scale = 1;
    using (var rawStream = this.ContentResolver.OpenInputStream(f))
    using (var options = new BitmapFactory.Options { InJustDecodeBounds = true })
    {
        BitmapFactory.DecodeStream(rawStream, null, options);

        while(options.OutWidth / scale / 2 > maxWidth || 
              options.OutHeight / scale / 2 > maxHeight)
        {
            scale *= 2;
        }
    }

    using (var options = new BitmapFactory.Options { InSampleSize = scale })
    using (var bitmap = f.GetBitmap(options))
    {
        var memoryStream = new MemoryStream();
        bitmap.Compress(Bitmap.CompressFormat.Png, 0, memoryStream);
        memoryStream.Position = 0;

        return memoryStream;
    }
}

关于您看到InSampleSize = 16 的原因,我的猜测是您的图像的高度或宽度小于1920(即60 * 2 * 16),并且由于您在while 循环中使用&amp;&amp;,因此需要更多检查side 失败,因此,您永远不会进入 while 正文。

此外,如果您希望创建较小的图像,将它们压缩为 Jpeg 是一种比使用 png 更好的方法。

【讨论】:

    猜你喜欢
    • 2015-12-10
    • 1970-01-01
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 2011-09-21
    • 2019-01-22
    • 1970-01-01
    • 2020-06-10
    相关资源
    最近更新 更多