Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Xamarin Forms Android Image orientation changes after compress

ChaitanyaKulkarniChaitanyaKulkarni INMember ✭✭
edited September 2015 in Xamarin.Forms

I'm writing a Xamarin forms android application where I'm taking images from gallery. I want to upload those images to server, So I need byte[] from it. I'm scaling and compressing those images and then taking byte[] from it. My problem is when I compress the image, the image is changing it's orientation from portrait to landscape. I've tried by using 'ExifInterface' class and changing the image orientation but it's not working. Below is the my complete code :-

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

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

        byte[] data1 = ReadFully (mediafile.GetStream ());

        byte[] resizedImage = ResizeImageAndroid (data1, 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 = data1;

        System.Diagnostics.Debug.WriteLine (mediafile.Path);

        MessagingCenter.Send<IPictureTaker,string> (this, "picturetaken", mediafile.Path);
    } 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[] ResizeImageAndroid (byte[] imageData, float width, float height, MediaFile file)
            {
                try {
                    // Load the bitmap

        var options = new BitmapFactory.Options ();
        options.InJustDecodeBounds = true;

        // Calculate inSampleSize
        options.InSampleSize = calculateInSampleSize (options, (int)width, (int)height);
        // Decode bitmap with inSampleSize set
        options.InJustDecodeBounds = false;

        Bitmap originalImage = BitmapFactory.DecodeByteArray (imageData, 0, imageData.Length, options);
        Bitmap resizedImage = Bitmap.CreateScaledBitmap (originalImage, (int)width, (int)height, false);


        using (var ms = new MemoryStream ()) {

            resizedImage.Compress (Bitmap.CompressFormat.Png, 0, ms);
            resizedImage = changeOrientation (file, resizedImage);

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

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

    static Bitmap changeOrientation (MediaFile mediafile, Bitmap bitmap)
        {
            var exifInterface = new ExifInterface (mediafile.Path);
            int orientation = exifInterface.GetAttributeInt (ExifInterface.TagOrientation, 0);
            var matrix = new Matrix ();
            switch (orientation) {
                case 2:
                    matrix.SetScale (-1, 1);
                    break;
                case 3:
                    matrix.SetRotate (180);
                    break;
                case 4:
                    matrix.SetRotate (180);
                    matrix.PostScale (-1, 1);
                    break;
                case 5:
                    matrix.SetRotate (90);
                    matrix.PostScale (-1, 1);
                    break;
                case 6:
                    matrix.SetRotate (90);
                    break;
                case 7:
                    matrix.SetRotate (-90);
                    matrix.PostScale (-1, 1);
                    break;
                case 8:
                    matrix.SetRotate (-90);
                    break;
                default:
                    return bitmap;
                }

    try {
        Bitmap oriented = Bitmap.CreateBitmap (bitmap, 0, 0, bitmap.Width, bitmap.Height, matrix, true);
        bitmap.Recycle ();
        return oriented;
    } catch (OutOfMemoryError e) {
        e.PrintStackTrace ();
        return bitmap;
    } catch (System.Exception e) {
        System.Diagnostics.Debug.WriteLine (e.Message);
        return bitmap;
    }
}

`

Answers

  • adamkempadamkemp USInsider, Developer Group Leader mod

    Looking at this code:

    using (var ms = new MemoryStream ()) {

            resizedImage.Compress (Bitmap.CompressFormat.Png, 0, ms);
            resizedImage = changeOrientation (file, resizedImage);
    
            return ms.ToArray ();
        }
    

    It looks like the orientation change affects the resizedImage only after you get the bytes of the compressed (original) image. Move the orientation change before the compression.

Sign In or Register to comment.