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.