问题
I have a xamarin.android project which have a custom camera Preview. Whenever I initialize the camera , it will open as landscape default. So I changed the orientation from SurfaceChanged
method like this.
private int setCameraDisplayOrientation(Activity mContext, int v)
{
var degrees = 0;
var orientation =0;
Display display = mContext.GetSystemService(Context.WindowService).JavaCast<IWindowManager>().DefaultDisplay;
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.GetCameraInfo(v, info);
var rotation = windowManager.DefaultDisplay.Rotation;
DisplayMetrics dm = new DisplayMetrics();
display.GetMetrics(dm);
int width = dm.WidthPixels;
int height = dm.HeightPixels;
//Natural orientation is portrait
if ((rotation == SurfaceOrientation.Rotation0 || rotation == SurfaceOrientation.Rotation180) && height > width ||
(rotation == SurfaceOrientation.Rotation90 || rotation == SurfaceOrientation.Rotation270) && width > height)
{
switch (rotation)
{
case SurfaceOrientation.Rotation0:
degrees = 90;
break;
case SurfaceOrientation.Rotation90:
degrees = 0;
break;
case SurfaceOrientation.Rotation180:
degrees = 270;
break;
case SurfaceOrientation.Rotation270:
degrees = 180;
break;
}
}
return (degrees);
}
It works fine. It will arrange both front and back camera in portrait.
The problem
When I capture photo, in some devices, it will store in landscape mode in some devices it will store portrait. I want the image to be in portrait mode no matter what. In order do that I tried to get the Exif
data of image and rotate it to portrait mode accordingly. But in some devices like samsung, VIVO the orientation value gets as "0". I don't know what to do with that value. If I PreRotate
90 , then some devices will solve this issue, while other will save the photo upwards.
**Managing Rotation**
Android.Graphics.Bitmap loadAndResizeBitmap(string filePath)
{
Android.Graphics.Bitmap resizedBitmap = Android.Graphics.BitmapFactory.DecodeFile(filePath);
ExifInterface exif = null;
try
{
exif = new ExifInterface(filePath);
string orientation = exif.GetAttribute(ExifInterface.TagOrientation);
Android.Graphics.Matrix matrix = new Android.Graphics.Matrix();
switch (orientation)
{
case "1":
matrix.PreRotate(-90);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "3":
matrix.PreRotate(180);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "4":
matrix.PreRotate(180);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "5":
matrix.PreRotate(90);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "6": // portrait
matrix.PreRotate(90);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "7":
matrix.PreRotate(-90);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "8":
matrix.PreRotate(-90);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
case "0":
matrix.PreRotate(-90);
resizedBitmap = Android.Graphics.Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, matrix, false);
matrix.Dispose();
matrix = null;
break;
}
return resizedBitmap;
}
catch (IOException ex)
{
return null;
}
}
I got this Idea from Xamarin.Andoid Image rotation. But somehow I cant relay on it. What will be the problem? Should I pass Stream instead of file path? Does it due to the surfaceview rotation? How can I make the captured image portrait no matter what on any device? Any help is appreciated.
回答1:
Only for Xamarin.Android, call it in shared project using dependency service
Get the Angle of rotation of image by this.
public int GetImageRotation(string filePath)
{
try
{
ExifInterface ei = new ExifInterface(filePath);
Orientation orientation = (Orientation)ei.GetAttributeInt(ExifInterface.TagOrientation, (int)Orientation.Undefined);
switch (orientation)
{
case Orientation.Rotate90:
return 90;
case Orientation.Rotate180:
return 180;
case Orientation.Rotate270:
return 270;
default:
return 0;
}
}
catch(Exception ex)
{
return 0;
}
}
Now Rotate the image according to the angle value you get.
I perform operation on stream rather than the actual file & return in the form of Byte array.
public byte[] RotateImage(System.IO.Stream imageStream, string filePath)
{
int rotationDegrees = GetImageRotation(filePath)
byte[] byteArray = new byte[imageStream.Length];
try
{
imageStream.Read(byteArray, 0, (int)imageStream.Length);
Bitmap originalImage = BitmapFactory.DecodeByteArray(byteArray, 0, byteArray.Length);
Matrix matrix = new Matrix();
matrix.PostRotate((float)rotationDegrees);
Bitmap rotatedBitmap = Bitmap.CreateBitmap(originalImage, 0, 0, originalImage.Width,
originalImage.Height, matrix, true);
using (MemoryStream ms = new MemoryStream())
{
rotatedBitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, ms);
return ms.ToArray();
}
}
catch(Exception ex)
{
return byteArray;
}
}
Let me know if it worked or not.
来源:https://stackoverflow.com/questions/64278491/camera-capture-image-rotate-to-portrait-xamarin-android