Xamarin表单android图像没有被压缩

时间:2015-09-25 11:48:24

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

我正在研究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是默认值。

如果我的代码中存在任何问题,请与我们联系。

1 个答案:

答案 0 :(得分:0)

这似乎是一种非常复杂和复杂的做法。这是一个更简洁的示例,可以帮助您调整图像大小:

CREATE FUNCTION array_distinct(
      anyarray, -- input array 
      boolean DEFAULT false -- flag to ignore nulls
) RETURNS anyarray AS $f$
      SELECT array_agg(DISTINCT x) 
      FROM unnest($1) t(x) 
      WHERE CASE WHEN $2 THEN x IS NOT NULL ELSE true END;
$f$ LANGUAGE SQL IMMUTABLE;

关于您看到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; } } 的原因,我的猜测是您的图片的高度或宽度小于1920(InSampleSize = 16),因为您使用的是60 * 2 * 16在while循环中,对该方的更大检查失败,因此,您永远不会进入while主体。

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