0

I´m working in a mobile app (developed in xamarin for android) able to stream data from the camera, take the picture and save it in the memory. The app works but there´s something strange when it is deployed in different smartphones, as is showed in the next pictures.

These are the screenshots of the stream view when the app is installed in a samsung (S7, S6, S7 edge) and an alcatel (Pop 2) smartphone It looks as it supose to be, but as you are going to see, in others cellphones like an Asus Zefone go and a sony xperia Z1 the image looks weird, like if the shape of the objects would be changing :

App Screenshots in Asus and Sony It´s difficult to explain, but this changes appears when I turn the phone from Vertically mode (Portrait) to Horizontally mode (landscape) All this, with the rotation screen feature disabled. It looks like some kind of distortion in the image because initially (Vertically mode),the objects looks more "Extended", and finally (turning the phone to horizontally mode) they looks shorter and fatter than how they looks originally.

This is the AXML code of the view:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1">
    <TextureView
        android:id="@+id/textureView"
        android:scaleType="fitXY"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/takePhotoButton"
        android:layout_width="65dp"
        android:layout_height="65dp"
        android:layout_marginBottom="15dp"
        android:layout_gravity="center|bottom"
        android:background="@drawable/TakePhotoButton" />
    <ToggleButton
        android:textOff=""
        android:textOn=""
        android:checked="false"
        android:layout_width="37dp"
        android:layout_height="37dp"
        android:layout_gravity="top|left"
        android:layout_marginLeft="25dp"
        android:layout_marginTop="25dp"
        android:id="@+id/toggleFlashButton"
        android:background="@drawable/FlashButton" />
</FrameLayout>

this is the class:

namespace CameraStream
{
    [Activity(Label = "CameraStream", MainLauncher = true, Icon = "@drawable/SendButton", Theme = "@android:style/Theme.NoTitleBar")]
    public class Activity1 : Activity, TextureView.ISurfaceTextureListener, IPictureCallback        
    {
        Android.Hardware.Camera _camera;

        TextureView _textureView;
        Button TakePictureBtn;
        ToggleButton FlashBtn;
        Bitmap UserPicture;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.Main);
            _textureView = FindViewById<TextureView>(Resource.Id.textureView);
            _textureView.SurfaceTextureListener = this;
            TakePictureBtn = FindViewById<Button>(Resource.Id.takePhotoButton);
            TakePictureBtn.Click += TakePicture_Click;
            FlashBtn = FindViewById<ToggleButton>(Resource.Id.toggleFlashButton);
            FlashBtn.CheckedChange += Flash_Click;
        }
        private void Flash_Click(object sender, CompoundButton.CheckedChangeEventArgs e)
        {
            Globals g = Globals.getInstance;
            Android.Hardware.Camera.Parameters param = _camera.GetParameters();
            if (e.IsChecked)
            {
                g.SetFlash(true);
                FlashBtn.SetBackgroundResource(Resource.Drawable.NoFlashButton);
                param.FlashMode = Android.Hardware.Camera.Parameters.FlashModeOn;
                _camera.SetParameters(param);
            }
            else
            {
                g.SetFlash(false);
                FlashBtn.SetBackgroundResource(Resource.Drawable.FlashButton);
                param.FlashMode = Android.Hardware.Camera.Parameters.FlashModeOff;
                _camera.SetParameters(param);
            }
        }
        private void TakePicture_Click(object sender, EventArgs e)
        {
            _camera.TakePicture(null, null, this);         
        }

        public void OnSurfaceTextureAvailable(Android.Graphics.SurfaceTexture surface, int w, int h)
        {
            Globals g = Globals.getInstance;
            bool flash = g.GetFlash();
            _camera = Android.Hardware.Camera.Open();
            _camera.SetDisplayOrientation(90);
            Android.Hardware.Camera.Parameters param = _camera.GetParameters();
            Android.Hardware.Camera.Size sizePicture = getBestPreviewSize(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
            param.Zoom = 0;
            param.FocusMode = Android.Hardware.Camera.Parameters.FocusModeContinuousPicture;
            param.SetPictureSize(sizePicture.Width, sizePicture.Height);
            param.FlashMode = Android.Hardware.Camera.Parameters.FlashModeOff;
            if (flash)
                param.FlashMode = Android.Hardware.Camera.Parameters.FlashModeOn;
            else
                param.FlashMode = Android.Hardware.Camera.Parameters.FlashModeOff;
            _camera.SetParameters(param);
            try
            {
                _camera.SetPreviewTexture(surface);
                _camera.StartPreview();
            }
            catch (Java.IO.IOException ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        private Android.Hardware.Camera.Size getBestPreviewSize(int width, int height)
        {
            Android.Hardware.Camera.Size result = null;
            Android.Hardware.Camera.Parameters p = _camera.GetParameters();
            IList<Android.Hardware.Camera.Size> Sizes = p.SupportedPictureSizes;
            foreach (Android.Hardware.Camera.Size size in Sizes)
            {
                if (size.Width <= width && size.Height <= height)
                {
                    if (result == null)
                    {
                        result = size;
                    }
                    else
                    {
                        int resultArea = result.Width * result.Height;
                        int newArea = size.Width * size.Height;

                        if (newArea > resultArea)
                        {
                            result = size;
                        }
                    }
                }
            }
            return result;
        }
        public bool OnSurfaceTextureDestroyed(Android.Graphics.SurfaceTexture surface)
        {
            _camera.StopPreview();
            _camera.Release();

            return true;
        }
        public void OnSurfaceTextureSizeChanged(Android.Graphics.SurfaceTexture surface, int width, int height)
        {
            _camera.StopPreview();
            _camera.SetPreviewTexture(surface);
            _camera.StartPreview();
        }
        public void OnSurfaceTextureUpdated(Android.Graphics.SurfaceTexture surface)
        {
        }
        public void OnPictureTaken(byte[] data, Android.Hardware.Camera camera)
        {
            _camera.StopPreview();
            Bitmap picture = BitmapFactory.DecodeByteArray(data, 0, data.Length);
            UserPicture = RotateBitmap(picture,90);
            Globals g = Globals.getInstance;
            g.SetPicture(UserPicture);
            Intent PictureActivity = new Intent(this, typeof(PictureActivity));
            this.StartActivity(PictureActivity);
            _camera.StartPreview();
        }
        public static Bitmap RotateBitmap(Bitmap source, float angle)
        {
            Matrix matrix = new Matrix();
            matrix.PostRotate(angle);
            return Bitmap.CreateBitmap(source, 0, 0, source.Width, source.Height, matrix, true);
        }
    }
}

Thanks for your help.

  • `fitXY` can distort the aspect ratio, you should obtain what camera's preview sizes are available and resize your textureview to match or use the textview to crop to actual camera's preview. – SushiHangover Apr 07 '17 at 18:39
  • @ SushiHangover I have already tried to resize the texture view with _textureView.LayoutParameters = new FrameLayout.LayoutParams(w,h); where w and h are sizePicture.Widht and sizePicture.Height but it did not work Also I have changed the android:scaleType="fitXY" to the line android:scaleType="centerCrop" but it did not work neither – Camilo Andres Gamarra Apr 08 '17 at 19:11
  • You should obtain the camera's supported preview sizes that are available and use one of those based upon your device's resolution and how you need to present the TextureView in your UI. Also remember different device manufactures rotate their camera chips 90 degrees and thus you have to deal with landscape/portait/aspect ratio/... issues yourself and take that into consideration when you are scaling and/or rotating the "preview" you are given. – SushiHangover Apr 08 '17 at 19:15

0 Answers0