Xamarin forms an Android image does not shrink

I am working on a xamarin forms project. I take images from the gallery and upload them to the server. My back-end is parsing where we cannot upload files larger than 1 MB. So, I am trying to compress the image so that each time the image size is less than 1 MB. Below is my code: -

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

But the problem is that my image is not compressed. I cannot upload an image of size = 2 MB, and I want to upload images of at least 30 MB in size. I also noticed that calculateInSampleSize always returns 16 as inSampleSize, which by default matters.

Please let me know if there are any problems in my code.

+4
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, , , while.

, , , Jpeg , png.

0

Source: https://habr.com/ru/post/1608980/


All Articles