android摄像头表面视图方向
好的,我有一个扩展SurfaceView和重写的类 surfaceChanged-仅调用StartViewandroid摄像头表面视图方向,android,orientation,smartphone,android-sdk-2.1,android-camera,Android,Orientation,Smartphone,Android Sdk 2.1,Android Camera,好的,我有一个扩展SurfaceView和重写的类 surfaceChanged-仅调用StartView surfaceCreated-打开相机,编辑参数*,设置surfaceHolder SurfacedStroked-查看、释放摄像头 这一切都非常有效,因为当方向为纵向时: 从表面处理* m_camera = Camera.open(); Camera.Parameters p = m_camera.getParameters(); if (getResources().getConfi
surfaceCreated-打开相机,编辑参数*,设置surfaceHolder
SurfacedStroked-查看、释放摄像头 这一切都非常有效,因为当方向为纵向时: 从表面处理*
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只会被调用一次,因为预览是横向的,相机总是用户看到的。但是,我需要一种方法来设置在肖像中拍摄的实际照片的方向。当我强制横向时,当相机保持纵向时,曲面永远不会被重新创建,参数也永远不会设置
那么,我如何才能(独家)执行以下操作之一
另外,如果我不在基地,有人能给我指出一个更好的方向吗?谢谢。我实施它的方式:
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);
}
我希望有帮助
更新现在,当基于横向的设备出现时,需要在DirectionEventListener中进行额外检查
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getOrientation() == Surface.ROTATION_0) {
// landscape oriented devices
} else {
// portrait oriented device
}
完整代码(LC有点浪费,但很容易演示该方法)
@覆盖
公共无效onOrientationChanged(int方向){
//根据传感器响应确定我们的方向
int lastOrientation=Morentation;
显示=((WindowManager)getSystemService(窗口服务)).getDefaultDisplay();
如果(display.getOrientation()==Surface.ROTATION\u 0){//面向横向的设备
如果(方向>=315 | |方向<45){
如果(mOrientation!=方向\横向\法线){
mOrientation=方向\横向\正常;
}
}否则如果(方向<315和方向>=225){
如果(Morentation!=方向\u纵向\u倒置){
mOrientation=方向\纵向\倒置;
}
}否则如果(方向<225&&orientation>=135){
如果(Morentation!=方向\横向\倒置){
mOrientation=方向\横向\倒置;
}
}如果(方向45){
if(Morentation!=方向\纵向\正常){
mOrientation=方向\纵向\法线;
}
}
}else{//面向肖像的设备
如果(方向>=315 | |方向<45){
如果(mOrientation!=方向\纵向\法线){
mOrientation=方向\纵向\法线;
}
}否则如果(方向<315和方向>=225){
if(Morentation!=方向\横向\正常){
mOrientation=方向\横向\正常;
}
}否则如果(方向<225&&orientation>=135){
如果(Morentation!=方向\u纵向\u倒置){
mOrientation=方向\纵向\倒置;
}
}如果(方向45){
如果(Morentation!=方向\横向\倒置){
mOrientation=方向\横向\倒置;
}
}
}
if(lastOrientation!=mOrientation){
改变旋转(晨昏,最后方向);
}
}
您是否考虑过使用API文档中提供的标准方法,您可以在surfaceChanged上调用该方法?您可以将度数存储在全局变量中,以便以后保存图片时使用。还可以对摄影机变量执行简单的null检查,这样您就不会在surfaceCreated中再次创建它
public void setCameraDisplayOrientation()
{
if (mCamera == null)
{
Log.d(TAG,"setCameraDisplayOrientation - camera null");
return;
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(CAM_ID, info);
WindowManager winManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
int rotation = winManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation)
{
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(result);
}
正如你从其他答案中看到的,这个代码变得非常复杂。您可能希望研究使用库来帮助您提供此功能,例如,CWAC Camera支持OS 2.3及以上版本(希望您现在可以放弃OS 2.1和OS 2.2支持):
CWAC Camera支持将相机预览锁定为横向,并将自动将图像旋转到校正方向。如果您想了解所有需要解决的特定于设备的问题,请浏览。这是尝试使用库而不是维护所有这些代码并进行自我测试的更多原因。+1我对此也很感兴趣。默认的谷歌相机应用程序可以很好地执行这一操作:它不会重新创建活动,但按钮和最后的图像预览会很好地旋转以匹配横向/纵向方向。顺便说一句,在我的理解中,p.set(“方向”,“肖像”)是一种隐藏的API用法,并且没有得到官方的支持,不是吗?我认为它实际上没有任何作用,哈哈。我首选的方法是强制横向。问题是我需要以另一种方式检测方向,因为这样摄影机活动就不会被重新创建。啊,我明白你的想法了。所以你会强迫相机活动到一个横向,然后根据实际方向,旋转一张图片,对吗?我可以帮你。这不是一个坏主意,我可能自己去实现它(-)。我最终使用了默认的摄影机活动,但是这看起来很好,我可能会在其他时间再讨论。谢谢。欢迎。老实说,我实现了我自己的摄影机活动,因为与默认摄影机活动不一致
@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);
}
}
public void setCameraDisplayOrientation()
{
if (mCamera == null)
{
Log.d(TAG,"setCameraDisplayOrientation - camera null");
return;
}
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(CAM_ID, info);
WindowManager winManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
int rotation = winManager.getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation)
{
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(result);
}