为了账号安全,请及时绑定邮箱和手机立即绑定

Android Camera SurfaceView方向

Android Camera SurfaceView方向

catspeake 2019-12-16 10:45:56
Android Camera SurfaceView方向好的,所以我有一个扩展SurfaceView和重写的类surfaceChanged-仅调用startPreviewsurfaceCreated-打开相机,编辑参数*,设置surfaceHoldersurfaceDestroyed-调用stopPreview,释放相机这一切都很好,因为当方向是纵向时:从surfaceCreated *m_camera = Camera.open();Camera.Parameters p = m_camera.getParameters();if (getResources().getConfiguration().orientation !=     Configuration.ORIENTATION_LANDSCAPE){    p.set("orientation", "portrait");    // CameraApi is a wrapper to check for backwards compatibility      if (CameraApi.isSetRotationSupported())    {         CameraApi.setRotation(p, 90);    }}但是,每次方向更改时,它都会调用Camera.open()...,您可能知道这是一项非常昂贵的操作,从而导致过渡不那么平滑。当我将方向强制为横向时,预览效果很好。仅调用一次Create就可以,因为预览是横向的,相机始终是用户看到的东西,因此可以调用。但是,我需要一种方法来设置肖像拍摄时实际照片的方向。但是,当我强制使用风景时,将相机纵向放置时,永远不会重新创建表面,也永远不会设置参数。那么,如何执行以下一项(排他性的)?方向更改时,在onDestroy和onCreate之间保留m_camera,以使过渡平滑强制横向移动并检测方向变化的另一种方式...如果纵向旋转,则旋转最终拍摄的照片。另外,如果我不在基地,有人可以指出我的方向吗?谢谢。
查看完整描述

3 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

我的实现方式:


private Camera mCamera;

private OrientationEventListener mOrientationEventListener;

private int mOrientation =  -1;


private static final int ORIENTATION_PORTRAIT_NORMAL =  1;

private static final int ORIENTATION_PORTRAIT_INVERTED =  2;

private static final int ORIENTATION_LANDSCAPE_NORMAL =  3;

private static final int ORIENTATION_LANDSCAPE_INVERTED =  4;


@Override

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    // force Landscape layout

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR | ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

   /*

   Your other initialization code here

   */

}


@Override 

protected void onResume() {

    super.onResume();


    if (mOrientationEventListener == null) {            

        mOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {


            @Override

            public void onOrientationChanged(int orientation) {


                // determine our orientation based on sensor response

                int lastOrientation = mOrientation;


                if (orientation >= 315 || orientation < 45) {

                    if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          

                        mOrientation = ORIENTATION_PORTRAIT_NORMAL;

                    }

                }

                else if (orientation < 315 && orientation >= 225) {

                    if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {

                        mOrientation = ORIENTATION_LANDSCAPE_NORMAL;

                    }                       

                }

                else if (orientation < 225 && orientation >= 135) {

                    if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {

                        mOrientation = ORIENTATION_PORTRAIT_INVERTED;

                    }                       

                }

                else { // orientation <135 && orientation > 45

                    if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {

                        mOrientation = ORIENTATION_LANDSCAPE_INVERTED;

                    }                       

                }   


                if (lastOrientation != mOrientation) {

                    changeRotation(mOrientation, lastOrientation);

                }

            }

        };

    }

    if (mOrientationEventListener.canDetectOrientation()) {

        mOrientationEventListener.enable();

    }

}


@Override protected void onPause() {

    super.onPause();

    mOrientationEventListener.disable();

}


/**

 * Performs required action to accommodate new orientation

 * @param orientation

 * @param lastOrientation

 */

private void changeRotation(int orientation, int lastOrientation) {

    switch (orientation) {

        case ORIENTATION_PORTRAIT_NORMAL:

            mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 270));

            mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 270));

            Log.v("CameraActivity", "Orientation = 90");

            break;

        case ORIENTATION_LANDSCAPE_NORMAL:

            mSnapButton.setImageResource(android.R.drawable.ic_menu_camera);

            mBackButton.setImageResource(android.R.drawable.ic_menu_revert);

            Log.v("CameraActivity", "Orientation = 0");

            break;

        case ORIENTATION_PORTRAIT_INVERTED:

            mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 90));

            mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 90));

            Log.v("CameraActivity", "Orientation = 270");

            break;

        case ORIENTATION_LANDSCAPE_INVERTED:

            mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 180));

            mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 180));      

            Log.v("CameraActivity", "Orientation = 180");

            break;

    }

}


    /**

 * Rotates given Drawable

 * @param drawableId    Drawable Id to rotate

 * @param degrees       Rotate drawable by Degrees

 * @return              Rotated Drawable

 */

private Drawable getRotatedImage(int drawableId, int degrees) {

    Bitmap original = BitmapFactory.decodeResource(getResources(), drawableId);

    Matrix matrix = new Matrix();

    matrix.postRotate(degrees);


    Bitmap rotated = Bitmap.createBitmap(original, 0, 0, original.getWidth(), original.getHeight(), matrix, true);

    return new BitmapDrawable(rotated);

}

然后在PictureCallback中设置元数据以指示旋转级别:


    private Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() {


    @Override

    public void onPictureTaken(byte[] data, Camera camera) {

        try {

            // Populate image metadata


            ContentValues image = new ContentValues();

            // additional picture metadata

            image.put(Media.DISPLAY_NAME, [picture name]);

            image.put(Media.MIME_TYPE, "image/jpg");

            image.put(Media.TITLE, [picture title]);

            image.put(Media.DESCRIPTION, [picture description]);

            image.put(Media.DATE_ADDED, [some time]);

            image.put(Media.DATE_TAKEN, [some time]);

            image.put(Media.DATE_MODIFIED, [some time]);


            // do not rotate image, just put rotation info in

            switch (mOrientation) {

                case ORIENTATION_PORTRAIT_NORMAL:

                    image.put(Media.ORIENTATION, 90);

                    break;

                case ORIENTATION_LANDSCAPE_NORMAL:

                    image.put(Media.ORIENTATION, 0);

                    break;

                case ORIENTATION_PORTRAIT_INVERTED:

                    image.put(Media.ORIENTATION, 270);

                    break;

                case ORIENTATION_LANDSCAPE_INVERTED:

                    image.put(Media.ORIENTATION, 180);

                    break;

            }


            // store the picture

            Uri uri = getContentResolver().insert(

                    Media.EXTERNAL_CONTENT_URI, image);


            try {

                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,

                        data.length);

                OutputStream out = getContentResolver().openOutputStream(

                        uri);

                boolean success = bitmap.compress(

                        Bitmap.CompressFormat.JPEG, 75, out);

                out.close();

                if (!success) {

                    finish(); // image output failed without any error,

                                // silently finish

                }


            } catch (Exception e) {

                e.printStackTrace();

                // handle exceptions

            }


            mResultIntent = new Intent();

            mResultIntent.setData(uri);

        } catch (Exception e) {

            e.printStackTrace();

        }


        finish();

    }

};

希望对您有所帮助。


更新现在,当基于景观的设备出现时,在OrientationEventListener中需要对其进行附加检查。


Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();                                        

if (display.getOrientation() == Surface.ROTATION_0) { 

    // landscape oriented devices

} else { 

    // portrait oriented device

}

完整代码(LC有点浪费,但可以轻松演示该方法)


@Override

public void onOrientationChanged(int orientation) {


    // determine our orientation based on sensor response

    int lastOrientation = mOrientation;


    Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();                                        


    if (display.getOrientation() == Surface.ROTATION_0) {   // landscape oriented devices

        if (orientation >= 315 || orientation < 45) {

            if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {                         

                mOrientation = ORIENTATION_LANDSCAPE_NORMAL;

            }

        } else if (orientation < 315 && orientation >= 225) {

            if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {

                mOrientation = ORIENTATION_PORTRAIT_INVERTED;

            }                       

        } else if (orientation < 225 && orientation >= 135) {

            if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {

                mOrientation = ORIENTATION_LANDSCAPE_INVERTED;

            }                       

        } else if (orientation <135 && orientation > 45) { 

            if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {

                mOrientation = ORIENTATION_PORTRAIT_NORMAL;

            }                       

        }                       

    } else {  // portrait oriented devices

        if (orientation >= 315 || orientation < 45) {

            if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          

                mOrientation = ORIENTATION_PORTRAIT_NORMAL;

            }

        } else if (orientation < 315 && orientation >= 225) {

            if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {

                mOrientation = ORIENTATION_LANDSCAPE_NORMAL;

            }                       

        } else if (orientation < 225 && orientation >= 135) {

            if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {

                mOrientation = ORIENTATION_PORTRAIT_INVERTED;

            }                       

        } else if (orientation <135 && orientation > 45) { 

            if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {

                mOrientation = ORIENTATION_LANDSCAPE_INVERTED;

            }                       

        }

    }


    if (lastOrientation != mOrientation) {

        changeRotation(mOrientation, lastOrientation);

    }

}


查看完整回答
反对 回复 2019-12-16
  • 3 回答
  • 0 关注
  • 1158 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信