Camera2预览和捕获的图像看起来有所不同

问题描述

认情况下,我捕获到的图像旋转了-90度,我需要将其旋转回去,但是其高度与屏幕的高度不同,所以我的图像不会充满屏幕。

拍照后在横向模式下,它仅显示捕获的图像的右上角。

我尝试了所有可用的示例,但是找不到解决方案。

private void SetUpCameraOutputs(int width,int height)
{
    _manager = (CameraManager)_context.GetSystemService(Context.CameraService);

    string[] cameraIds = _manager.GetCameraIdList();

    _cameraId = cameraIds[0];

    Cameracharacteristics chararc = _manager.GetCameracharacteristics(cameraIds[i])
    var characteristics = _manager.GetCameracharacteristics(_cameraId);
    var map = (StreamConfigurationMap)characteristics.Get(Cameracharacteristics.ScalerStreamConfigurationMap);

    if (_supportedJpegSizes == null && characteristics != null){
        _supportedJpegSizes = ((StreamConfigurationMap)characteristics.Get(Cameracharacteristics.ScalerStreamConfigurationMap)).GetoutputSizes((int)ImageFormatType.Jpeg);
    }

    if (_supportedJpegSizes != null && _supportedJpegSizes.Length > 0){
        _idealPhotoSize = GetoptimalSize(_supportedJpegSizes,1050,1400); 
    }

    _imageReader = ImageReader.NewInstance(_idealPhotoSize.Width,_idealPhotoSize.Height,ImageFormatType.Jpeg,1);

    var readerListener = new ImageAvailableListener();

    readerListener.Photo += (sender,buffer) =>
    {
        Photo?.Invoke(this,buffer);
    };

    _flashSupported = HasFLash(characteristics);

    _imageReader.SetonImageAvailableListener(readerListener,_backgroundHandler);
        
    _previewSize = GetoptimalSize(map.GetoutputSizes(Class.FromType(typeof(SurfaceTexture))),_idealPhotoSize.Width);
}

TakePhoto方法

public void TakePhoto()
{
    if (_context == null || CameraDevice == null) return;

    if (_captureBuilder == null)
        _captureBuilder = CameraDevice.CreateCaptureRequest(CameraTemplate.StillCapture);

    _captureBuilder.AddTarget(_imageReader.Surface);

    _captureBuilder.Set(CaptureRequest.ControlAfMode,(int)ControlAFMode.ContinuousPicture);

    var windowManager = _context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
    var rotation = windowManager.Defaultdisplay.Rotation;
    _captureBuilder.Set(CaptureRequest.JpegOrientation,new Integer(Orientations.Get((int)rotation)));

    _previewSession.StopRepeating();
    _previewSession.Capture(_captureBuilder.Build(),new CameraCaptureStillPictureSessionCallback
        {
            OnCaptureCompletedAction = session =>
            {
                UnlockFocus();
            }
        },null);
}

还有我的OnPhoto方法

private void OnPhoto(object sender,byte[] imgSource)
{
    Android.Graphics.Bitmap bitmap = BitmapFactory.DecodeByteArray(imgSource,imgSource.Length);
    var windowManager = _context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
    var rotation = windowManager.Defaultdisplay.Rotation;
    if (rotation == SurfaceOrientation.Rotation0 || rotation == SurfaceOrientation.Rotation180)
    {
        bitmap = resizeAndRotate(bitmap,bitmap.Width,bitmap.Height); //rotate bitmap by 90
    }

    var SkBitmap = bitmap.ToSKBitmap();

    Application.Current.Properties["bitmap"] = SkBitmap;

    Device.BeginInvokeOnMainThread(() =>
    {
        _currentElement?.PictureTaken();
    });
}

解决方法

为纵向模式创建位图时,必须更改位图的宽度和高度。 这样宽度就变成了纵向图像,而高度变成了纵向图像的宽度。


int newWidth = oldHeight;
int newHeight = oldWidth;

Bitmap newBitmap  =Bitmap.createScaledBitmap(oldbitmap,newWidth,newHeight,true);

您现在已经完成了newBitmap的真实显示而无需拉伸。

根据您的代码,只需使用以下命令即可还原位图的宽度和高度:

bitmap = resizeAndRotate(bitmap,bitmap.height,bitmap.width);