Портретный режим в CameraView

Я собираюсь разработать приложение для Android с использованием BeyondAR Framework. Я пытаюсь использовать компонент CameraView в первой половине экрана (приложение работает только в портретном режиме), но когда я поворачиваю камеру, изображение на 90 градусов растягивается, а соотношение сторон неправильное.

Класс CameraView (Beyondar Framework)

public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
    Camera.PictureCallback {

/**
 * 
 * @author Joan Puig Sanz (joanpuigsanz@gmail.com)
 * 
 */
public static interface IPictureCallback {
    /**
     * This method is called when the snapshot of the camera is ready. If
     * there is an error, the image will be null
     * 
     * @param picture
     */
    void onPictureTaken(Bitmap picture);
}

private SurfaceHolder mHolder;
private Camera mCamera;
private IPictureCallback mCameraCallback;
private BitmapFactory.Options mOptions;

private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private List<String> mSupportedFlashModes;

public CameraView(Context context) {
    super(context);
    init(context);
}

public CameraView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

public CameraView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

private void init(Context context) {
    mHolder = getHolder();
    mHolder.addCallback(this);

    try {
        mCamera = Camera.open();
        //mCamera.setDisplayOrientation(90);


        //Camera.Parameters params = mCamera.getParameters();
        //params.setPreviewSize(427, 1240); 
        //mCamera.setParameters(params);
        setCamera(mCamera);
    } catch (Exception e) {
        Log.e(Constants.TAG, "ERROR: Unable to open the camera", e);
    }

    if (android.os.Build.VERSION.SDK_INT <= 10) {// Android 2.3.x or lower
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
}

public void setCamera(Camera camera) {
    mCamera = camera;
    if (mCamera != null) {
        mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
        mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
        // Set the camera to Auto Flash mode.
        if (mSupportedFlashModes != null
                && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)) {
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
            //parameters.setPreviewSize(300, 200);
            mCamera.setParameters(parameters);
        }
    }
}

public void setSupportedPreviewSizes(List<Size> supportedPreviewSizes) {
    mSupportedPreviewSizes = supportedPreviewSizes;
}

public Size getPreviewSize() {
    return mPreviewSize;
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    try {

        if (mCamera == null) {
            init(getContext());
            if (mCamera == null) {
                return;
            }
        }

        mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        if (mCamera != null) {
            mCamera.release();
        }
        mCamera = null;
        Log.e(Constants.TAG, "CameraView -- ERROR en SurfaceCreated", exception);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    // Because the CameraDevice object is not a shared resource, it's very
    // important to release it when the activity is paused.
    if (mCamera == null) {
        return;
    }
    mCamera.stopPreview();
    mCamera.release();
    mCamera = null;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
    }

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

private Size getOptimalPreviewSize(List<Size> sizes, int width, int height) {

    Size result = null;

    for (Camera.Size size : 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 void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if (mCamera == null || getPreviewSize() == null) {
        return;
    }

    Camera.Parameters parameters = mCamera.getParameters();
    Size previewSize = getPreviewSize();
    parameters.setPreviewSize(previewSize.width, previewSize.height);

    mCamera.setParameters(parameters);
    previewCamera();

}

@Override
public void onPictureTaken(byte[] imageData, Camera camera) {
    if (imageData != null && mCameraCallback != null) {
        mCameraCallback.onPictureTaken(StoreByteImage(imageData));
    }
    previewCamera();
}

public void previewCamera() {
    if (mCamera == null){
        return;
    }
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        Log.d(Constants.TAG, "Cannot start preview.", e);
    }
}

private Bitmap StoreByteImage(byte[] imageData) {

    Bitmap myImage = DebugBitmap.decodeByteArray(imageData, 0, imageData.length, mOptions);

    imageData = null;
    System.gc();

    return myImage;
}

public void tackePicture(IPictureCallback cameraCallback) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    tackePicture(cameraCallback, options);
}

public void tackePicture(IPictureCallback cameraCallback, BitmapFactory.Options options) {
    if (mCamera == null) {
        return;
    }
    mCameraCallback = cameraCallback;
    mCamera.takePicture(null, this, this);
    mOptions = options;
}


}

редактировать

MyLayout XML-файл

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0dip"
    android:layout_weight="1"
    android:orientation="horizontal"
    android:paddingBottom="@dimen/padding"
    android:paddingLeft="@dimen/padding"
    android:paddingRight="@dimen/padding"
    android:paddingTop="@dimen/padding" >  

    <FrameLayout 
   android:orientation="vertical"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   >
    <com.beyondar.android.opengl.views.BeyondarGLSurfaceView
    android:id="@+id/customGLSurface"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" />    
    <com.beyondar.android.views.CameraView 
    android:id="@+id/camera"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" />

<TextView  
    android:id="@+id/labelText"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Touch an AR Object"
    android:background="#000000"
    android:textColor="#FFFFFF"
    />


    </FrameLayout>
   </LinearLayout

2 ответа

Если вы посмотрите на пример приложения для BeyondAR, вы увидите, что у него есть похожая проблема в том, что изображение с камеры растягивается, чтобы заполнить экран, и поэтому не имеет правильного соотношения сторон в обоих пейзажах в портретной ориентации. Это распространенная проблема при работе с предварительным просмотром камеры, поскольку при первом запуске она фиксируется в определенной ориентации.

Чтобы получить это, вам нужно изменить размер изображения при вращении до соотношения сторон, которое соответствует камере устройства. Вот официальное руководство по Android.

Обратите внимание на деталь, которая называется "Установить ориентацию предварительного просмотра".

BeyondAR был обновлен, теперь это стало проще благодаря фрагментам. Проверьте веб-страницу и обновите свою библиотеку:

https://github.com/BeyondAR/beyondar

Другие вопросы по тегам